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.
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.
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 only javax.transaction.Transactional is in your classpath and not javax.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 provide javax.ejb.TransactionAttribute.
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]
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.
Spring @Transactional
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 level
noRollbackFor and noRollbackForClassName: the list of Java Exception classes that can be triggered without triggering a transaction rollback
rollbackFor and rollbackForClassName: the list of Java Exception classes that trigger a transaction rollback when being thrown
propagation: the transaction propagation type given by the Propagation 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 or transactionManager: the name of the Spring TransactionManager bean to be used when binding the transaction context.
Java EE @Transactional
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 Java Exception classes that can be triggered without triggering a transaction rollback
rollbackOn: the list of Java Exception classes that trigger a transaction rollback when being thrown
value: the propagation strategy, given by the TxType 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.
private
methods?
Success story sharing
javax.transaction.Transactional
so one could now use it also in Spring applications without any additional actions. IMO, this was quite bad decision from design standpoint, because out of my experience a lot of developers unconciously confuse these two in their code which leads to problems afterwards.org.springframework.transaction.annotation.Transactional
offers more options (likereadOnly
,timeout
) thanjavax.transaction.Transactional