Spring @Transactional
In this post we will look mainly into Spring transaction management. We will go over on how does @Transactional really works.
Generally Transactional is declared as:
UserTransaction utx = entityManager.getTransaction();
try {
utx.begin();
businessLogic();
utx.commit();
} catch(Exception ex) {
utx.rollback();
throw ex;
}
This way of managing transactions makes the scope of the transaction very clear in the code, but it has several disavantages:
- It's repetitive and error prone.
- Any error can have a very high impact
- Errors are hard to debug and reproduce
- This decreases the readability of the code base
- What if this method calls another transactional method?
Spring @Transactional is defined as:
@Transactional("transactionManager")
public void department() {
... use entity manager inside a transaction ...
}
This is much more convenient and readable, and the best recommended way to handle transactions in Spring.
By using @Transactional, transaction propagation are handled automatically. In this case if another transactional method is called by department(), that method will have the option of joining the ongoing transaction.
We are going to use multiple database transactions:
Because, in most frequent cases it is when the application is using the Open Session. In View pattern to deal with lazy initialization exceptions, In such case the queries that run in the view layer are in separate database transactions than the one used for the btrs, but they are made via the same entity manager.
For example:
@Transactional("transactionManager");
Alternatively, we can use the more explicit TransactionProxyFactoryBean, which gives finer-grained control over objects gets proxied by what tx managers. This still uses the annotations, but it doesn't auto-detect beans, I configured explicitly on a bean-by-bean basis.
It's not wise to have multiple transaction managers unless we have a very good reason to do so. If you find yourself needing two tx managers, it's usually better to see if you can do with one. For example, if you have two data sources configured in your app server, you can incorporate both in a single JtaTransactionManager, rather than two seperate JpaTransactionManager or DataSourceTransactionmanagers.