Я использую данные пружины jpa с @EnableJpaRepositories
и повтор пружины с @EnableRetry
.
Я хочу повторить транзакционный метод, который вызывает другой транзакционный метод, который получает Oracle DBMS_LOCK
, используя хранимую процедуру-обертку: MY_PROC_THAT_CALLS_ORACLE_DBMS_LOCK
.
Полученная блокировка настроена на снятие после фиксации транзакции, и это то, что я хочу.
Но, несмотря на успешное получение блокировки, скажем, со второй попытки, моя транзакция помечается как rollback_only
и не выполняется.
Я подозреваю, что аннотация @Transactional
в моем методе acquireDbmsLock
в моем репозитории позволяет увидеть SQLException
и настроить только откат транзакции.
Из моего понимания семантики распространения транзакций я думаю, что не хочу @Transactional(propogation = Propogation.REQUIRES_NEW)
в методе интерфейса acquireDbmsLock
. Похоже, Hibernate не поддерживает Propogation.NESTED
.
Итак, что является хорошим решением для этой проблемы?
Я сопротивляюсь настройке noRollbackFor = SQLException.class
.
Вот мой код:
@Retriable(SQLException.class)
@Transactional
public MyThing myService(String thingId) {
MyThing myThing = myRepository.findMyThing(thingId);
if(myThing == null) {
myLockRepository.acquireDbmsLock(thingId);
myRepository.createMyThing(thingId);
} else {
return myThing;
}
}
public interface MyLockRepository extends Repository<XXX, YY> {
@Procedure(procedureName = "MY_PROC_THAT_CALLS_ORACLE_DBMS_LOCK")
void acquireDbmsLock(String lockName);
}
Я попытался переопределить конфигурацию повторных попыток по умолчанию, как показано ниже (после удаления аннотации @EnableRetry
):
@Bean
RetryConfiguration retryConfiguration() {
// Need retries to happen before transaction is set to rollback only: https://stackoverflow.com/a/53654301/499635
return new RetryConfiguration() {
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
};
}