Spring Data: rollback transaction on retry

Aliaxander :

There is an entity:

@Entity
class A {
    ...
    @Version
    int version; 
}

A instances update implemented in optimistic manner:

@Transactional(rollbackFor = {StaleStateException.class})
@Retryable(value = {StaleStateException.class})
public void updateA() {
    A a = findA();
    B b = new B();
    // Update "a" somehow
    a.update();
    // "b" is saved on each retry!
    save(b);
}

As stated in comments, seems that transaction is not rollbacked when StaleStateException occurs, so B instance is saved on each retry.

Is it possible to rollback transaction on retry?

The desired behaviour is that b is saved only on successfull a update.

Zeromus :

I think it may be something related to the @Retryable configuration.

As the doc says https://docs.spring.io/spring-batch/trunk/reference/html/retry.html#statelessRetry a stateless retryable is nothing more than a cycle that keeps calling the same method until it succedes.

The problem is that everytime it fails the first interceptor called is the retryable that will not rethrow the exception, so it does never reach the @Transactional one.

So what happens is that every retry will follow the default transaction propagation which will reuse the same opened transaction with a new B() in the context.

You can check if i'm on the right lead by debugging: if you enter a second retry and find that A is already updated before the update block then i should be right.

You can fix in 2 ways:

Either divide the two block (retry first with nested transaction)

@Retryable(value = {StaleStateException.class})
public void retryableUpdate() {
   updateA();
}

@Transactional(rollbackFor = {StaleStateException.class})
public void updateA() {
    A a = findA();
    B b = new B();
    // Update "a" somehow
    a.update();
    // "b" is saved on each retry!
    save(b);
}

So that the transaction is rolled back first.

Or you can follow the docs and use a stateful retry https://docs.spring.io/spring-batch/trunk/reference/html/retry.html#statefulRetry

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=443451&siteId=1