【问题标题】:REQUIRES_NEW: Spring outer transaction rollbacks also instead of persisting when inner rollbacksREQUIRES_NEW:Spring 外部事务回滚,而不是在内部回滚时持久化
【发布时间】:2021-06-19 07:23:59
【问题描述】:

我有一个 Spring Boot 应用程序,其中控制器和服务之间有一个薄层,它的唯一目的是尝试捕获,如果抛出异常,则使用 JpaRepository 保存失败的实体,以供后续检查。 我设计了我的“拦截器”:

    @Transactional
    public void upload(byte[] bytes) {
       try {
          service.upload(bytes);
       } catch (Exception e) {
           failRepo.save(new Failure(bytes, e)); // code trimmed for brevity 
           throw e;
       }
   }

我的服务方法如下:

@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public void upload(byte[] bytes);

我期望的是,如果服务中抛出异常,内部事务将被回滚,异常会弹出并且外部事务将保留我的数据,但是休眠日志显示由于某种原因外部事务也回滚并且失败数据不会被持久化。 我还需要外层的另一个传播级别吗?

编辑:相关日志

o.s.o.h.HibernateTransactionManager      : Creating new transaction with name [com.company.interceptor.upload]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
o.s.o.h.HibernateTransactionManager      : Opened new Session [SessionImpl(480607911<open>)] for Hibernate transaction
o.h.e.t.internal.TransactionImpl         : On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
o.h.e.t.internal.TransactionImpl         : begin
o.s.o.h.HibernateTransactionManager      : Exposing Hibernate transaction as JDBC [org.springframework.orm.hibernate5.HibernateTransactionManager$$Lambda$1317/0x0000000800d0c440@52318830]
o.s.o.h.HibernateTransactionManager      : Found thread-bound Session [SessionImpl(480607911<open>)] for Hibernate transaction
o.s.o.h.HibernateTransactionManager      : Suspending current transaction, creating new transaction with name [com.company.service.upload]
o.s.o.h.HibernateTransactionManager      : Opened new Session [SessionImpl(1041560268<open>)] for Hibernate transaction
o.h.e.t.internal.TransactionImpl         : On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
o.h.e.t.internal.TransactionImpl         : begin
o.s.o.h.HibernateTransactionManager      : Exposing Hibernate transaction as JDBC [org.springframework.orm.hibernate5.HibernateTransactionManager$$Lambda$1317/0x0000000800d0c440@778c9da3]

------ other irrelevant for us logs

o.s.o.h.HibernateTransactionManager      : Initiating transaction rollback
o.s.o.h.HibernateTransactionManager      : Rolling back Hibernate transaction on Session [SessionImpl(1041560268<open>)]
o.h.e.t.internal.TransactionImpl         : rolling back
o.s.o.h.HibernateTransactionManager      : Closing Hibernate Session [SessionImpl(1041560268<open>)] after transaction
o.s.o.h.HibernateTransactionManager      : Resuming suspended transaction after completion of inner transaction
stomAnnotationTransactionAttributeSource : Adding transactional method 'save' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
o.s.o.h.HibernateTransactionManager      : Found thread-bound Session [SessionImpl(480607911<open>)] for Hibernate transaction
o.s.o.h.HibernateTransactionManager      : Participating in existing transaction
org.hibernate.engine.spi.ActionQueue     : Executing identity-insert immediately
org.hibernate.SQL                        : insert into failure_table (content_type, created_time, exception_message, bytes, user_agent) values (?, ?, ?, ?, ?)
o.h.id.IdentifierGeneratorHelper         : Natively generated identity: 15
o.h.r.j.i.ResourceRegistryStandardImpl   : HHH000387: ResultSet's statement was not registered
o.s.o.h.HibernateTransactionManager      : Initiating transaction rollback
o.s.o.h.HibernateTransactionManager      : Rolling back Hibernate transaction on Session [SessionImpl(480607911<open>)]
o.h.e.t.internal.TransactionImpl         : rolling back
o.s.o.h.HibernateTransactionManager      : Closing Hibernate Session [SessionImpl(480607911<open>)] after transaction

【问题讨论】:

  • 请提供日志。另外,能否在调试模式下检查代码流,看看是否捕获了异常?
  • @aksappy 是的,在 catch 子句中成功捕获了异常,Failure 对象创建得很好,异常被重新抛出。唯一的问题是失败没有持续存在。更新了问题以包含相关日志。
  • 请提供您的源代码。我看不到您在外部事务中插入内容的位置
  • FailRepo 是一个 JpaRepository,我在其上调用默认的 save() 方法。编辑了问题。

标签: java spring hibernate spring-data spring-transactions


【解决方案1】:

https://stackoverflow.com/a/7125918/3214777 帮助找到的问题解决方案。

问题是 Spring 默认在运行时异常时回滚,所以我需要一个

@Transactional(noRollbackFor = Exception.class)

在我的拦截器上让它按我预期的那样运行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-17
    • 2014-11-12
    • 2019-01-21
    • 1970-01-01
    • 2021-10-15
    • 1970-01-01
    • 2017-11-21
    相关资源
    最近更新 更多