Springboot 嵌套事务中内层事务Propagation.REQUIRES_NEW不生效

类似下面这种构造

外层A是默认的事务(),内层B选择了REQUIRES_NEW,期待B的业务可以独立commit

但是结果是,只有A的业务完全结束了,B才能一起commit
这个和我对REQUIRES_NEW的理解不一样,有木有大佬教教我呜呜

@Service
public class A {
    @Autowired
    B b;
 
    @Async
    @Transactional
    public void execute() {
        //其他业务
        b.method()
        //其他业务
    }
}

@Service
public class B {
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void method() {
        //...
    }
}

破案了,

写一下我的debug流程
首先、在DataSourceTransactionManager的doCommit进行了断点,确认了只有一次commit
那就说明requires_new失效了
思考了一下springboot中事务失效的几大可能性
感觉还是代理的问题
于是debug模式下仔细看了一下A类和B类2个bean
发现B类的bean的debug信息中没有springclibproxy字样,也就是说没有自动代理?

然后我注意到B类是一个比较特殊的类,在启动时其实有提示它不能自动代理↓
INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - xxxxxxxx is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

阅读 5.3k
3 个回答

很好验证你的想法,自己注入DataSourceTransactionManager事务管理器(或者debug事务管理器也是一样的道理),看docommit会执行几次,执行两次那就是默认场景,new会单独提交,执行一次那就是打破你的认知,事务传播下去了,两次没说好说的,一次那就要分享你的代码了,让大家开开眼,改了什么配置

大概是数据库的 session 阻止你提交了,如果你在 b.method 里修改的记录,在 a.execute 也进行了修改,数据库层面就会阻塞该 session,直到这些事务都完成,再进行处理。

事务的隔离一帮场景应该是作用在不用的表上才需要使用的,如果是同表操作的话理应是不需要事务级别的隔离的。

这个策略貌似在数据库是可以修改的(具体的我也不太清楚哈)。

并没有测试出你的结果。

