Как в java использовать разные транзакции для вложенного метода
Условно есть некий класс сервис: 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 после изменений в базе вторым методом и убедиться что они не произошли. При этом первый метод должен сделать свои изменения в базе до вызова второго, и соответственно эти изменения должны быть зафиксированы.