В чем разница между методом с @Transactional(распространение = Propagation.SUPPORTS) и методом без @Transactional?
В чем разница между методом с
@Transactional(propagation = Propagation.SUPPORTS)
и метод без @Transactional
?
Например:
public class TEst {
@Transactional
public void methodWithTransaction1(){
methodWithSupportsTransaction();
}
@Transactional
public void methodWithTransaction2(){
methodWithoutTransactional();
}
@Transactional(propagation = Propagation.SUPPORTS)
public void methodWithSupportsTransaction(){
}
public void methodWithoutTransactional(){
}
}
2 ответа
За исключением небольшой разницы, указанной в javadoc в отношении синхронизации, разница между ними заключается в том, что транзакционный прокси-сервер перехватывает вызов метода, если метод аннотирован с помощью Transactional, и помечает текущую транзакцию, если таковая имеется, как rollbackOnly, если исключение времени выполнения выброшенный из этого метода.
Итак, давайте возьмем пример:
public class A {
@Autowired B b;
@Transactional
public void foo() {
try {
b.bar();
}
catch (RuntimeException e) {
// ignore
}
...
}
}
public class B {
// @Transactional(propagation = Propagation.SUPPORTS)
public void bar() {
throw new RuntimeException();
}
}
призвание a.foo()
начнет транзакцию, если ее еще нет (распространение НЕОБХОДИМО). Затем будет вызвана функция b.bar(), которая выдаст исключение. Исключение поймано a.foo()
, который продолжает выполняться, как будто ничего не произошло. В конце a.foo()
транзакция будет успешно завершена.
Теперь давайте раскомментируем аннотацию транзакции b.bar()
, призвание a.foo()
начнет транзакцию, если ее еще нет (распространение НЕОБХОДИМО). Затем будет вызвана функция b.bar(), которая выдаст исключение. Это исключение будет "перехвачено" транзакционным прокси-сервером вокруг B, который помечает транзакцию как rollbackOnly. Тогда исключение будет распространяться на А. a.foo()
, Исключение поймано a.foo()
, который продолжает выполняться, как будто ничего не произошло. В конце a.foo()
транзакция будет зафиксирована, но эта фиксация не будет выполнена, поскольку транзакция уже помечена как rollbackOnly. Вызывающая функция a.foo() получит исключение TransactionSystemException.
Spring поддерживает два типа управления транзакциями: программный и декларативный.
Программное управление транзакциями. Таким образом, транзакции должны обрабатываться нами. Например-
EntityTransaction tran = entityManager.getTransaction();
try {
tran.begin();
methodWithoutTransactional();
tran.commit();
} catch(Exception ex) {
tran.rollback();
throw ex;
}
Декларативное управление транзакциями. Таким образом, мы можем отделить код управления транзакциями от нашей бизнес-логики, просто используя аннотации или конфигурацию на основе XML. Что вы уже сделали в примере кода
@Transactional
public void methodWithTransaction1(){
methodWithSupportsTransaction();
}
Для аннотации @Transactional, если мы не определим тип распространения, по умолчанию будет применяться PROPAGATION_REQUIRED. Вы можете найти документацию здесь.