@Transactional метод, вызывающий другой метод без @Transactional anotation?
Я видел метод в классе Service, который был помечен как @Transactional
, но он также вызывал некоторые другие методы в том же классе, которые не были помечены как @Transactional
.
Означает ли это, что вызов отдельных методов приводит к тому, что приложение открывает отдельные соединения с БД или приостанавливает родительскую транзакцию и т.д.?
Каково поведение по умолчанию для метода без каких-либо аннотаций, который вызывается другим методом с аннотацией @Transactional
?
Ответы
Ответ 1
Когда вы вызываете метод без @Transactional
внутри блока транзакции, родительская транзакция будет продолжать новый метод. Он будет использовать одно и то же соединение из родительского метода (с @Transactional
), и любое исключение, вызванное вызываемым методом (без @Transactional
, приведет к откату транзакции, как указано в определении транзакции.
Если вы вызываете метод с аннотацией @Transactional
от метода с @Transactional
внутри одного и того же экземпляра, то транзакционное поведение вызываемых методов не окажет никакого влияния на транзакцию. Но если вы вызываете метод с определением транзакции из другого метода с определением транзакции, и они находятся в разных экземплярах, тогда код в вызываемом методе будет следовать определениям транзакций, указанным в вызываемом методе.
Более подробную информацию вы можете найти в разделе Декларативное управление транзакциями spring документации по транзакциям.
spring модель декларативной транзакции использует прокси AOP. поэтому прокси-сервер AOP отвечает за создание транзакций. Прокси-сервер AOP будет активен только в том случае, если методы из экземпляра вызываются со стороны экземпляра.
Ответ 2
- Означает ли это, что вызов отдельных методов заставляет приложение открывать отдельные подключения к БД или приостанавливать родительскую транзакцию и т.д.
Это зависит от уровня распространения . Вот все возможные значения .
Например, если уровень распространения NESTED, текущая транзакция будет "приостановлена " и будет создана новая транзакция (обратите внимание: фактическое создание вложенной транзакции будет работать только с конкретными менеджерами транзакций)
- Что такое поведение по умолчанию для метода без каких-либо аннотаций, которое вызывается другим методом с помощью аннотации @Transactional?
Уровень распространения по умолчанию (то, что вы называете "поведение" ) является REQUIRED. В случае вызова "внутреннего" метода, который имеет аннотацию @Transactional
на нем (или транзакционно декларативно через XML), он будет выполняться в той же транзакции, например. "ничего нового" не создано.
Ответ 3
@Transactional отмечает границу транзакции (начало/конец), но сама транзакция привязана к потоку. Как только транзакция начинается, она распространяется по вызову метода до тех пор, пока исходный метод не вернется, и транзакция совершит/откатится.
Если вызывается другой метод, который имеет аннотацию @Transactional, то распространение зависит от атрибута распространения этой аннотации.
Ответ 4
Возможно, вы угадали ответ на свой вопрос из ответов выше. Внутренний метод повлияет на внешний метод, если внутренний метод не аннотирован @Transactional.
В случае, если внутренний метод также аннотирован @Transactional с REQUIRES_NEW
, произойдет следующее.
...
@Autowired
private TestDAO testDAO;
@Autowired
private SomeBean someBean;
@Override
@Transactional(propagation=Propagation.REQUIRED)
public void outerMethod(User user) {
testDAO.insertUser(user);
try{
someBean.innerMethod();
} catch(RuntimeException e){
// handle exception
}
}
@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void innerMethod() {
throw new RuntimeException("Rollback this transaction!");
}
Внутренний метод аннотируется с помощью REQUIRES_NEW
и выдает исключение RuntimeException, поэтому он будет устанавливать откат транзакции, но не будет влиять на внешнюю транзакцию. Внешняя транзакция приостанавливается, когда начинается внутренняя транзакция, а затем возобновляет ПОСЛЕ того, как внутренняя транзакция завершается. Они запускаются независимо друг от друга, поэтому внешняя транзакция МОЖЕТ успешно зафиксироваться.