Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling Hibernate Transactions

Currently I have this code duplicated in each one of my Controller methods:

Transaction transaction = HibernateUtil.getSessionFactory().getCurrentSession().getTransaction();
if (!HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().isActive()) {
    transaction.begin();
}

Is this the correct way or is there a better way of doing this, perhaps in a separate class that I can reference? If so, how? Every time I've tried to put it in a separate class and reference it from other classes, it failed.

edit: I'm trying to use as few external libraries as possible. I wouldn't use Hibernate if Java had an ORM/JPA implementation built into the JDK

like image 822
ThreaT Avatar asked Jan 09 '14 15:01

ThreaT


People also ask

How are transactions handled in Hibernate?

Transaction Interface in Hibernate In hibernate framework, we have Transaction interface that defines the unit of work. It maintains abstraction from the transaction implementation (JTA,JDBC). A transaction is associated with Session and instantiated by calling session.

How Hibernate handle multiple transactions?

Therefore, you can run multiple transactions on the same Hibernate Session, but there's a catch. Once an exception is thrown you can no longer reuse that Session. My advice is to divide-and-conquer. Just split all items, construct a Command object for each of those and send them to an ExecutorService#invokeAll .

Does Hibernate provide transaction management?

The key to successful Hibernate transaction management is the JPA EntityManager. It's the only JPA component that can start transactions, commit transactions and hook into Hibernate transactions that are already in progress.

Do we need to close transaction in Hibernate?

In Hibernate, the transaction management is quite standard, just remember any exceptions thrown by Hibernate are FATAL, you have to roll back the transaction and close the current session immediately.


1 Answers

I've run into this myself many times. Ordinarily my first recommendation would be Spring transaction management, however I understand you are trying to limit the number of third party libraries you are using.

Since you're using a static API in your HibernateUtil class, you may find it helpful to consolidate your logic in a method, and putting the 'what you want to do in a transaction' code (which varies controller to controller) in a callback.

First, define an interface to describe each controller's inTransaction behavior:

public interface TransactionCallback {
    void doInTransaction();
}

Now, create a static method in your HibernateUtil class to handle beginning, committing, and if necessary rolling back your transactions:

public class HibernateUtil {
    public static void inTransaction(TransactionCallback tc) {
        Transaction transaction = HibernateUtil.getSessionFactory().getCurrentSession().getTransaction();
        if (!HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().isActive()) {
            transaction.begin();
            try {
                tc.doInTransaction();
                transaction.commit();
            } catch (Exception e) {
                transaction.rollback();
            }
        }
    }
}

In your controller, you'd use your new method with an anonymous inner class:

....
    HibernateUtil.inTransaction(new TransactionCallback() {
        void doInTransaction() {
            // do stuff for this controller
        }
    });
....

This approach should at least take care of the duplication you'd like to eliminate, and there's plenty of room for extending it to handle particular exceptions, etc.

like image 76
Peter Bratton Avatar answered Oct 02 '22 01:10

Peter Bratton