Весенний вложенный @транзакционный метод и откат

#hibernate #spring #service #rollback #transactional

#переход в спящий режим #весенний #Обслуживание #Откат #транзакционный

Вопрос:

У меня есть класс @Service, в котором есть @Transactional метод, который вызывает другой @Transactional метод в том же классе. Я тестировал поведение отката для этого и обнаружил, что оно не работает должным образом. Код выглядит примерно так:

 @Service
public class DefaulService implements ervice
{
    @Transactional
    public void methodOne()
    {
        methodTwo();

            //question edited
            //this seems to be the problem
            this.serviceDAO.executeUpdateOperation();

        //test rollback
        throw new RuntimeException();
    }

    @Transactional
    public void methodTwo()
    {
        //DAO stuff
    }
}
  

После запуска methodOne я проверяю базу данных и нахожу изменения, хотя в журнале отображается «JDBCTransaction — rollback».

Если я вызываю methodTwo по отдельности и добавляю исключение в конце его, изменения откатываются правильно.

Есть ли способ заставить methodOne должным образом откатывать изменения, которые произошли во время вложенного @транзакционного вызова? У меня создалось впечатление, что распространение REQUIRED по умолчанию позволило бы достичь этого, но, похоже, это не работает. Спасибо

Обновить

Хорошо, я только что заметил кое-что еще. Прямо перед выбросом исключения я вызываю dao службы и выполняю обновление вручную через ‘executeUpdate’. Если я прокомментирую эту строку, вложенный откат сработает. Итак, похоже, что проблема на самом деле заключается в вызове DAO и выполнении запроса executeUpdate. Но разве это не должно выполняться также внутри текущей транзакции?

Комментарии:

1.Вы знаете, что при вызове аннотации methodTwo() из methodOne() @Transactional поверх предыдущей она игнорируется? Смотрите мою статью для получения дополнительной информации. Однако это не вызывает ваших проблем, но стоит знать.

2. Да, но поскольку methodTwo может вызываться независимо, то для таких случаев ему нужна собственная аннотация. Прямо сейчас я в тупике относительно того, почему executeUpdate вызывает фиксацию транзакции, хотя, возможно, это поведение по умолчанию.

3. каково распространение транзакции serviceDao? Это случайно не REQUIRES_NEW ?

Ответ №1:

Вы определенно получаете экземпляр «objections» из bean factory при вызове методов, верно? Фабрике компонентов необходимо настроить прокси, который реализует транзакционную логику для каждого вызова метода. У меня сложилось впечатление, что это работает только тогда, когда «посторонние» вызывают методы через прокси-сервер, и не обязательно работает, когда один метод вызывает другой, поскольку этот метод является прямым вызовом внутри объекта реализации и не проходит через прокси-сервер AOP.

Комментарии:

1. Это зависит от того, какой подход AOP вы используете. Проверьте ссылку от Томаша Нуркевича. Также это не может объяснить поведение, описываемое JayPea.