Home » Java » Where does the @Transactional annotation belong?

Where does the @Transactional annotation belong?

Posted by: admin November 2, 2017 Leave a comment

Questions:

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”?

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.

Questions:
Answers:

In general I agree with the others stating that transactions are usually started on the service level (depending on the granularity that you require of course).

However, in the mean time I also started adding @Transactional(propagation = Propagation.MANDATORY) to my DAO layer (and other layers that are not allowed to start transactions but require existing ones) because it is much easier to detect errors where you have forgotten to start a transaction in the caller (e.g. the service). If your DAO is annotated with mandatory propagation you will get an exception stating that there is no active transaction when the method is invoked.

I also have an integration test where I check all beans (bean post processor) for this annotation and fail if there is a @Transactional annotation with propagation other than Mandatory in a bean that does not belong to the services layer. This way I make sure we do not start transactions on the wrong layer.

Questions:
Answers:

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.

Questions:
Answers:

The correct answer for traditional Spring architectures is to place transactional semantics on the service classes, for the reasons that others have already described.

An emerging trend in Spring is toward domain-driven design. Spring Roo exemplifies the trend nicely. The idea is to make the domain object POJOs a lot richer than they are on typical Spring architectures (usually they are anemic), and in particular to put transaction and persistence semantics on the domain objects themselves. In cases where all that’s needed is simple CRUD operations, the web controllers operate directly on the domain object POJOs (they’re functioning as entities in this context), and there’s no service tier. In cases where there’s some kind of coordination needed between domain objects, you can have a service bean handle that, with @Transaction as per tradition. You can set the transaction propagation on the domain objects to something like REQUIRED so that the domain objects use any existing transactions, such as transactions that were started at the service bean.

Technically this technique makes use of AspectJ and <context:spring-configured />. Roo uses AspectJ inter-type definitions to separate the entity semantics (transactions and persistence) from the domain object stuff (basically fields and business methods).

Questions:
Answers:

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.

Questions:
Answers:

I place the @Transactional on the @Service layer and set “rollbackFor” any exception and “readOnly” to optimize the transaction further.

By default @Transactional will only look for RuntimeException (Unchecked Exceptions), by setting rollback to Exception.class (Checked Exceptions) it will rollback for any exception.

@Transactional(readOnly = false, rollbackFor=Exception.class)

Checked vs. Unchecked Exception: http://www.javapractices.com/topic/TopicAction.do?Id=129

Questions:
Answers:

Or does it make sense to annotate both “layers”? – does’nt it make sense to annotate both the service layer and the dao layer – if one wants to make sure that dao method is always called (propogated)from a service layer with propogation “mandatory” in dao. This would provide some restriction for dao methods from being called from UI layer (or controllers). Also – when unit testing Dao layer in perticular – having dao annotated will also ensure it is tested for transactional functionality.

Questions:
Answers:

Also, Spring recommends only using the annotation on concrete classes and not interfaces.

http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html

Questions:
Answers:

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.

Questions:
Answers:

For Transaction in database level

mostly I used @Transactional in DAO’s just on method level, so configuration can be specifically for a method / using default (required)

  1. DAO’s method that get data fetch (select .. ) – don’t need
    @Transactional this can lead to some overhead because of
    transaction interceptor / and AOP proxy that need to be executed as
    well.

  2. DAO’s methods that do insert / update will get @Transactional

very good blog on transctional

For application level –
I am using transactional for business logic I would like to be able rolback in case of unexpected error

@Transactional(rollbackFor={MyApplicationException.class})
public void myMethod(){

    try {    
        //service logic here     
    } catch(Throwable e) {

        log.error(e)
        throw new MyApplicationException(..);
    }
}

Questions:
Answers:

It is better to have it in the service layer! This is clearly explained on one of the article that I came across yesterday! Here is the link that you can check out!

Questions:
Answers:

@Transactional Annotations should be placed around all operations that are inseparable.
Using @Transactional transaction propagation are handled automatically.In this case if another method is called by current method,then that method will have the option of joining the ongoing transaction.

So lets take example:

We have 2 model’s i.e. Country and City. Relational Mapping of Country and City model is like one Country can have multiple Cities so mapping is like,

@OneToMany(fetch = FetchType.LAZY, mappedBy="country")
private Set<City> cities;

Here Country mapped to multiple cities with fetching them Lazily. So here comes role of @Transactinal when we retrieve Country object from database then we will get all the data of Country object but will not get Set of cities because we are fetching cities LAZILY.

//Without @Transactional
public Country getCountry(){
   Country country = countryRepository.getCountry();
   //After getting Country Object connection between countryRepository and database is Closed 
}

When we want to access Set of Cities from country object then we will get null values in that Set because object of Set created only this Set is not initialize with there data to get values of Set we use @Transactional i.e.,

//with @Transactional
@Transactional
public Country getCountry(){
   Country country = countryRepository.getCountry();
   //below when we initialize cities using object country so that directly communicate with database and retrieve all cities from database this happens just because of @Transactinal
   Object object = country.getCities().size();   
}

So basically @Transactional is Service can make multiple call in single transaction without closing connection with end point.

Questions:
Answers:

Ideally, Service layer(Manager) represents your business logic and hence it should be annotated with @Transactional.Service layer may call different DAO to perform DB operations. Lets assume a situations where you have N number of DAO operations in a service method. If your 1st DAO operation failed, others may be still passed and you will end up inconsistent DB state. Annotating Service layer can save you from such situations.

Questions:
Answers:

First of all let’s define where we have to use transaction?

I think correct answer is – when we need to make sure that sequence of actions will be finished together as one atomic operation or no changes will be made even if one of the actions fails.

It is well known practice to put business logic into services. So service methods may contain different actions which must be performed as a single logical unit of work. If so – then such method must be marked as Transactional. Of course, not every method requires such limitation, so you don’t need to mark whole service as transactional.

And even more – don’t forget to take into account that @Transactional obviously, may reduce method performance.
In order to see whole picture you have to know transaction isolation levels. Knowing that might help you avoid using @Transactional where it’s not necessarily needed.

Questions:
Answers:

I prefer to use @Transactional on services layer at method level.

Questions:
Answers:

@Transactional uses in service layer which is called by using controller layer (@Controller) and service layer call to the DAO layer (@Repository) i.e data base related operation.

Questions:
Answers:

Service layer is best place to add @Transactional annotations as most of the business logic present here, it contain detail level use-case behaviour.

Suppose we add it to DAO and from service we are calling 2 DAO classes , one failed and other success , in this case if @Transactional not on service one DB will commit and other will rollback.

Hence my recommendation is use this annotation wisely and use at Service layer only.

https://github.com/VishalTambe/java-algos/