Where does the @Transactional annotation belong?

Viewed 268099

Should you place the @Transactional in the DAO classes and/or their methods or is it better to annotate the Service classes which are calling using the DAO objects? Or does it make sense to annotate both "layers"?

19 Answers

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.

Transactional Annotations should be placed around all operations that are inseparable.

For example, your call is "change password". That consists of two operations

  1. Change the password.
  2. Audit the change.
  3. Email the client that the password has changed.

So in the above, if the audit fails, then should the password change also fail? If so, then the transaction should be around 1 and 2 (so at the service layer). If the email fails (probably should have some kind of fail safe on this so it won't fail) then should it roll back the change password and the audit?

These are the kind of questions you need to be asking when deciding where to put the @Transactional.

The normal case would be to annotate on a service layer level, but this really depends on your requirements.

Annotating on a service layer will result in longer transactions than annotating on DAO level. Depending on the transaction isolation level that can youse problems, as concurrent transactions wont see each other's changes in eg. REPEATABLE READ.

Annotating on the DAOs will keep the transactions as short as possible, with the drawback that the functionality your service layer is exposing wont be done in a single (rollbackable) transaction.

It does not make sense to annotate both layers if the propagation mode is set to default.

Usually, one should put a transaction at the service layer.

But as stated before, the atomicity of an operation is what tells us where an annotation is necessary. Thus, if you use frameworks like Hibernate, where a single "save/update/delete/...modification" operation on an object has the potential to modify several rows in several tables (because of the cascade through the object graph), of course there should also be transaction management on this specific DAO method.

It's better to keep @Transactional in a separate middle layer between DAO and Service Layer. Since, rollback is very important, you can place all your DB manipulation in the middle layer and write business logic in Service Layer. Middle layer will interact with your DAO layers.

This will help you in many situations like ObjectOptimisticLockingFailureException - This exception occurs only after your Transaction is over. So, you cannot catch it in middle layer but you can catch in your service layer now. This would not be possible if you have @Transactional in Service layer. Although you can catch in Controller but Controller should be as clean as possible.

If you are sending mail or sms in seperate thread after completing all the save,delete and update options, you can do this in service after Transaction is completed in your middle layer. Again, if you mention @Transactional in service layer, you mail will go even if your transaction fails.

So having a middle @Transaction layer will help to make your code better and easy to handle. Otherwise, If you use in DAO layer, you may not be able to Rollback all operations. If you use in Service layer, you may have to use AOP(Aspect Oriented Programming) in certain cases.

Related