2
votes

I have a method with @Transaction calling a method with @Transaction( Propagation.REQUIRES_NEW) . Both the transactions are rolled back in case of exception in the parent method.

Parent Transaction:

@Transactional(propagation = Propagation.REQUIRED)
public void test() {
    SampleClassParent sampleClassParent = new SampleClassParent();
    sampleClassParent.setAddressId(2545L);
    sampleClassParent.setUserId(21660742L);
    getBaseDao().saveOrUpdate(sampleClassParent);
    newTransaction();

    // getting an exception purposefully
    User user = null;
    user.getId(); // Will throw a null pointer exception
}

Nested Transaction:

@Transactional(propagation = Propagation.REQUIRES_NEW)
private void newTransaction(){
    SampleClassNested sampleClassNested = new SampleClassNested();
    sampleClassNested.setCityId(15747L);
    sampleClassNested.setStoreId(5L);
    getBaseDao().saveOrUpdate(sampleClassNested);
}

SaveOrUpdate Method: (uses hibernate 3.3.2)

  // Wrapper around hibernate method
  public void saveOrUpdate(Object entity, boolean delayCommit) {
      getSessionFactory().getCurrentSession().saveOrUpdate(entity);
  }

All entries are created successfully when no exception is thrown. SampleClassParent and SampleClassNested are Hibernate Entity classes.

Here both the transactions are rolled back, but Ideally, Propagation.REQUIRES_NEW should suspend the existing transaction and create a new transaction. Why?

1
@Transactional doesn't work on a private method. See stackoverflow.com/questions/4396284/…. Even for public methods, it only works when called from outside of your class. So your outside caller will have to make two calls. - David Lavender
The result is the same for both, public and private methods. The issue is that I have nested transactions. The outside method only calls the parent transaction. Also, If I call it using an outside method, will it not effectively mean the same thing (nested transactions)? - Abhinav

1 Answers

0
votes

From the provided code I would think it's because you call directly the method newTransaction(). For transaction management could be processed you have to give the container a chance to intercept the method call. That could be done by injection the bean and by calling the method from that injection point, kind of bean.newTransaction().