春天总是为REQUIRES_NEW创建新的事务,无论是否存在已有事务。但是,在哪种情况下Spring不会创建新的事务,而是参与现有事务呢?
以下是不会创建新事务,而是参与现有事务的情况。
所有方法,mainMethod、methodA()、methodB()和logExceptionMethod()都在不同的bean中, 理想情况下,当methodB()失败时,异常将在catch块中捕获,并且logExceptionMethod()将通过创建新事务来审计日志。
但是在这里,即使logExceptionMethod()方法被标注为requires_new并且是公共的且位于不同的bean中,也没有启动新的事务,而是参与现有事务,导致回滚。
mainMethod - Propagation.REQUIRES methodA - Propagation.REQUIRES_NEW methodB - 未标注 logExceptionMethod - Propagation.REQUIRES_NEW
流程
@Transactional
mainMethod() {
try{
methodA();
} catch(Exception e) {
throw e;
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
methodA(){
try{
methodB()
}
catch(Exception e) {
throw e;
}
}
methodB(){
try {
// api call gives exception
}
catch(Exception e) {
logExceptionMethod();
throw e;
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
logExceptionMethod() {
// create log entity
// store entity in db
}
日志
DEBUG o.s.orm.jpa.JpaTransactionManager - 1F2EA187-C884-461C-8183-328A4B7621D0 - Creating new transaction with name [mainMethod]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
DEBUG o.s.orm.jpa.JpaTransactionManager - 1F2EA187-C884-461C-8183-328A4B7621D0 - Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@53f498b2]
TRACE o.s.t.i.TransactionInterceptor - 1F2EA187-C884-461C-8183-328A4B7621D0 - Getting transaction for [mainMethod]
TRACE o.s.d.r.c.s.TransactionalRepositoryProxyPostProcessor$RepositoryAnnotationTransactionAttributeSource - 1F2EA187-C884-461C-8183-328A4B7621D0 - Adding transactional method 2023-08-11 03:04:13 [qtp1482177069-1382]
TRACE o.s.b.f.s.DefaultListableBeanFactory - 1F2EA187-C884-461C-8183-328A4B7621D0 - Returning cached instance of singleton bean 'transactionManager'
DEBUG o.s.orm.jpa.JpaTransactionManager - 1F2EA187-C884-461C-8183-328A4B7621D0 - Found thread-bound EntityManager [SessionImpl(1543398267<open>)] for JPA transaction
INFO - 1F2EA187-C884-461C-8183-328A4B7621D0 - Current transaction : mainMethod
DEBUG o.s.orm.jpa.JpaTransactionManager - 1F2EA187-C884-461C-8183-328A4B7621D0 - Found thread-bound EntityManager [SessionImpl(1543398267<open>)] for JPA transaction
DEBUG o.s.orm.jpa.JpaTransactionManager - 1F2EA187-C884-461C-8183-328A4B7621D0 - Suspending current transaction, creating new transaction with name [methodA]
DEBUG o.s.orm.jpa.JpaTransactionManager - 1F2EA187-C884-461C-8183-328A4B7621D0 - Opened new EntityManager [SessionImpl(1186799888<open>)] for JPA transaction
DEBUG o.s.orm.jpa.JpaTransactionManager - 1F2EA187-C884-461C-8183-328A4B7621D0 - Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@54c9937c]
TRACE o.s.t.i.TransactionInterceptor - 1F2EA187-C884-461C-8183-328A4B7621D0 - Getting transaction for [methodA]
INFO- 1F2EA187-C884-461C-8183-328A4B7621D0 - Current transaction : methodA
ERROR - 1F2EA187-C884-461C-8183-328A4B7621D0 - Exception Occured
TRACE o.s.d.r.c.s.TransactionalRepositoryProxyPostProcessor$RepositoryAnnotationTransactionAttributeSource - 1F2EA187-C884-461C-8183-328A4B7621D0 - Adding transactional method 'org.springframework.data.jpa.repository.support.SimpleJpaRepository.save' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
TRACE o.s.b.f.s.DefaultListableBeanFactory - 1F2EA187-C884-461C-8183-328A4B7621D0 - Returning cached instance of singleton bean
'transactionManager'
DEBUG o.s.orm.jpa.JpaTransactionManager - 1F2EA187-C884-461C-8183-328A4B7621D0 - Found thread-bound EntityManager [SessionImpl(1186799888<open>)] for JPA transaction
DEBUG o.s.orm.jpa.JpaTransactionManager - 1F2EA187-C884-461C-8183-328A4B7621D0 - Participating in existing transaction
INFO - 1F2EA187-C884-461C-8183-328A4B7621D0 - Added entry in log
TRACE o.s.t.i.TransactionInterceptor - 1F2EA187-C884-461C-8183-328A4B7621D0 - Completing transaction for [methodA] after exception:
DEBUG o.s.orm.jpa.JpaTransactionManager - 1F2EA187-C884-461C-8183-328A4B7621D0 - Initiating transaction rollback
DEBUG o.s.orm.jpa.JpaTransactionManager - 1F2EA187-C884-461C-8183-328A4B7621D0 - Rolling back JPA transaction on EntityManager [SessionImpl(1186799888<open>)]
DEBUG o.s.orm.jpa.JpaTransactionManager - 1F2EA187-C884-461C-8183-328A4B7621D0 - Closing JPA EntityManager [SessionImpl(1186799888<open>)] after transaction
DEBUG o.s.orm.jpa.JpaTransactionManager - 1F2EA187-C884-461C-8183-328A4B7621D0 - Resuming suspended transaction after completion of inner transaction
TRACE o.s.t.i.TransactionInterceptor - 1F2EA187-C884-461C-8183-328A4B7621D0 - Completing transaction for [mainMethod] after exception:
DEBUG o.s.orm.jpa.JpaTransactionManager - 1F2EA187-C884-461C-8183-328A4B7621D0 - Initiating transaction rollback
DEBUG o.s.orm.jpa.JpaTransactionManager - 1F2EA187-C884-461C-8183-328A4B7621D0 - Rolling back JPA transaction on EntityManager [SessionImpl(1543398267<open>)]
DEBUG o.s.orm.jpa.JpaTransactionManager - 1F2EA187-C884-461C-8183-328A4B7621D0 - Not closing pre-bound JPA EntityManager after transaction
现在我可以使用特定的noRollbackFor属性来防止事务回滚,但是主要问题仍然是:
1. 为什么Spring没有创建新的事务? 2. 在什么情况下会发生这种情况?