在阅读了很多 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>
任何帮助或见解将不胜感激,以便在引发异常时回滚数据库操作。