javax.transaction.Transactional vs org.springframework.transaction.annotation.Transactional
Solution 1
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
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
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
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
andnoRollbackForClassName
: the list of JavaException
classes that can be triggered without triggering a transaction rollback -
rollbackFor
androllbackForClassName
: the list of JavaException
classes that trigger a transaction rollback when being thrown -
propagation
: 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.
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 JavaException
classes that can be triggered without triggering a transaction rollback -
rollbackOn
: the list of JavaException
classes that trigger a transaction rollback when being thrown -
value
: 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.
Related videos on Youtube
stamis
Updated on July 16, 2022Comments
-
stamis almost 2 years
I don't understand what is the actual difference between annotations
javax.transaction.Transactional
andorg.springframework.transaction.annotation.Transactional
?Is
org.springframework.transaction.annotation.Transactional
an extension ofjavax.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.
-
Yuriy Nakonechnyy over 7 yearsMore than that: in order to rule the universe, Spring also added implicit support for
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. -
pierrefevrier about 7 yearsFurthermore,
org.springframework.transaction.annotation.Transactional
offers more options (likereadOnly
,timeout
) thanjavax.transaction.Transactional
-
Arend v. Reinersdorff almost 7 yearsI think this is not an issue anymore with Spring 4.2.0: javax.transaction.Transactional annotation is also supported as a drop-in replacement to Spring’s own annotation
-
Lee Chee Kiam almost 7 years@yura, what problems have you observed?
-
Yuriy Nakonechnyy almost 7 years@LeeCheeKiam please see two answers below
-
Jidehem over 6 yearsNote: this answer is a special case of my answer
-
strash over 6 yearsits not always taken, if its on a private method for example it won't be taken.
-
Dina Bogdan over 3 yearsDoes the Java/Jakarta EE @Transactional annotation work for
private
methods? -
Vlad Mihalcea over 3 yearsMost likely, not. The transaction boundary should start when calling a service from a different layer, like the web or a scheduler.
-
Dina Bogdan over 3 yearsActually, I'm already having a delegate method in the same class with the method annotated with @Transactional. I know that I can just move the annotation to this delegate method, but I was curious about this and I didn't find anything on the web.
-
Vlad Mihalcea over 3 yearsPrivate methods don't count. Only inter-services methods count for propagation rules.
-
ymajoros over 2 years"Java EE 7 has finally done the same thing" is quite misleading: this annotation exists since EJB 3.0, actually at about the same time that Spring has been having such annotation (in 1.2). Support in CDI was quite "new" when this was published (but so was CDI).