Как в java использовать разные транзакции для вложенного метода

Рейтинг: 0Ответов: 1Опубликовано: 13.04.2023

Условно есть некий класс сервис: TestService Есть приложение на спринге. Класс выглядит так:

public class TestService{
    @Transactional
    public void first() {
        second();
    }

    @Transactional
    protected void second() {
        //todo
    }
}

Мне необходимо чтобы метод second каждый раз работал в новой физической транзакции. Почитал статьи и в них пишут что если оставить все как есть, то по факту, метод second будет работать в той же транзакции что и first.

Собственно вопрос: Как сделать так, чтобы метод second работал в своей транзакции? Желательно без введения дополнительных классов. Так же интересует, как в junit можно проверить что транзакции у first и second разные?

Ответы

▲ 1Принят

То что вы хотите сделать и "Желательно без введения дополнительных классов" практически невозможно, ибо аннотация над вторым методом, вернее прокси прослойка, никогда не сработает (это отдельная тема и она неоднократно обсуждалась). Существуют костыльные варианты решения этой проблемы (например инжектирование сервиса самого в себя и вызов второго метода через инжектированный инстанс), но наиболее грамотным является создание бина с необходимым функционалом.

Теперь по существу. Спринг предлагает несколько вариантов декларирования "распространения" транзакции, которые описываются свойством propagation аннотации @Transactional. В вашем случае скорее всего необходимо propagation.REQUIRES_NEW - создание новой транзакции и приостановка текущей (из первого метода) до момента завершения выполнения второй. Как это протестировать - кинуть RuntimeException после изменений в базе вторым методом и убедиться что они не произошли. При этом первый метод должен сделать свои изменения в базе до вызова второго, и соответственно эти изменения должны быть зафиксированы.