-->
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.  [ 7 posts ] 
Author Message
 Post subject: Failing to Rollback?
PostPosted: Sat Jul 03, 2004 6:32 pm 
Newbie

Joined: Thu Dec 18, 2003 12:30 am
Posts: 9
I'm using Hibernate 2.1 with MySQL with InnoDB tables (though I've seen the same behavior with Oracle 8.x). The problem I'm having is with transactions not rolling back. My Servlet Engine is Tomcat 4.

in hibernate.cfg.xml I've set:

Code:
<property name="hibernate.transaction.factory_class">
    net.sf.hibernate.transaction.JDBCTransactionFactory
</property>


My java code looks like:

Code:
try
{
    transaction = session.beginTransaction();
    session.saveOrUpdate(persistable);
    session.flush();
    transaction.commit();
}
catch (Throwable err)
{
    convertException(err);
}
finally
{
    if (null != transaction)
    {
        try
        {
            if (!transaction.wasCommitted())
            {
                transaction.rollback();
            }
        }
        catch (HibernateException err2)
        {
            getLog().error("Failed to rollback transaction!", err2);
        }
    }
}


I've stepped through the code, and when there is an error on the flush, I verify that rollback is being called. However, the data from associations is not getting rolled back. I am sure of this because I start my test with an empty DB.

I've tried taking the flush out, still no roll back.

If I add 'session.connection().setAutoCommit(false);' before the call to beginTransaction, I get very strange behavior. I step through the code, and my newly created object has it's id set inside the saveOrUpdate, but, on flush (or commit if I take the explicit flush out), I get an error saying that the object already exists. Huh? However, the rollback does work in this case.

How can I have both rollback capability and be able to saveUpdate newly created objects? I know this is wanting to have my cake and eat it to, but it is rather important ;)


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 03, 2004 7:08 pm 
Senior
Senior

Joined: Sun Jan 04, 2004 2:46 pm
Posts: 147
You're transaction logic looks a bit odd. I believe the standard(ish) pattern for exception handling is this...

Code:
Session session = null;
Transaction tx = null;

try
{
    session = factory.openSession();
    tx = session.beginTransaction();

    // do some db stuff here

    tx.commit();
}
catch ( HibernateException e )
{
    if ( tx != null )
    {
        try { tx.rollback(); } catch ( HibernateException e1 ) { // handle this }
        // handle exception e if need be ( rethrow )
    }
}
finally
{
    if ( session != null )
    {
        try { session.close(); } catch ( HibernateException e ) { // handle this }
    }
}


Try refactoring your code to see if this helps.


Top
 Profile  
 
 Post subject: Mine's just more robust is all
PostPosted: Sat Jul 03, 2004 8:07 pm 
Newbie

Joined: Thu Dec 18, 2003 12:30 am
Posts: 9
Thanks, but that's definitely not the problem here. My code isn't really any different, just more robust.

The differences are:

1) I catch Throwable as opposed to HibernateException. This ensures that I call my convertException (just some boilerplate error logging code that will rethrow an appropriate exception) even if a RuntimeException or Error occurs.

2) I put the rollback in the finally clause to make sure that it gets rolledback regardless of error condition. By placing the rollback in a catch (HibernateException) clause, there is danger of hanging transactions out to dry on any uncaught exception (RuntimeExceptions and Errors can be thrown regardless of what's declared).

3) Having the rollback in the finally clause forces me to check if the transaction was commited because, at that point, I don't know whether an exception/error was thrown.

You're right that the example you quote is the standard way you see that stuff written up in the documentation and tutorials. But, remember, those examples are trying to get illustrate a point and industrial error handling isn't a big concern. I would recommend you go through all your code and alter it to something similar to mine if you are doing anything for a production app.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 04, 2004 7:57 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
If you have only one method in application then this code must look like this:


Code:
Transaction transaction = session.beginTransaction();
try
{
   
    session.saveOrUpdate(persistable);
    transaction.commit();
}
catch (Throwable err)
{
    transaction.rollback();
}
finally

    session.close();
}


If you have more than one method or you are going to have more methods then your code must look like this:

Code:
session.saveOrUpdate(persistable);


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 04, 2004 3:09 pm 
Senior
Senior

Joined: Sun Jan 04, 2004 2:46 pm
Posts: 147
Two things I'd suggest. Put debug logging on in hibernate and post that, and that the autocommit mode, of your connection before you start a transaction tho that shouldn't matter as hibernate will set it to false regardless.


Top
 Profile  
 
 Post subject: why flush
PostPosted: Mon Jul 05, 2004 11:22 am 
Beginner
Beginner

Joined: Wed Feb 04, 2004 5:21 pm
Posts: 37
I don't understand why you are calling flush. I believe trx.commit() is sufficient, and that flush is only if you dont use a transaction.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 06, 2004 2:35 am 
Newbie

Joined: Thu Dec 18, 2003 12:30 am
Posts: 9
Thanks for the responses. I found the problem, and it wasn't the flush or commit. Turned out to be a problem due to the odd way I was forced to map the associations (see an earlier post). The error 's stack trace was just misleading. Fixed the problem by adding an artificial Entity to track an id, key and value.

baliukas, I really don't understand what you were trying to say. You might want to read what I posted just before your own post. What you recommend is only okay if you don't care about leaking transactions.

Myk, You win the golden suggestion award. I hadn't read it until afterwards, but, it was checking out the hibernate debug output that lead me to the problem.

hbendelbo, the flush might be redundant, but, it certainly doesn't hurt, and I've been burnt one too many times relying on code to do things like this implicitly.


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