Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixing programmatic and declarative transactions in legacy software

My question concerns about possible concurrency issues with mixing programmatic and declarative transactions. I am developing a legacy software (Spring + Hibernate) that handles database connections and transactions in a programmatic fashion.

Session db = HibernateUtil.getSessionFactory().openSession();
db.beginTransaction();
// do stuff
db.getTransaction().commit();

The software has newer modules that are using Spring data architecture with declarative transactions (@Transactional). We have experienced database deadlocks in rare cases with Microsoft SQL Server when newer Spring services are being called from inside "manually" opened transactions. I think the problem is that there are two nested transactions reading/writing same tables causing deadlocks.

Session db = HibernateUtil.getSessionFactory().openSession();
db.beginTransaction();
// do stuff
springService.getStuff();
// do stuff
db.getTransaction().commit();

Is there a way to mix these transactions safely or use the already started transaction in both? Should I just close the manually/programmatically opened transaction before calling Spring @Service/@Repository methods? Both Spring and HibernateUtil uses the same entity manager for database connections.

like image 762
anssias Avatar asked Feb 11 '16 14:02

anssias


People also ask

What is programmatic and declarative transaction management?

Programmatic transaction management − This means that you have to manage the transaction with the help of programming. That gives you extreme flexibility, but it is difficult to maintain. Declarative transaction management − This means you separate transaction management from the business code.

Why is declarative transaction management more efficient than programmatic transaction?

Being able to set the transaction name explicitly is also something that can only be done using the programmatic approach to transaction management. On the other hand, if your application has numerous transactional operations, declarative transaction management is usually worthwhile.

Which of the following method is used to start a transaction in programmatic transaction management in hibernate?

Once the TransactionDefinition is created, you can start your transaction by calling getTransaction() method, which returns an instance of TransactionStatus.

Is ChainedTransactionManager deprecated?

ChainedTransactionManager (Deprecated) ChainedTransactionManager is a way of declaring multiple data sources, in which, in the case of exception, rollbacks will occur in the reverse order.


1 Answers

When it comes to the behavior of the transactions, there is really no difference between declarative and programmatic/manual ones. Declarative transactions enable you to demarcate transaction boundaries in a more concise and readable way, that's all about it. Under the hood, Spring will do the same thing you would do manually to start and commit/rollback transactions.

I think the problem is that there are two nested transactions reading/writing same tables causing deadlocks.

Very possible.

Is there a way to mix these transactions safely or use the already started transaction in both?

Whether it is safe to do it in your specific part code highly depends on what the code does. If a nested transaction will cause deadlock, then it's obviously not safe, and that has nothing to do how you obtained the nested transaction (manually or Spring started it when intercepting a method annotated with @Transactional(propagation = Propagation.PROPAGATION_REQUIRES_NEW)).

Should I just close the manually/programmatically opened transaction before calling Spring @Service/@Repository methods?

Again, depends of what you need to solve. If you need the outer transaction to proceed once the nested transaction completes, then you shouldn't. Otherwise you can.

TransactionTemplate is the recommended way to manually start transactions with Spring, because Spring is then aware of transaction boundaries, meaning it will treat such a transaction the same as if it were started declaratively with a Spring annotation.

like image 74
Dragan Bozanovic Avatar answered Nov 16 '22 01:11

Dragan Bozanovic