Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: How to persist entity with *manually* assigned id
PostPosted: Tue Feb 21, 2017 12:12 pm 
Beginner
Beginner

Joined: Tue Oct 20, 2009 6:28 am
Posts: 20
Hello,

I wonder how to persist an entity that has the id defined as autonumeric or sequence but that I want to persist with my own defined id.
Why?

Because I saved this database entity to disk ( made a json backup ). Cleared DB. And now I want to introduce already existent entities with some of them filtered out.

The problem is that:
[*][list=]persist or save seems to go same route and fails because entity is not managed[/list]
[*][list=]merge does create an id that's different than the one I want to persist[/list]

The former doesn't work, the latter creates problem on the database because JSON can have references to the same entity along the saved tree and each save will create a different entity. Something is wrong.

Sooo. Is there a properly way to do it?

Best regards,


Top
 Profile  
 
 Post subject: Re: How to persist entity with *manually* assigned id
PostPosted: Tue Feb 21, 2017 12:57 pm 
Beginner
Beginner

Joined: Tue Oct 20, 2009 6:28 am
Posts: 20
Reading Hibernate code found that when the merge is done, there's a piece of code that search for the id before creating a new one.

Code:
Serializable id = event.getRequestedId();
      if ( id == null ) {
         id = persister.getIdentifier( entity, source );
      }
      else {
         // check that entity id = requestedId
         Serializable entityId = persister.getIdentifier( entity, source );
         if ( !persister.getIdentifierType().isEqual( id, entityId, source.getFactory() ) ) {
            throw new HibernateException( "merge requested with id not matching id of passed entity" );
         }
      }


Unfortunately there's no way to set that requested id. The only function I found can do it is SaveOrUpdate:


Code:
   /**
    * Handle the given update event.
    *
    * @param event The update event to be handled.
    */
   public void onSaveOrUpdate(SaveOrUpdateEvent event) {
      final SessionImplementor source = event.getSession();
      final Object object = event.getObject();
      final Serializable requestedId = event.getRequestedId();

   [b]   if ( requestedId != null ) {
         //assign the requested id to the proxy, *beforeQuery*
         //reassociating the proxy
         if ( object instanceof HibernateProxy ) {
            ( (HibernateProxy) object ).getHibernateLazyInitializer().setIdentifier( requestedId );
         }
      }[/b]

      // For an uninitialized proxy, noop, don't even need to return an id, since it is never a save()
      if ( reassociateIfUninitializedProxy( object, source ) ) {
         LOG.trace( "Reassociated uninitialized proxy" );
      }
      else {
         //initialize properties of the event:
         final Object entity = source.getPersistenceContext().unproxyAndReassociate( object );
         event.setEntity( entity );
         event.setEntry( source.getPersistenceContext().getEntry( entity ) );
         //return the id in the event object
         event.setResultId( performSaveOrUpdate( event ) );
      }

}


But again it seems that the version of Hibernate + JPA we use doesn't support that method in the entityManager. So there's no way to do it.

Should we upgrade?


Top
 Profile  
 
 Post subject: Re: How to persist entity with *manually* assigned id
PostPosted: Thu Feb 23, 2017 4:02 pm 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1177
It's not that difficult. Check out this article which explains in great detail.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: How to persist entity with *manually* assigned id
PostPosted: Fri Feb 24, 2017 12:13 pm 
Beginner
Beginner

Joined: Tue Oct 20, 2009 6:28 am
Posts: 20
Hi Vlad,

Really this has nothing to do with the generator but the way Hibernate and JPA manages entities that are DETACHED.
To me it seems that there's a problem with that management.

What you posted in the article is really a dirty trick that modifies the way generators work to accept a parameter that's already inside the field and instead of generating the Id use the one already set.
While it's a great workaround I would implement. The solution is not hacking the generator. The solution is make hibernate behave as expected.

I opened an issue where it's tracked:

https://hibernate.atlassian.net/browse/HHH-11514

Mainly what JPA says with replicate action is:

Quote:

Persist the state of the given detached instance, reusing the current
identifier value. This operation cascades to associated instances if
the association is mapped with {@code cascade="replicate"}



But it's not doing it. What it does is generate a new Id ignoring what's inside the instance.

For me, or the javadoc is wrong or the implementation is wrong. As replicate only is used to store an instance in the DB as is. I think the implementation is wrong.
So I added a patch.

Hope it clarifies.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.