1

在阅读了很多 SO 材料并搜索了任何可能的途径之后,我求助于您:

我在@service 类中有一个公共方法,它通过@repository 提交一些事务。尽管我声明事务在异常时回滚(并且还尝试涵盖更通用的类,例如运行时异常、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);
        }
    }

最后,这就是我从 main 调用方法的方式:

    @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();
}

pom.xml 文件(包括 spring-boot-autoconfigure 依赖项)如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.9.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.my-project</groupId>
    <artifactId>project</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>project-name</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

任何帮助或见解将不胜感激,以便在引发异常时回滚数据库操作。

4

0 回答 0