Where Does the @Transactional Annotation Belong

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



Leave a reply



Submit