-->
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.  [ 6 posts ] 
Author Message
 Post subject: Transaction Patterns
PostPosted: Tue Jan 17, 2006 4:00 am 
Beginner
Beginner

Joined: Wed Nov 30, 2005 4:58 pm
Posts: 22
Location: Austin, TX
What do you see as the merits/faults of the following pattern?

Code:
Session sess = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
try {
  ... do some work A ...
  tx.commit();

  ... do some work B ...
  tx.commit()

  ... do some work C ...
  tx.commit();
} catch (HibernateException he) {
  if (tx != null) tx.rollback();
}


Is the above equivelant to the following, disregarding the difference that A, B, and C can commit/rollback independently of each other?

Code:
Session sess = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
try {
  ... do some work A ...
  tx.commit();
} catch (HibernateException he) {
  if (tx != null) tx.rollback();
}

tx = session.beginTransaction();
try {
  ... do some work B ...
  tx.commit();
} catch (HibernateException he) {
  if (tx != null) tx.rollback();
}

tx = session.beginTransaction();
try {
  ... do some work C ...
  tx.commit();
} catch (HibernateException he) {
  if (tx != null) tx.rollback();
}


In other words, does it matter whether I use the same transaction object throughout as opposed to getting a new transaction object for each block of work?

What about the following?

Code:
Session sess = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
try {
  ... do some work A ...
  tx.commit();
} catch (HibernateException he) {
  if (tx != null) tx.rollback();
}
sess.close();

sess = sessionFactory.openSession();
tx = session.beginTransaction();
try {
  ... do some work B ...
  tx.commit();
} catch (HibernateException he) {
  if (tx != null) tx.rollback();
}
sess.close();

sess = sessionFactory.openSession();
tx = session.beginTransaction();
try {
  ... do some work C ...
  tx.commit();
} catch (HibernateException he) {
  if (tx != null) tx.rollback();
}
sess.close();


Is there any advantage to having new sessions for each block of work rather than using the same session object throughout? I'm assuming the session object would be configured/managed the same way for each block of work.

Suppose that A and B do inserts and deletes, while C does a query where you expect the inserts and deletes to be factored into the results. Are any of the above patterns more or less suitable for that situation?

One more, a nested transaction.

Code:
Session sess = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
try {
  ... do some work A ...

  Transaction tx2 = session.beginTransaction();
  try {
    ... do some work B ...
    tx.commit()
  }  catch (HibernateException he) {
    if (tx != null) tx.rollback();
  }

  ... do some work C ...
  tx.commit();
} catch (HibernateException he) {
  if (tx != null) tx.rollback();
}


If B throws an exception and is rolled back, could A and C still commit? Or are tx and tx2 really using the same underlying DB transaction? If so, would I have to get a new session for the inner transaction like the following:

Code:
Session sess = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
try {
  ... do some work A ...

  Session sess2 = sessionFactory.openSession();
  Transaction tx2 = session.beginTransaction();
  try {
    ... do some work B ...
    tx.commit()
  }  catch (HibernateException he) {
    if (tx != null) tx.rollback();
  }
  sess2.close();

  ... do some work C ...
  tx.commit();
} catch (HibernateException he) {
  if (tx != null) tx.rollback();
}


Top
 Profile  
 
 Post subject: commit/rollback strategy
PostPosted: Wed Jan 18, 2006 1:49 pm 
Beginner
Beginner

Joined: Wed Nov 30, 2005 4:58 pm
Posts: 22
Location: Austin, TX
By the way, I prefer pattern A to B (below). With A, once the try block is entered, there is no way to prevent either a commit or rollback (short of killing the VM). This insures you will do one or the other.

With B, rollback depends on catching the right exception. If you are interested in only one kind of exception, that's fine. But what if an IOException or some other exception you haven't thought of is thrown? Or an Error of some kind? You will be forced to catch Throwable to cover them all or have multiple catch blocks for each possible exception with a rollback in each catch block. If you miss an exception type, you'll leave the transaction unresolved.

One disadvantage I see is when you want your error handling code in the catch block to write error messages of some sort to the DB. Since you're still in the transaction that will be rolled back, so will your error messages.

Any thoughts on this?

Pattern A
Code:
Transaction tx = session.beginTransaction();
boolean txSuccess = false;
try {
  ... do some work...
  txSuccess = true;
} catch (Whatever-exception-you-want e) {
.. whatever error handling code you want...
}
finally {
  if (tx != null) {
    if (txSuccess) {
      tx.commit();
    } else {
      tx.rollback():
    }
  }
}


Pattern B
Code:
try
{
  session.beginTransaction();
  .. do some work..
  tx.commit();
} catch (Whatever-exception-you-want e) {
.. whatever error handling code you want...
  tx.rollback();
}


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 18, 2006 7:48 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 7:19 pm
Posts: 2364
Location: Brisbane, Australia
See hibernate docs, even the API has details for this, eg,
http://www.hibernate.org/hib_docs/v3/api/

A typical transaction should use the following idiom:
Code:
Session sess = factory.openSession();
Transaction tx;
try {
     tx = sess.beginTransaction();
     //do some work
     ...
     tx.commit();
}
catch (Exception e) {
     if (tx!=null) tx.rollback();
     throw e;
}
finally {
     sess.close();
}


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 19, 2006 3:42 pm 
Beginner
Beginner

Joined: Wed Nov 30, 2005 4:58 pm
Posts: 22
Location: Austin, TX
Quote:
See hibernate docs, even the API has details for this, eg,
http://www.hibernate.org/hib_docs/v3/api/


That's a lot of docs. Can you be more specific?

I like that you put the beginTransaction() call inside the try block. But other than that, why is this idiom superior to commiting or rolling back in the finally block as I proposed?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 23, 2006 6:33 pm 
Newbie

Joined: Sun Feb 05, 2006 11:46 pm
Posts: 13
Shouldnt the rollback be in the finally before the session.close()?
Eg

Code:
finally {
   if(tx != null && tx.isActive())
      tx.rollback();
   session.close();
}


as apposed to

Code:
catch (Exception e) {
     if (tx!=null) tx.rollback();
     throw e;
}
finally {
     sess.close();
}

[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 23, 2006 10:57 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 7:19 pm
Posts: 2364
Location: Brisbane, Australia
Your code snippet always rolls back the transaction.


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