Search code examples
springhibernatejpatransactionsspring-transactions

Multiple transaction management in Spring JPA


I am using Spring 4, JPA and Hibernate 5. I have a service as follows:

@Transactional(rollbackFor = Exception.class)
public methodA() {
  // do some stuff
  methodB();
}

@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public methodB() {
  try {
    methodC();
  } catch (Exception e) {
    // only log
  }
}


@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public methodC() {
  // do some stuff
}

What I want to achieve is this: when methodA is called, everything executed before calling methodB should be persisted, independently to what happens afterwards. For this reason I added methodB, the only purpose of which is to create a new transaction, so if the transaction of methodC rollbacks, the original transaction of methodA does not rollback as well. So to sum this up, I want the first transaction to commit and the second to rollback in case of failure. Note that methodC cannot be changed in any way.

This code however does not work and I still get the exception: "TransactionException: Transaction was marked for rollback only; cannot commit"

Any ideas on what I'm doing wrong?


Solution

  • I am using Spring 4, JPA and Hibernate 5. I have a service as follows:

    So you're using three methods inside same service

    This highlight is important because of how spring AOP works.

    If you call method within the same class, then the other methods do not get proxied by @Transaction so they're still using the same transaction of methodA. Therefore you will see exception when the transaction is marked as rollbackOnly by methodB

    So to solve this: You have to move the method methodB to another service so it will proxy-able by Spring.