2022-04-27 20:24:09.229 DEBUG 11420 --- [nio-8080-exec-5] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.weiliang.dbmqRollback.controller.DemoController#dd()
2022-04-27 20:24:09.229 DEBUG 11420 --- [nio-8080-exec-5] o.j.s.OpenEntityManagerInViewInterceptor : Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
2022-04-27 20:24:09.229 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(413240813<open>)] for JPA transaction
2022-04-27 20:24:09.229 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [com.weiliang.dbmqRollback.service.DemoServiceImpl.roll]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2022-04-27 20:24:09.229 DEBUG 11420 --- [nio-8080-exec-5] o.h.e.t.internal.TransactionImpl         : On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
2022-04-27 20:24:09.229 DEBUG 11420 --- [nio-8080-exec-5] o.h.e.t.internal.TransactionImpl         : begin
2022-04-27 20:24:09.232 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@1c9e1a21]
2022-04-27 20:24:10.576 DEBUG 11420 --- [alina-utility-1] org.apache.catalina.session.ManagerBase  : Start expire sessions StandardManager at 1651062250576 sessioncount 0
2022-04-27 20:24:10.576 DEBUG 11420 --- [alina-utility-1] org.apache.catalina.session.ManagerBase  : End expire sessions StandardManager processingTime 0 expired sessions: 0
2022-04-27 20:24:11.266 DEBUG 11420 --- [l-1 housekeeper] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Pool stats (total=10, active=1, idle=9, waiting=0)
2022-04-27 20:24:11.266 DEBUG 11420 --- [l-1 housekeeper] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Fill pool skipped, pool is at sufficient level.
2022-04-27 20:24:15.038 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(413240813<open>)] for JPA transaction
2022-04-27 20:24:15.038 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Participating in existing transaction
2022-04-27 20:24:15.038 DEBUG 11420 --- [nio-8080-exec-5] org.hibernate.engine.spi.ActionQueue     : Executing identity-insert immediately
2022-04-27 20:24:15.038 DEBUG 11420 --- [nio-8080-exec-5] org.hibernate.SQL                        : insert into demo (age, name) values (?, ?)
Hibernate: insert into demo (age, name) values (?, ?)
2022-04-27 20:24:15.041 DEBUG 11420 --- [nio-8080-exec-5] o.h.id.IdentifierGeneratorHelper         : Natively generated identity: 58
2022-04-27 20:24:15.042 DEBUG 11420 --- [nio-8080-exec-5] o.h.r.j.i.ResourceRegistryStandardImpl   : HHH000387: ResultSet's statement was not registered
2022-04-27 20:24:15.042 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(413240813<open>)] for JPA transaction
2022-04-27 20:24:15.042 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Suspending current transaction, creating new transaction with name [com.weiliang.dbmqRollback.service.Demo2ServiceImpl.roll2]
2022-04-27 20:24:15.042 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(1778155779<open>)] for JPA transaction
2022-04-27 20:24:15.042 DEBUG 11420 --- [nio-8080-exec-5] o.h.e.t.internal.TransactionImpl         : On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
2022-04-27 20:24:15.042 DEBUG 11420 --- [nio-8080-exec-5] o.h.e.t.internal.TransactionImpl         : begin
2022-04-27 20:24:15.044 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@7c08a836]
2022-04-27 20:24:15.044 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(1778155779<open>)] for JPA transaction
2022-04-27 20:24:15.044 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Participating in existing transaction
2022-04-27 20:24:15.045 DEBUG 11420 --- [nio-8080-exec-5] org.hibernate.engine.spi.ActionQueue     : Executing identity-insert immediately
2022-04-27 20:24:15.045 DEBUG 11420 --- [nio-8080-exec-5] org.hibernate.SQL                        : insert into demo (age, name) values (?, ?)
Hibernate: insert into demo (age, name) values (?, ?)
2022-04-27 20:24:15.047 DEBUG 11420 --- [nio-8080-exec-5] o.h.id.IdentifierGeneratorHelper         : Natively generated identity: 59
2022-04-27 20:24:15.047 DEBUG 11420 --- [nio-8080-exec-5] o.h.r.j.i.ResourceRegistryStandardImpl   : HHH000387: ResultSet's statement was not registered
2022-04-27 20:24:15.047 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction commit
2022-04-27 20:24:15.047 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Committing JPA transaction on EntityManager [SessionImpl(1778155779<open>)]
2022-04-27 20:24:15.047 DEBUG 11420 --- [nio-8080-exec-5] o.h.e.t.internal.TransactionImpl         : committing
2022-04-27 20:24:15.047 DEBUG 11420 --- [nio-8080-exec-5] o.h.e.i.AbstractFlushingEventListener    : Processing flush-time cascades
2022-04-27 20:24:15.047 DEBUG 11420 --- [nio-8080-exec-5] o.h.e.i.AbstractFlushingEventListener    : Dirty checking collections
2022-04-27 20:24:15.048 DEBUG 11420 --- [nio-8080-exec-5] o.h.e.i.AbstractFlushingEventListener    : Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects
2022-04-27 20:24:15.048 DEBUG 11420 --- [nio-8080-exec-5] o.h.e.i.AbstractFlushingEventListener    : Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
2022-04-27 20:24:15.048 DEBUG 11420 --- [nio-8080-exec-5] o.hibernate.internal.util.EntityPrinter  : Listing entities:
2022-04-27 20:24:15.048 DEBUG 11420 --- [nio-8080-exec-5] o.hibernate.internal.util.EntityPrinter  : com.weiliang.dbmqRollback.pojo.Demo{name=two, id=59, age=10}
2022-04-27 20:24:15.063 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Closing JPA EntityManager [SessionImpl(1778155779<open>)] after transaction
2022-04-27 20:24:15.063 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Resuming suspended transaction after completion of inner transaction
2022-04-27 20:24:15.064 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction rollback
2022-04-27 20:24:15.064 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Rolling back JPA transaction on EntityManager [SessionImpl(413240813<open>)]
2022-04-27 20:24:15.064 DEBUG 11420 --- [nio-8080-exec-5] o.h.e.t.internal.TransactionImpl         : rolling back
2022-04-27 20:24:15.068 DEBUG 11420 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Not closing pre-bound JPA EntityManager after transaction
2022-04-27 20:24:15.069 DEBUG 11420 --- [nio-8080-exec-5] o.j.s.OpenEntityManagerInViewInterceptor : Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
2022-04-27 20:24:15.069 DEBUG 11420 --- [nio-8080-exec-5] o.s.web.servlet.DispatcherServlet        : Failed to complete request: java.lang.ArithmeticException: / by zero
2022-04-27 20:24:15.069 DEBUG 11420 --- [nio-8080-exec-5] o.s.s.w.h.S.SESSION_LOGGER               : No session found by id: Caching result for getSession(false) for this HttpServletRequest.
2022-04-27 20:24:15.070 ERROR 11420 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[.[dispatcherServlet]      : Servlet.service() for servlet [dispatcherServlet] in context with path [/boot] threw exception [Request processing failed; nested exception is java.lang.ArithmeticException: / by zero] with root cause

java.lang.ArithmeticException: / by zero

从中可以看出是提交了的。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题