@ Транзакционный метод, вызывающий другой метод без аннотации @Transactional? - PullRequest
64 голосов
/ 03 июня 2011

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

Означает ли это, что вызов отдельных методов приводит к тому, что приложение открывает отдельные соединения с БД или приостанавливает родительскую транзакцию и т. Д.?

Каково поведение по умолчанию для метода без каких-либо аннотаций, который вызывается другим методом с @Transactional аннотацией?

Ответы [ 4 ]

88 голосов
/ 03 июня 2011

Когда вы вызываете метод без @Transactional в блоке транзакции, родительская транзакция переходит к новому методу. Он будет использовать то же соединение из родительского метода (с @Transactional), и любое исключение, вызванное в вызываемом методе (без @Transactional, вызовет откат транзакции, как настроено в определении транзакции.

Если вы вызываете метод с аннотацией @Transactional из метода с @Transactional в том же экземпляре, то поведение транзакции вызываемых методов не окажет никакого влияния на транзакцию. Но если вы вызываете метод с определением транзакции из другого метода с определением транзакции, и они находятся в разных экземплярах, тогда код в вызываемом методе будет следовать определениям транзакции, данным в вызываемом методе.

Более подробную информацию можно найти в разделе Декларативное управление транзакциями из Документация по пружинным транзакциям .

Модель декларативных транзакций Spring использует прокси AOP. поэтому прокси-сервер AOP отвечает за создание транзакций. Прокси-сервер AOP будет активен, только если методы в экземпляре вызываются извне экземпляра.

18 голосов
/ 18 января 2012
  • Означает ли это, что вызов отдельных методов приводит к тому, что приложение открывает отдельные соединения с БД или приостанавливает родительскую транзакцию и т. Д.?

Это зависит от уровня распространения . Вот все возможные уровни значений .

Например, если уровень распространения NESTED , текущая транзакция будет «приостановлена» и будет создана новая транзакция ( примечание: фактическое создание вложенной транзакции будет работать только для конкретной транзакции менеджеры )

  • Каково поведение по умолчанию для метода без каких-либо аннотаций, который вызывается другим методом с аннотацией @Transactional?

Уровень распространения по умолчанию (то, что вы называете «поведением») равен REQUIRED . Если вызывается «внутренний» метод с аннотацией @Transactional (или декларативно передаваемый через XML), он будет выполняться в рамках той же транзакции , например, "ничего нового" не создано.

8 голосов
/ 03 июня 2011

@ Транзакционный отмечает границу транзакции (начало / конец), но сама транзакция связана с потоком.Как только транзакция начинается, она распространяется по вызовам метода до тех пор, пока исходный метод не вернется и транзакция не завершит фиксацию / откат.

Если вызван другой метод с аннотацией @Transactional, то распространение зависит от атрибута распространения этой аннотации..

1 голос
/ 05 апреля 2019

Возможно, вы угадали ответ на свой вопрос из ответов выше. Внутренний метод повлияет на внешний метод, если внутренний метод не аннотирован @ 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, поэтому он устанавливает откат транзакции, но НЕ ВЛИЯЕТ на внешнюю транзакцию. Внешняя транзакция приостанавливается, когда начинается внутренняя транзакция, а затем возобновляет ПОСЛЕ того, как внутренняя транзакция завершается. Они выполняются независимо друг от друга, поэтому внешняя транзакция МОЖЕТ успешно зафиксироваться.

...