Когда вы вызываете метод вне @Transactional
блока транзакции, родительская транзакция перейдет к новому методу. Он будет использовать то же соединение из родительского метода (с @Transactional
) и любое исключение, вызванное в вызываемом методе (без этого @Transactional
будет откат транзакции, как настроено в определении транзакции.
Если вы вызываете метод с @Transactional
аннотацией из метода @Transactional
в том же экземпляре, то транзакционное поведение вызываемых методов не будет иметь никакого влияния на транзакцию. Но если вы вызываете метод с определением транзакции из другого метода с определением транзакции, и они находятся в разных экземплярах, то код в вызываемом методе будет следовать определениям транзакции, данным в вызываемом методе.
Более подробную информацию можно найти в разделе « Декларативное управление транзакциями» документации по весенним транзакциям .
Модель декларативной транзакции Spring использует прокси AOP. Таким образом, за создание транзакций отвечает AOP-прокси. Прокси-сервер AOP будет активен только в том случае, если методы, содержащиеся в экземпляре, вызываются извне экземпляра.
will follow the transaction definitions given in the called method
. Но если вызов исходит от того же экземпляра объекта, он не будет иметь никакого эффекта, поскольку вызов не будет распространяться через прокси-серверы aop, которые отвечают за обслуживание транзакции.@Transactional
определением из другого объекта / экземпляра, тогда, даже если вызывающий метод имеет другие@Transactional
атрибуты, вызываемый метод будет следовать своему собственному определению транзакции.Это зависит от уровня распространения . Вот все возможные значения уровней .
Например, если уровень распространения - ВСТАВЛЕННЫЙ, текущая транзакция будет «приостановлена» и будет создана новая транзакция ( примечание: фактическое создание вложенной транзакции будет работать только для определенных менеджеров транзакций )
Уровень распространения по умолчанию (то, что вы называете «поведением») ТРЕБУЕТСЯ . В случае вызова «внутреннего» метода, который имеет
@Transactional
аннотацию (или транзакция декларативно выполняется через XML), он будет выполняться в рамках той же транзакции , например, «ничего нового» не создается.источник
@Transactional отмечает границу транзакции (начало / конец), но сама транзакция привязана к потоку. После запуска транзакция распространяется по вызовам методов до тех пор, пока исходный метод не вернется, а транзакция не зафиксируется / не откатится.
Если вызывается другой метод с аннотацией @Transactional, то распространение зависит от атрибута распространения этой аннотации.
источник
Внутренний метод повлияет на внешний метод, если внутренний метод не аннотирован @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, поэтому он установит для своей транзакции откат, но НЕ ВЛИЯЕТ на внешнюю транзакцию. Внешняя транзакция приостанавливается, когда начинается внутренняя транзакция, и затем ВОЗОБНОВЛЯЕТСЯ ПОСЛЕ завершения внутренней транзакции. Они работают независимо друг от друга, поэтому внешняя транзакция МОЖЕТ успешно зафиксироваться.источник