【问题标题】:Rollback inner transaction affects the outer transaction in hibernate spring回滚内部事务影响hibernate spring中的外部事务
【发布时间】:2021-10-15 04:33:40
【问题描述】:

@Service
@Transactional
public class Service1 {
    
    @Autowired
    Service2 service2;

    public void method1(){
        //read some records from db
         List<Record> recordList = getFromSomewhere();
            method2(recordList);

        //persist the records to db of whatever updates were made to them

    }
}


@Service
@Transactional
public class Service2 {

    @Autowired
    Service3 service3;

    private final TransactionTemplate transactionTemplate;

    public Service2(DataSourceTransactionManager transactionManager) {
        this.transactionTemplate = new TransactionTemplate(transactionManager);
    }

    public void method2(List<Record> recordList) {
        //process the records one by one
        


        transactionTemplate.execute(new TransactionCallback<>() {
                @Override
                public String doInTransaction(TransactionStatus status) {
                    try {
                        service3.process(record);
                        return "done";
                    } catch (Exception e) {
                        e.printStackTrace();
                        return "failed";
                    }
                }
            });
    }

}


@Service
@Transactional(rollbackFor = Exception.class)
public class Service3 {


    // Process method has to be all or none
    public void process(Record record) {
        //will throw custom/any exception
        //everything here should rollback if any exception occurs
        //this also updates the Record object
    }

}

在上面的代码中,我期望的是,即使 Service3 的 process 方法抛出异常并尝试回滚,Service1 的 method1 也必须提交记录。提交不应失败。 截至目前 UnexpectedRollbackException 被抛出。据我说,它试图坚持,但就在它退出方法1之前,看到了下面的异常。 org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

请告知需要使用任何传播策略或任何其他方式。 注意:不能更改 Service3 类的 (rollbackFor = Exception.class)。

简而言之:如果内部事务失败,外部事务应该能够无错误地持续下去。

Language: Java 11
Framework: Spring boot (2.2.12.RELEASE) + Hibernate 
Database: Mysql 8

【问题讨论】:

  • 有什么帮助吗?
  • 如果无法避免将主事务标记为仅回滚,则必须在新事务中运行 method3。使用事务传播REQUIRES_NEW

标签: spring spring-boot hibernate transactions rollback


【解决方案1】:

假设您不能真正将Service3 上的@Transactional(rollbackFor = Exception.class) 更改为@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)Service2 上的以下更改应该有效:

public void method2(List<Record> recordList) {
    //process the records one by one

    transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
    transactionTemplate.execute(new TransactionCallback<>() {
            @Override
            public String doInTransaction(TransactionStatus status) {
                try {
                    service3.process(record);
                    return "done";
                } catch (Exception e) {
                    e.printStackTrace();
                    return "failed";
                }
            }
        });
}

【讨论】:

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