Spring JTATransactionManager fails to bind Hibernate and JDBC in a single session - java

I use JTATransactionManager to manage Transactions. One piece of code that I want to wrap with Spring's #Transactional annotation has 2 database calls - one using Hibernate SessionFactory and another a plain JDBC. Both use the same dataSource. Hence, I expect both to be bound by the same Transaction.
But it does not look like one Transaction is used. Instead each opens its own Transaction. What could be the reason for this. ? How do I make sure to use a single Transaction to bind both these operations. ?
I can provide configuration and code if needed.

Make sure in both of your database calls, you use propagation as Propagation.NESTED as
#Transactional(propagation=Propagation.NESTED)
and in the wrapper method, you mention Propagation.REQUIRED orPropagation.REQUIRED_NEW` as
#Transactional(propagation=Propagation.REQUIRED)
or
#Transactional(propagation=Propagation.REQUIRED_NEW)
By doing this, you mention that both DB calls will inherit the transaction boundary of the wrapper method.

Related

Example of Propagation in spring data JPA

I am trying to understand the propagation attribute of #Transactional annotation in Spring Data JPA. I have read enough theory. But I do not understand(nor can I find anywhere on internet) the real-life scenario where I need to use the PROPAGATION_REQUIRED in place of PROPAGATION_REQUIRES_NEW. I understand the theory that PROPAGATION_REQUIRED can utilize the existing transaction and PROPAGATION_REQUIRES_NEW will start a new transaction each time. But I could not understand two things -
How does it matter to me as a programmer? or in which used cases one is preferred over other?
Is the "TRANSACTION" we are talking about is a spring transaction or a database transaction
In Spring, if a method that is annotated with #Transactional calls another method annotated with #Transactional, the transaction is started at the beginning of the first method and commited after the second method is finished.
Requiring a new transaction can be helpful, if you have a sequence of methods that are transactional but you want to commit a transaction half way through the sequence.
Or maybe you have a method that should always open it's own transaction and you want to make sure it does so, even if it is called by another transactional method.

JTA for single database

I am just learning JTA and can't understand if I should use it if I have only one database. Currently I use hibernate 5 as JPA provider and if I need to use one transaction between methods I just pass EntityManager as argument.
However, I don't like this method as I need to remember if transaction is opened or not. I would like to find any library that will help me to control transactions (but without Spring) in SE environment. So, should I use JTA in my situation or should I use something different?
Normally when talking about JTA , it refers to the distributed transaction across multiple systems (e.g. across two databases , one database and one JMS compliant message broker). If you only have one database , it is not necessary to use JTA transaction although it should also work. Instead, use a local transaction for one database which should theoretically faster than using JTA transaction.
On the other hands , if you are just talking about #Transactional defined in the JTA , which allow you to declaratively control the transaction boundary by annotating it on a method and without passing the EntityManager between methods , you should look into which frameworks support it.
Under the cover , a proxied EntityManager is injected into different classes such that when it is invoked , it will get the actual EntityManager from the ThreadLocal. So every class in the same thread will get the same EntityManager which prevent you from passing the EntityManager around the methods. A new EntityManager instance will be set to the ThreadLocal just before the #Transactional method is executed using some sort of AOP technique.
Please note that #Transcational is nothing to do with the underlying transaction is JTA or local transaction. It should work for both transaction type.
I would use a framework that support #Transactional such as Spring , Quarkus or Micronaut etc , and configure Hibernate to use local transaction but not JTA transaction for single database.

Spring's JdbcTemplate and Transactions

When using JdbcTemplate, do I need to explicitly configure transactions?
My code layout looks like the following:
I will have a UserDao that will be injected into my UserService, and then my Controllers will make calls on methods in my UserService.
I want to keep things as simple as possible transaction wise, and I don't need multiple database calls to span a transaction.
By default, do I have to do anything in my configuration file or use a #Transaction annotation anywhere?
Now say in my controller I need to make 2 calls on my userService and accountService, could I explicitly wrap it in a transaction somehow?
userService.updateUser(user);
accountService.updateXXX(...);
Yes, JdbcTemplate is not a substitute for transaction management. You still benefit from database transactions, so userService.updateUser will operate in a database transaction, but if accountService.updateXXX fails, userService.updateUser will not rollback.
If you don't want to use AOP, you can use TransactionTemplate instead. See programmatic transaction management in the Spring Reference Documentation.
One pattern I've seen before is for the MVC controller class to invoke a business service, which encapsulates the operation. The method of the business class could then be annotated #Transactional.
If your controller wants to do several things with users and accounts and have all that happen within one transaction, then you should have a service with one method that does all that stuff. Creating one service per DAO is not a great idea, because you end up with do-nothing wrappers around DAOs and processing will be slow because the database will have to create a separate transaction for each call to a DAO, you're making it do a lot more work than it should have to.
The service should provide functionality to the controller or whoever else is calling it. I try to create services with the idea that the service provides specific functions useful to a certain type of user.

How can one explicitly commit a spring db transaction when using declarative transaction management?

I am using Spring declarative database transaction management using the #Transactional annotation on my java methods.
In one case, I would like to explicitly commit the current transaction (the one wrapping the currently executing method) prior to the method returning.
How can this be done?
I have tried auto wiring the current HibernateTransactionManager from the spring context and using that to commit, but it doesn't commit the transaction.
The code I have tried is:
transactionManager.commit(transactionManager
.getTransaction(new DefaultTransactionDefinition()));
i have not tried but you might be able to do this with some trick which i can think of
get TransactionStatus using TransactionAspectSupport.currentTransactionStatus()
inject transaction manager to your bean (assuming you are using hibernate)
try to invoke doCommit(DefaultTransactionStatus status) in transaction manager.
try this out not sure it will work or not because as per spring doc
transaction
You are strongly encouraged to use the declarative approach to
rollback if at all possible. Programmatic rollback is available should
you absolutely need it, but its usage flies in the face of achieving a
clean POJO-based architecture.
i have not tested but if you set setRollbackOnly to TransactionStatus that might also do the job.
The nested transaction, that being seeked above, can be achieved using REQUIRES_NEW propogation, BUT by taking care of self invocation, as explained here

On services and #Transactional

If I have a service class which calls three other service classes in a row, and each of those sub-services has to deal with a DAO object at some point, how can I make so that the wrapper service wraps them all into a single transaction? Will it be as simple as annotating the wrapper with #Transactional? What if the DAO is already marked as #Transactional?
The default transaction propagation in Spring framework is REQUIRED, which means that the transaction is created if it does not already exist or the code joins existing one:
Support a current transaction, create a new one if none exists. Analogous to EJB transaction attribute of the same name.
This is the default setting of a transaction annotation.
This means that if you wrap calls to three transactional methods in a single transactional method, they will all run within a single transaction. Just like that.
See also:
What is the right way to use spring MVC with Hibernate in DAO, sevice layer architecture
If you annotate the outer service as #Transactional and your DAOs are also #Transactional and called by the service they will by default join the outer transaction as you're hoping.
this is actually a question about nested transaction (http://en.wikipedia.org/wiki/Nested_transaction). with spring, (assume you are using version 3 and annotation), REQUIRED is default for transaction mode. If you set this model for your service methods, all methods wrapped by your "wrapper" service will use the host transaction, which means they will run in same transaction.

Categories