-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 posts ] 
Author Message
 Post subject: Feature or Bug?
PostPosted: Wed May 03, 2006 11:28 am 
Beginner
Beginner

Joined: Tue Jun 07, 2005 8:24 am
Posts: 33
Location: Cincinnati, OH
When using generated keys, Hibernate will set the identity propery even if the enclosing transaction is rolled back. This can cause some nasty side effects when you go to saveOrUpdate() that object again, since Hibernate will think it's persistent when it's really not. I understand that Hibernate doesn't rollback entity object state to what it was at the beginning of the transaction. I can expect that for values that I change. What I do not expect is that Hibernate will make my object look persistent when it's not when I'm using generated keys. It seems that it should either rollback the identity value or just not set it until the transaction is committed and we know the data is in the database.

Code:
final Foo foo = new Foo();
foo.setName( "Hello, Foo!" );
final SessionFactory sf = getSessionFactory();
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
session.save( foo );
tx.rollback();
session.close();
session = sf.openSession();
tx = session.beginTransaction();
session.saveOrUpdate( foo );
tx.commit(); // Exception here!
session.close();
sf.close();


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 03, 2006 10:58 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
That's why newer hibernates use "y = session.merge(x);". The object passed in as a parameter isn't updated by merge, so you can continue to use it in case of rollback. If the commit works, you use y, which is the persistant version of x.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject: Re: Feature or Bug?
PostPosted: Thu May 04, 2006 6:44 am 
Beginner
Beginner

Joined: Tue Jun 07, 2005 8:24 am
Posts: 33
Location: Cincinnati, OH
So, I'm supposed to keep x and y around until after the transaction commits? That's quite a burden to place on all of the pages/components (I'm using Tapestry) in my webapp. How am I supposed to inform them that the transaction has committed and to switch out their x's for their y's?


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 04, 2006 6:51 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
That depends on what version of hibernate you're using. If your version has session.merge, you could use that: don't record the return value, and query by example on the initial parameter (x in above example) after the transaction commits. Querying by example on a fully-populated object with not id should return the persistent version of that object. Something like:
Code:
try
{
  sess.beginTransaction();
  y = session.merge(x);
  sess.commitTransaction();
}
catch (HibernateException e)
{
  sess.rollbackTransaction();
  y = x;
}
x = y;
// Now both y and x are correct: if the transaction was
// successful, they're both the persistent version;
// if the transaction was rolled back, they're both the
// original version with no id.

It must be said that by and large, this problem doesn't come up often because objects involved in a rolled back transaction are usually discarded. At best, they're used to re-populate a form, then discarded. So having a generated id in them isn't a factor. Can you change to working that way?

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject: Re: Feature or Bug?
PostPosted: Thu May 04, 2006 9:03 pm 
Beginner
Beginner

Joined: Tue Jun 07, 2005 8:24 am
Posts: 33
Location: Cincinnati, OH
I am using a TransactionPerRequestFilter, so it can't really talk to all the classes that did work during the course of the transaction.


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 04, 2006 11:21 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 7:19 pm
Posts: 2364
Location: Brisbane, Australia
Depending on the ID generation policy selected, its a fact that the process runs outside of the transaction. It is well known that a sequence, for example in Oracle, is atomic and is not rewound if a rollback occurs. The same applies to the assignment of the Id when using a Sequnce generation policy. So its consistent with database behaviour. I guess the biggest issue is that its something you tend to discover with use rather than pick this up as a matter of reading a manual or tutorial. The solution is not to use the ID's presence as an indication of a successful save operation.


Top
 Profile  
 
 Post subject: Re: Feature or Bug?
PostPosted: Thu May 04, 2006 11:32 pm 
Beginner
Beginner

Joined: Tue Jun 07, 2005 8:24 am
Posts: 33
Location: Cincinnati, OH
But, I'm not the one using the id to indicate that the object is persisted. Hibernate is. If I want to reuse that object, after a transaction rollback, I'll get an exception from Hibernate because it thinks that the object is a persistent object (since it has an id). And, hibernate caused that object to have an id (which makes it think that it's persistent).


Top
 Profile  
 
 Post subject: Re: Feature or Bug?
PostPosted: Thu Nov 08, 2007 5:49 pm 
Newbie

Joined: Tue Nov 06, 2007 4:33 pm
Posts: 2
Location: New York
I'm facing the exact same issue. In my scenario my application contains a status object. I set the status to 'success' before committing. If a rollback occurs I want other objects to be rolled back but i want to update the status to 'failed' and re-commit it.
Hibernate tries an update() on saveOrUpdate() since the id value is not an unsaved-value. But the object was never committed :=(
jwcarman wrote:
But, I'm not the one using the id to indicate that the object is persisted. Hibernate is. If I want to reuse that object, after a transaction rollback, I'll get an exception from Hibernate because it thinks that the object is a persistent object (since it has an id). And, hibernate caused that object to have an id (which makes it think that it's persistent).


Top
 Profile  
 
 Post subject: Re: Bug or Feature?
PostPosted: Thu Nov 08, 2007 5:54 pm 
Beginner
Beginner

Joined: Tue Jun 07, 2005 8:24 am
Posts: 33
Location: Cincinnati, OH
I fixed this problem (and others) by using a UUID for my id property. So, Hibernate isn't generating the id at all, I am. This also solves the hashCode/equals problem.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 08, 2007 6:00 pm 
Newbie

Joined: Tue Nov 06, 2007 4:33 pm
Posts: 2
Location: New York
Thanks. In our physical model we need to use a database sequence as the identifier. I suppose I could add a uuid as a surrogate and add another sequence column.
Hibernate's preferred method would be to create a fresh object and persist it. Shall try to follow that without getting involved in nasty rollback callbacks.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 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.