When using Spring, probably the best way to add transaction management, you can still solve it even without re-factorizing your entire code base.
What you need to do is set up the following configuration:
hibernate.current_session_context_class=thread
You, DAO, must access the session through:
[SessionFactory.getCurrentSession()][1];
You still need to declare the boundaries of the transactions at the service level:
Session sess = factory.openSession(); Transaction tx = null; try { tx = sess.beginTransaction(); dao1.find(); dao2.save(entity); tx.commit(); } catch (RuntimeException e) { if (tx != null) tx.rollback(); throw e; } finally { sess.close(); }
Both dao1 and dao2 will use the same Hibernate session and the same transaction.
To avoid this complicated transaction management code processing, you can write a simple TransactionManager utility, for example:
pubic static abstract class TransactionCallable<T> { public abstract T execute(); } public class TransactionManager { pubic static <T> T doInTransaction(TransactionCallable<T> callable) { T result = null; Session session = null; Transaction txn = null; try { session = sf.openSession(); txn = session.beginTransaction(); result = callable.execute(); txn.commit(); } catch (RuntimeException e) { if ( txn != null && txn.isActive() ) txn.rollback(); throw e; } finally { if (session != null) { session.close(); } } return result; } }
And here is what the service looks like:
TransactionManager.doInTransaction(new TransactionCallable<Void>() { @Override public Void execute() { dao1.find(); dao2.save(entity); } });
Vlad Mihalcea
source share