Where does the @Transactional annotation belong?
I think transactions belong on the service layer. It's the one that knows about units of work and use cases. It's the right answer if you have several DAOs injected into a service that need to work together in a single transaction.
Where to use @Transactional annotation and @Repository annotation
I have always used @Service
and @Repository
annotations on their implementations, but they can be put in either one. Although, putting it on a interface would mean that you won't be able to have more than one implementation, because you would get a NoUniqueBeanDefinitionException
error.
In the case of @Transactional
, it depends, but normally it goes on the service. If you want to be able to add various DB calls on one transaction, then it should go in the service. If you want to make small transactions, then on the DAO would be best, but then, you wouldn't be able to modify several tables in one single transaction. Another con of having it on the DAO, is that you won't be able to rollback multiple modifications, only the ones that are bing executed by the DAO.
EDIT
After several projects using Spring, each one of different proportions, I end up changing my own practices. I would like to add that even though adding @Transactional
to the service layer isn't exactly bad practice, it can be negatively affect the performance of the application. So in my own experience, it is better to add it to the DAO/Repository
layers and only add at function level in the service layer, if a transaction must be atomic.
One more thing, if you are using Spring Data
, the @Repository
must be added on the interface. Only if you extend the JpaRepository
will you need to add the @Repository
annotation on the implementation. In this case, the interface of the JpaRepository
and the custom implementation will both have @Repository
.
Where should @Transactional be placed Service Layer or DAO
Ideally, Service layer (Manager) represents your business logic and hence it should be annotated with @Transactional
.
Service layer may call different DAOs to perform DB operations. Lets assume a situation where you have 3 DAO operations in a service method. If your 1st DAO operation failed, other two may be still passed and you will end up with an inconsistent DB state. Annotating Service layer can save you from such situations.
Spring managed transactions @Transactional annotation
Spring transaction default is
@Transactional(propagation = Propagation.REQUIRED)
So you do not need to specify the propagation property.
So, What does it mean by @Transactional
annotation for a spring component ?
Spring framework will start a new transaction and executes all the method and finally commit the transaction.
But If no transaction is exists in the
application context
then spring container will start a new transaction.- If more than one method configured as
Propagation.REQUIRED
then transactional behavior assigned in a nested way to each method in logically but they are all under the same physical transaction.
So, What is the result ?
The result is if any nested transaction fail, then the whole transaction will fail and rolled back (do not insert any value in db) instead of commit.
Example:
@Service
public class ServiceA{
@Transactional(propagation = Propagation.REQUIRED)
public void foo(){
fooB();
}
@Transactional(propagation = Propagation.REQUIRED)
public void fooB(){
//some operation
}
}
Explanation :
In this example foo()
method assigned a transactional behavior and inside foo()
another method fooB()
called which is also transactional.
Here the fooB()
act as nested transaction in terms of foo()
. If fooB()
fails for any reason then foo()
also failed to commit. Rather it roll back.
Where should I put @Transactional annotation: at an interface definition or at an implementing class?
From http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html
The Spring team's recommendation is that you only annotate concrete classes with the
@Transactional
annotation, as opposed to annotating interfaces. You certainly can place the@Transactional
annotation on an interface (or an interface method), but this will only work as you would expect it to if you are using interface-based proxies. The fact that annotations are not inherited means that if you are using class-based proxies then the transaction settings will not be recognised by the class-based proxying infrastructure and the object will not be wrapped in a transactional proxy (which would be decidedly bad). So please do take the Spring team's advice and only annotate concrete classes (and the methods of concrete classes) with the@Transactional
annotation.Note: Since this mechanism is based on proxies, only 'external' method calls coming in through the proxy will be intercepted. This means that 'self-invocation', i.e. a method within the target object calling some other method of the target object, won't lead to an actual transaction at runtime even if the invoked method is marked with
@Transactional
!
(Emphasis added to the first sentence, other emphasis from the original.)
Related Topics
Causes of Getting a Java.Lang.Verifyerror
What Causes Javac to Issue the "Uses Unchecked or Unsafe Operations" Warning
Getting a File'S Md5 Checksum in Java
Equals VS Arrays.Equals in Java
Why Can't I Do Assignment Outside a Method
How to Access Java-Classes in the Default-Package
Why Are Arrays Covariant But Generics Are Invariant
Making a Robust, Resizable Swing Chess Gui
Including Dependencies in a Jar With Maven
How Can an App Use Files Inside the Jar For Read and Write
How to Add an Image to a Jpanel
Recursively List Files in Java
What Is the Equivalent of the C++ Pair≪L,R≫ in Java