2

У меня есть настройка, в которой внешний метод вызывает внутренний метод. Возможно, этот внутренний метод будет генерировать исключение, которое приведет к откату. Я не хочу, чтобы это исключение влияло на внешний метод. Для этого я использовал @Transactional (распространение = Propagation.REQUIRED_NEW) во внутреннем методе.Проблема с распространением пружинных транзакций и оптимистическим блокированием

Вот упрощенная версия моего кода:

public class ServiceAImpl implements ServiceA{ 
    @Autowired 
    private ServiceB serviceB; 

    @Transactional(propagation=Propagation.REQUIRED) 
    public void updateParent(Parent parent) { 
     update(parent); 
     serviceB.updateChild(parent); 
    } 
} 

public class ServiceBImpl implements ServiceB { 
    @Transactional(propagation=Propagation.REQUIRED_NEW) 
    public void updateChild(Parent parent) { 
     checkIfChildHasErrors(parent.getChild()); //throws RuntimeException if Child has errors 
     update(parent.getChild()); 
    } 
} 

public class Parent { 
    @Version 
    private Integer version; 
    private Child child; 

    //insert getters and setters 
} 

public class Child { 
    @Version 
    private Integer version; 

    //insert getters and setters 
} 

Я еще новичок в размножении, но от моего понимания, так как внешний метод (updateParent) имеет Propagation.REQUIRED и внутренний метод (updateChild) имеет Propagation.REQUIRED_NEW, они теперь содержатся в их собственных отдельных транзакциях. Если внутренний метод встречает исключение, он откатывается, но не вызывает откат внешнего метода.

Когда наружный метод работает, он вызывает внутренний метод. Внешний метод приостанавливается, пока выполняется внутренний метод. Как только внутренний метод заканчивается, он совершается с , это другая транзакция. Внешний метод не работает. и он также совершается в качестве другой транзакции.

Проблема, с которой я сталкиваюсь, заключается в том, что процесс выполнения внешнего метода запускает оптимистическую блокировку для класса Child (возможно, потому что значение поля версии было изменено после завершения внутреннего метода и было выполнено). Поскольку экземпляр внешнего метода Child уже устарел, его совершение вызывает оптимистичную блокировку.

Мой вопрос: ЯВЛЯЕТСЯ ПУТЕМ ПРЕДОТВРАЩЕНИЯ ВНЕШНЕГО МЕТОДА ОТ ОПТИМИЗАЦИИ ОПТИМИСТИЧЕСКОГО БЛОКИРОВАНИЯ?

Я удивлен, что внешний метод даже пытается зафиксировать изменения в классе Child. Я предположил, что, поскольку внутренний метод содержится в его собственной транзакции, транзакция внешнего метода больше не будет включать метод updateChild.

Я использую Spring 3.0.5 с Hibernate 3.6.10

+0

Одним простым решением было бы уловить ОПТИМИСТИЧЕСКИЙ БЛОК. Исключение внутреннего метода из внешнего метода a и заставьте исключение. – Esty

+0

Привет, Tanjim, это внешний метод, который генерирует исключение оптимистического блокирования. Внутренний метод обновляет запись БД без исключений. Кроме того, я не думаю, что его разумно поймать и игнорировать оптимистичный замок, я ввернута, если реальное оптимистичное исключение блокировки выбрасывается через одновременные обновления пользователей. – poach

+0

Ваше распространение верно. Использование Propagation.REQUIRED для внешней транзакции и Propagation.REQUIRED_NEW во внутренней транзакции не повлияет на внешнюю транзакцию при любом фиксации/откате внутренней транзакции. Не могли бы вы определить, какая из ваших строк изменяется во время работы. Я думаю, что u работает с одной и той же строкой в ​​обеих транзакциях, для которых обновляется поле версии, и генерируется исключение OptimisticLockException. – Esty

ответ

0

Предполагая, что вы используете слияние для обновления

Для внутренней сделки

Entity entityUpdated = entityManager.merge(entity); 

Для внешней транзакции

if (entityUpdated != null){ 
    // if inner transaction rolledback entityUpdated will be null. Condition will save u from nullPointerException 
    outerEntity.setVersion(entityUpdated.getVersion); 
} 

entityManager.merge(outerEntity); 
+0

Привет, Tanjim, слияние не удалось решить, к сожалению. Тем не менее я ценю вашу помощь. – poach

+0

Определенное слияние - это не тот момент, когда вы решаетесь. Точка - это когда u обновлять строку второй раз, просто использовать обновленную версию и ее единственный способ избежать исключения OptimisticLockingException. – Esty