javax.transaction.Transactional vs org.springframework.transaction.annotation.Transactional
JavaSpringHibernateTransactionsJtaJava Problem Overview
I don't understand what is the actual difference between annotations javax.transaction.Transactional
and org.springframework.transaction.annotation.Transactional
?
Is org.springframework.transaction.annotation.Transactional
an extension of javax.transaction.Transactional
or they have totally different meaning? When should each of them be used? Spring @Transactinal
in service layer and javax in DAO?
Thanks for answering.
Java Solutions
Solution 1 - Java
Spring has defined its own Transactional annotation to make Spring bean methods transactional, years ago.
Java EE 7 has finally done the same thing and now allows CDI bean methods to be transactional, in addition to EJB methods. So since Java EE 7, it also defines its own Transactional annotation (it obviously can't reuse the Spring one).
In a Java EE 7 application, you'll use the Java EE annotation.
In a Spring application, you'll use the Spring annotation.
Their use is the same: informing the container (Java EE or Spring) that a method is transactional.
Solution 2 - Java
Another difference is how Spring handles the @Transactional annotations
- org.springframework.transaction.annotation.Transactional is always taken into account
- javax.transaction.Transactional is taken into account only when EJB3 transactions are present. EJB3 transactions' presence is done by checking if class
javax.ejb.TransactionAttribute
is available in the classpath (from version 2.5.3 to 3.2.5). Thus you can end up with your annotations not being taken into account if onlyjavax.transaction.Transactional
is in your classpath and notjavax.ejb.TransactionAttribute
. This can be the case if you're working with Hibernate: hibernate-core (4.3.7.Final) depends on jboss-transaction-api_1.2_spec (1.0.0.Final), which doesn't providejavax.ejb.TransactionAttribute
.
Solution 3 - Java
Please be careful, (this issue happened in tomcat),
If your application is SPRING web application and you are using Spring's transaction handling mechanism that is @org.springframework.transaction.annotation.Transactional
, then don't mix it with javax.transaction.Transactional.
That is Always use, @org.springframework.transaction.annotation.Transactional
in a spring application consistently.
Otherwise we may end up with this error,
org.springframework.orm.jpa.JpaSystemException: commit failed; nested exception is org.hibernate.TransactionException: commit failed
........
Caused by: java.sql.SQLException: Protocol violation: [0]
Solution 4 - Java
Declarative transaction scope
Both the Spring and JPA @Transaction
annotation allow you to define the scope of a given application transaction.
So, if a service method is annotated with the @Transactional
annotation, it will run in a transactional context. If the service method uses multiple DAO or Repositories, all read and write operations will be executed in the same database transaction.
@Transactional
Spring The org.springframework.transaction.annotation.Transactional
annotation has been available since the 1.2 version of the Spring framework (circa 2005), and it allows you to set the following transactional properties:
isolation
: the underlying database isolation levelnoRollbackFor
andnoRollbackForClassName
: the list of JavaException
classes that can be triggered without triggering a transaction rollbackrollbackFor
androllbackForClassName
: the list of JavaException
classes that trigger a transaction rollback when being thrownpropagation
: the transaction propagation type given by thePropagation
Enum. For instance, if the transaction context can be inherited (e.g.,REQUIRED
) or a new transaction context should be created (e.g.,REQUIRES_NEW
) or if an exception should be thrown if no transaction context is present (e.g.,MANDATORY
) or if an exception should be thrown if a current transaction context is found (e.g.,NOT_SUPPORTED
).readOnly
: whether the current transaction should only read data without applying any changes.timeout
: how many seconds should the transaction context be allowed to run until a timeout exception is thrown.value
ortransactionManager
: the name of the SpringTransactionManager
bean to be used when binding the transaction context.
@Transactional
Java EE The javax.transaction.Transactional
annotation was added by the Java EE 7 specification (circa 2013). So, the Java EE annotation was added 8 years later than its Spring counterpart.
The Java EE @Transactional
defines just 3 attributes:
dontRollbackOn
: the list of JavaException
classes that can be triggered without triggering a transaction rollbackrollbackOn
: the list of JavaException
classes that trigger a transaction rollback when being thrownvalue
: the propagation strategy, given by theTxType
Enum. For instance, if the transaction context can be inherited (e.g.,REQUIRED
) or a new transaction context should be created (e.g.,REQUIRES_NEW
) or if an exception should be thrown if no transaction context is present (e.g.,MANDATORY
) or if an exception should be thrown if a current transaction context is found (e.g.,NOT_SUPPORTED
).
Which one to choose?
If you're using Spring or Spring Boot, then use the Spring @Transactional
annotation, as it allows you to configure more attributes than the Java EE @Transactional
annotation.
If you are using Java EE alone, and you deploy your application on a Java EE application server, then use the Java EE @Transactional
annotation.