@Transactional метод, який викликає інший метод без @Transactional анотації?


89

Я бачив метод у класі Service, який був позначений як @Transactional, але він також викликав деякі інші методи в тому ж класі, які не були позначені як @Transactional.

Чи означає це, що виклик окремих методів змушує програму відкривати окремі підключення до БД або призупиняти батьківську транзакцію тощо?

Яка поведінка за замовчуванням для методу без жодних анотацій, який викликається іншим методом із @Transactionalанотацією?

Відповіді:


117

Коли ви викликаєте метод поза @Transactionalблоком транзакції, батьківська транзакція перейде до нового методу. Він використовуватиме те саме підключення від батьківського методу (with @Transactional) та будь-який виняток, викликаний викликаним методом (без @Transactional, призведе до відкоту транзакції, як налаштовано у визначенні транзакції.

Якщо ви викликаєте метод із @Transactionalанотацією з методу, що знаходиться @Transactionalв тому самому екземплярі, тоді викликані методи транзакційної поведінки не вплинуть на транзакцію. Але якщо ви викликаєте метод із визначенням транзакції з іншого методу з визначенням транзакції, і вони знаходяться в різних екземплярах, тоді код у викликаному методі буде слідувати за визначеннями транзакцій, вказаними у викликаному методі.

Ви можете знайти більш детальну інформацію в розділі декларативного управління транзакціями в документації пружинних угод .

Весняна декларативна модель транзакції використовує проксі-сервер AOP. тому проксі-сервер AOP відповідає за створення транзакцій. Проксі-сервер AOP буде активним лише в тому випадку, якщо методи з екземпляром будуть викликані ззовні екземпляра.


це поведінка весни за замовчуванням?
goe

Так. Це поведінка за замовчуванням.
Arun P Johny

2
@Tomasz Так. Але слід також згадати, що зміна розповсюдження транзакції на метод, який викликається з іншого методу @Transactional, не матиме ефекту.
Fil

1
@Tomasz, Це я мав на увазі, сказавши will follow the transaction definitions given in the called method. Але якщо виклик надходить з того самого екземпляра об'єкта, це не матиме жодного ефекту, оскільки виклик не буде поширюватися через проміжні пристрої aop, які відповідають за обслуговування транзакції.
Arun P Johny

5
@Filip, Це не зовсім правильно, якщо ви викликаєте метод із @Transactionalвизначенням з іншого об'єкта / екземпляра, то навіть незважаючи на те, що викличний метод має різні @Transactionalатрибути, викликаний метод буде слідувати за власним визначенням транзакції.
Arun P Johny

23
  • Чи означає це, що виклик окремих методів змушує програму відкривати окремі підключення до БД або призупиняти батьківську транзакцію тощо?

Це залежить від рівня розповсюдження . Ось усі можливі значення рівня .

Наприклад, у випадку, якщо рівень поширення NESTED, поточна транзакція буде "призупинена" і буде створена нова транзакція ( примітка: фактичне створення вкладеної транзакції буде працювати лише на певних менеджерах транзакцій )

  • Яка поведінка за замовчуванням для методу без будь-яких анотацій, що викликається іншим методом із анотацією @Transactional?

Рівень розповсюдження за замовчуванням (те, що ви називаєте "поведінкою") ОБОВ'ЯЗКОВИЙ . У разі виклику "внутрішнього" методу, який містить @Transactionalанотацію (або транзакціюється декларативно через XML), він буде виконуватися в рамках тієї самої транзакції , наприклад, "нічого нового" не створюється.


А як щодо підзакликів NOT_SUPPORTED, які не мають жодних приміток? Він успадковує NOT_Supported чи вони відкрили нову транзакцію, оскільки за замовчуванням встановлено REQURED? Наприклад: f1.call () {f2 ()} з анотацією NOT_SUPPORTED для f1 та non для f2.
Дейв

8

@Transactional позначає межу транзакції (початок / кінець), але сама транзакція прив'язана до потоку. Після того, як транзакція починається, вона поширюється між викликами методів, поки оригінальний метод не повернеться і транзакція не фіксується / відкочується.

Якщо викликається інший метод, який має анотацію @Transactional, розповсюдження залежить від атрибута поширення цієї анотації.


Три відповіді певною мірою конфліктують між собою, не впевнений, що є більш точним.
Ерік Ванг

1
@EricWang Просто хотів поділитися тим, що сьогодні я випробував цей сценарій, і відповідь Аруна П. Джонні (з коментарями) є найбільш точною для цього сценарію внутрішніх викликів.
Vinay Vissh

3

Внутрішній метод вплине на зовнішній метод, якщо внутрішній метод не анотований @Transactional.

Якщо внутрішній метод також анотований @Transactional with 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, тому він встановлює свою транзакцію на відкат, але НЕ ЕФЕКТУЄ на зовнішню транзакцію. Зовнішня транзакція ПАУЗА, коли починається внутрішня транзакція, а потім ВІДНОВЛЯЄТЬСЯ ПІСЛЯ внутрішньої транзакції. Вони працюють незалежно один від одного, тому зовнішня транзакція МОЖЕ успішно здійснити транзакцію.


1
Щоб пояснити для початківців, я майже впевнений, що innerMethod () повинен знаходитись в іншому bean-файлі (він же керується Spring-об'єктом Java), ніж externalMethod (). Якщо вони обидва знаходяться на одному компоненті, я не думаю, що innerMethod насправді використовуватиме поведінку транзакцій, заявлену в своїй анотації. Швидше він використовуватиме те, що оголошено у декларації externalMethod (). Це пов’язано з тим, як Spring обробляє AOP, який використовується для його анотацій @Transactional ( docs.spring.io/spring/docs/3.0.x/spring-framework-reference/… )
johnsimer
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.