Vadim Kirilchuk
Vadim Kirilchuk

Reputation: 3542

Spring transactions: inner transaction changes are "rolled back" by outer transaction (or maybe jpa misuse)

I have a simple code spring+jpa which looks correct at first glance:

@Transactional(propagation=REQUIRED)
public void outer(long id) {
    MyEntity entity = myRepo.findById(id);
    try {
         // doing something that changes entity
         // and may throw exception
         doInOuter(entity);
    } catch (Exception ex) {
        anotherSpringService.inner(entity);
        throw ex; // this rollbacks outer transaction for sure
    }
}

@Transactional(propagation=REQUIRES_NEW)
public void inner(MyEntity entity) {
    // doing something that changes entity
}

Let's consider the case when exception happens during doInOuter(). I would expect that in a catch block in the inner()

  1. outer transaction gets suspended
  2. inner transaction commits the changes
  3. inner transaction closed
  4. exception is thrown in the catch block
  5. outer transaction is rolled back
  6. The changes in the database contain the changes done by inner()

Unfortunately that is not what happens. All the changes in both inner/outer are completely "rolled back". I put the quotes because I don't think it happens because of the rollback itself.

If I change the inner to retrieve the entity one more time:

@Transactional(propagation=REQUIRES_NEW)
public void inner(MyEntity entity) {
    entity = myRepo.findById(entity.getId());
    // doing something which changes entity
}

The code starts to work as expected and I do see the changes done by inner() in the database.

Can anyone explain me why that works and why the first approach doesn't work as expected?

Upvotes: 2

Views: 1011

Answers (1)

JB Nizet
JB Nizet

Reputation: 691635

The Hibernate session is bound to the transaction, and the entity is bound to the session. So, when you pass the entity to the inner method, since it has been loaded from the outer transaction, it stays bound to the outer session.

You shouldn't share the entity between transactions, as you discovered.

Upvotes: 4

Related Questions