spring boot @transactional不会在异常时回滚,声称Winning回滚规则是:具有模式的RollbackRuleAttribute

问题描述 投票:0回答:1

阅读了很多SO资料并搜索了所有可能的途径后,我求助于您:

我在@service类中有一个公共方法,该方法通过@repository提交一些事务。尽管我声明事务将在Exception时回滚(并尝试覆盖更通用的类,例如Runtime Exception,Throwable等),但它不会回滚,即使在抛出上述异常后仍会在数据库中提交。在日志级别上记录事务后,这些是我得到的行:

Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.updateCategoryOrder]
2020-01-01 14:22:40.795 TRACE 1580 --- [           main] .s.t.s.TransactionSynchronizationManager : Removed value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@66a50c93] for key [public abstract void com.aliza.davening.repositories.CategoryRepository.updateCategoryOrder(int,long)] from thread [main]
2020-01-01 14:22:40.795 TRACE 1580 --- [           main] o.s.t.i.TransactionInterceptor           : Completing transaction for [com.aliza.davening.services.AdminService.changeCategoryOrder] after exception: exceptions.ReorderCategoriesException: Now everything should stay the same.
2020-01-01 14:22:40.795 TRACE 1580 --- [           main] o.s.t.i.RuleBasedTransactionAttribute    : Applying rules to determine whether transaction should rollback on exceptions.ReorderCategoriesException: Now everything should stay the same.
2020-01-01 14:22:40.795 TRACE 1580 --- [           main] o.s.t.i.RuleBasedTransactionAttribute    : 
**Winning rollback rule is: RollbackRuleAttribute with pattern [exceptions.ReorderCategoriesException]**
2020-01-01 14:22:40.795 TRACE 1580 --- [           main] .s.t.s.TransactionSynchronizationManager : Clearing transaction synchronization
2020-01-01 14:22:40.795 TRACE 1580 --- [           main] .s.t.s.TransactionSynchronizationManager : Removed value [org.springframework.orm.jpa.EntityManagerHolder@6442cf3e] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@7e1fb22c] from thread [main]
2020-01-01 14:22:40.795 TRACE 1580 --- [           main] .s.t.s.TransactionSynchronizationManager : Removed value [org.springframework.jdbc.datasource.ConnectionHolder@7b4c793b] for key [HikariDataSource (HikariPool-1)] from thread [main]
Exception in thread "main" exceptions.ReorderCategoriesException: Now everything should stay the same.

[从日志中看来,他确实研究了回滚的选项,并且只是停留在评估我提供的规则是否足够。我大胆的“制胜法则”是否意味着他得出结论要退后?如果是这样,为什么要进行交易?

或者,如果“获胜规则”意味着他得出的结论是我提供的规则不足以回滚,那么如何使此回滚规则起作用?

这里是代码:

    @Service("adminService")
    @EnableTransactionManagement
    @Transactional(rollbackFor = ReorderCategoriesException.class)
    public class AdminService {

            public void changeCategoryOrder() 
                throws ReorderCategoriesException {

                //updateCategoryOrder accepts the order and id of a category
                categoryRepository.updateCategoryOrder(1, 4);
                categoryRepository.updateCategoryOrder(2,11);
                categoryRepository.updateCategoryOrder(3, 9);

                //this exception should in theory cause the previous commits to rollback, I would think?
                throw new ReorderCategoriesException("Now everything should stay the same.");

        }
    }

这里是执行数据库操作的存储库类:

@Repository
public interface CategoryRepository extends JpaRepository<Category, Long> {

    @Modifying
    @Transactional
    @Query("update Category set catOrder=?1 where id=?2")
        public void updateCategoryOrder(int newOrder, long categoryId);
}

异常的定义如下:(我尝试从Exception和RuntimeException继承,结果相同)

    package exceptions;

    @SuppressWarnings("serial")
    public class ReorderCategoriesException extends RuntimeException {

        public ReorderCategoriesException(String msg) {
            super(msg);
        }
    }

最后,这就是我从主要位置调用方法的方式:

    @SpringBootApplication
    @EnableAutoConfiguration
    @EnableTransactionManagement
    public class MyApplication {

        public static void main(String[] args) throws ReorderCategoriesException {

            ConfigurableApplicationContext context = SpringApplication.run(MyApplication.class, args);

            AdminService adminService = context.getBean(AdminService.class);

            adminService.changeCategoryOrder();
}

任何帮助或见解,都会引发异常时回滚数据库操作。

spring-boot exception transactions rollback
1个回答
0
投票

每个categoryRepository.updateCategoryOrder()均在自己的事务上运行。它在每次更新调用后提交,因此数据得以保留。

更新CategoryRepository @Transactional批注以使用当前事务(在AdminService中启动的事务)

  @Transactional(propagation = Propagation.REQUIRED ) 
  @Query("update Category set catOrder=?1 where id=?2")
  public void updateCategoryOrder(int newOrder, long categoryId);

此更改应在一个事务下运行所有​​更新(该更新在AdminService中启动,并且应在最后的ReorderCategoriesException上回滚。

事务性Propogation的API参考

© www.soinside.com 2019 - 2024. All rights reserved.