0

I am working with some legacy code where all the Spring DAOs are annotated with @Transactional annotation. Now I have a business requirement where I need to call two different DAOs in my service layer and rollback the transaction if it fails at any point.

How do I achieve this in Spring 5 without removing the @Transactional annotation from DAOs and still use them from the service layer. I don't think the code below will work as the transaction in each DAO would be independent of each other.

Many thanks in advance.

@Transactional
public FooDao {
}

@Transactional
public BarDao {
}


@Transactional
public TestServiceImple implements TestService {
  fooDao.action1();
  barDao.action2();
}
getITdone
  • 95
  • 2
  • 12

3 Answers3

1
  1. The default propagation type for a @Transactional annotation is Propagation.REQUIRED.

Support a current transaction, create a new one if none exists.

  1. The default rollback behaviour for a @Transactional annotation is as follows

By default, a transaction will be rolling back on RuntimeException and Error but not on checked exceptions (business exceptions).

These two default configurations will make sure that both fooDao.action1() and barDao.action2() in the TestServiceImple work with the same txn and rollback together on any RuntimeException/custom rollback configuration at service layer , provided these two methods are called from the same service method annotated with @Transactional .

Example

 @Transactional
 public TestServiceImple implements TestService {

     public void callDaoMethods(){
      fooDao.action1();
      barDao.action2();
     }

 }

or

public TestServiceImple implements TestService {

 @Transactional
 public void callDaoMethods(){
   fooDao.action1();
   barDao.action2();
 }
}
R.G
  • 6,436
  • 3
  • 19
  • 28
  • 1
    This one was also useful: https://stackoverflow.com/questions/5684473/how-to-call-a-custom-rollback-method-in-spring-transaction-management – getITdone Feb 04 '20 at 01:35
0

With Propagation.REQUIRED as default in @Transaction the second method will use current transaction. @Transactional(propagation=Propagation.REQUIRED), so in the end it will just only one transaction.

Pedro Henrique
  • 171
  • 2
  • 10
0

If your general goal is to ensure the transactional will rollback changes made via both dao calls, when an unchecked exception is thrown, you should be able to remove the @Transactional from the dao methods themselves, and keep it in the service layer. Transactionals in Spring can be class or method level, so in this case, you can have it on just the method* that calls both dao methods (though, as you point out, you seem to want to keep those annotations in dao layer?).

One of the general points of transactions is when dealing with multiple database changes (multiple calls to dao(s)), so it's not really good design to have the transactional annotation on individual dao methods (or on the dao layer in general).

If you're two daos deal with two different datasources (not sure, you didn't mention) then, if you have/can get spring data as a dependency, you can utilize the ChainedTransactionManager (https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/transaction/ChainedTransactionManager.html)

rokus_inv
  • 113
  • 1
  • 3