Search code examples
springhibernateormtransactionsentitymanager

How to rollback transaction from service class?


I am trying to rollback for some condition by throwing exception. But i can not find proper way to do this. Here is my service class

@Service
public class UserManager implements IUserManager {

    private final IBasicEM basicEM;

    public ApplicantInfoManager(IBasicEM basicEM) {
        this.basicEM = basicEM;
    }

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public boolean purgeUser(Long id) throws Exception {
      //business logic
      basicEM.Update(entity)
      if(//condition) {
          throw New RollBackException("//message")
      }
      //business logic
    }
}

And here is my BasicEM class

@Component
@Transactional(value = "transactionManager", rollbackFor = Exception.class)
public class BasicEM {
    @PersistenceContext(unitName = "db1")
    private EntityManager em;

    public void update(Object target) {
        em.merge(target);
    }
}

So what i want is to call that update method, then if the condition is true undo the update. My intention is that when i throw the exception, the transaction ends and does not commit the update. But i am wrong and the update is already done. Please help me to achieve my goal.


Solution

  • In order to achieve what you want you will need to have a transaction already in the Service method. The default propagation type for @Transactional(value = "transactionManager", rollbackFor = Exception.class) is Propagation.REQUIRED which means that if your Service is already included in a transaction, the basicEM.Update(entity) will also be included in such transaction.

    @Service
    public class UserManager implements IUserManager {
    
        private final IBasicEM basicEM;
    
        public ApplicantInfoManager(IBasicEM basicEM) {
            this.basicEM = basicEM;
        }
    
        @Override
        @Transactional(value = "transactionManager", 
           propagation = Propagation.REQUIRES_NEW, rollbackFor = RollBackException.class)
        public boolean purgeUser(Long id) throws Exception {
          //business logic
          basicEM.Update(entity)
          if(//condition) {
              throw New RollBackException("//message")
          }
          //business logic
        }
    }
    

    If RollBackException is a RuntimeException you don't need to explicitly configure that the transaction should rollback when it is thrown. If it is not, then you need to configure it as follows: @Transactional(value = "transactionManager", propagation = Propagation.REQUIRES_NEW, rollbackFor = RollBackException.class).