Spring @Transactional 不在 MS 上开始新事务 SQL
Spring @Transactional does not begin new transaction on MS SQL
我在 Spring 使用 @Transactional 注释启动时遇到事务问题。最新的 Spring 已连接到 MS SQL 数据库。
我有以下服务,它根据一些标准定期执行事务方法:
@Service
public class SomeService {
SomeRepository repository;
public SomeService(SomeRepository someRepository) {
this.repository = someRepository;
}
@Scheduled(fixedDelayString="${property}") //10 seconds
protected scheduledIteration() {
if(something) {
insertDataInNewTransaction(getSomeData());
}
}
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
protected void insertDataInNewTransaction(List<Data> data) {
//insert data to db
repository.saveAll(data);
//call verify proc
repository.verifyData();
}
}
该算法应该处理数据,将它们插入 table 并执行检查(数据库过程)。如果过程抛出异常,事务应该被回滚。我敢肯定,该过程不会执行事务的提交。
我面临的问题是,调用该方法不会开始新的事务(或开始但它是自动提交的),因为我尝试了以下操作:
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
protected void insertDataInNewTransaction(List<Data> data) {
int counter = 0;
for(Data d : data) {
repository.save(d);
counter++;
//test
if(counter == 10) {
throw new Exception("test");
}
}
}
执行测试方法后,前 10 行保留在 table 中,它们应该被回滚。在调试期间我注意到,在循环中调用 repository.save()
会插入到 table 外部事务,因为我可以在调试器位于下一行时看到来自 DB IDE 的行。这给了我一个想法,问题是由自动提交引起的,因为它是 MS SQL 默认值。所以我尝试添加以下属性,但没有任何区别:
spring.datasource.hikari.auto-commit=false
spring.datasource.auto-commit=false
我做错了什么吗?
如果使用Spring Proxy AOP,那么需要将方法insertDataInNewTransaction转为public.
请记住,如果方法是 public,但它是从同一个 bean 调用的,它不会创建新事务(因为 spring 代理不会被调用)。
简答:
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void insertDataInNewTransaction(List<Data> data) {
//insert data to db
repository.saveAll(data);
//call verify proc
repository.verifyData();
}
但如果您真的需要一个新的单独交易,请使用 Propagation.REQUIRES_NEW
而不是 Propagation.REQUIRED
。
我在 Spring 使用 @Transactional 注释启动时遇到事务问题。最新的 Spring 已连接到 MS SQL 数据库。
我有以下服务,它根据一些标准定期执行事务方法:
@Service
public class SomeService {
SomeRepository repository;
public SomeService(SomeRepository someRepository) {
this.repository = someRepository;
}
@Scheduled(fixedDelayString="${property}") //10 seconds
protected scheduledIteration() {
if(something) {
insertDataInNewTransaction(getSomeData());
}
}
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
protected void insertDataInNewTransaction(List<Data> data) {
//insert data to db
repository.saveAll(data);
//call verify proc
repository.verifyData();
}
}
该算法应该处理数据,将它们插入 table 并执行检查(数据库过程)。如果过程抛出异常,事务应该被回滚。我敢肯定,该过程不会执行事务的提交。
我面临的问题是,调用该方法不会开始新的事务(或开始但它是自动提交的),因为我尝试了以下操作:
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
protected void insertDataInNewTransaction(List<Data> data) {
int counter = 0;
for(Data d : data) {
repository.save(d);
counter++;
//test
if(counter == 10) {
throw new Exception("test");
}
}
}
执行测试方法后,前 10 行保留在 table 中,它们应该被回滚。在调试期间我注意到,在循环中调用 repository.save()
会插入到 table 外部事务,因为我可以在调试器位于下一行时看到来自 DB IDE 的行。这给了我一个想法,问题是由自动提交引起的,因为它是 MS SQL 默认值。所以我尝试添加以下属性,但没有任何区别:
spring.datasource.hikari.auto-commit=false
spring.datasource.auto-commit=false
我做错了什么吗?
如果使用Spring Proxy AOP,那么需要将方法insertDataInNewTransaction转为public.
请记住,如果方法是 public,但它是从同一个 bean 调用的,它不会创建新事务(因为 spring 代理不会被调用)。
简答:
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void insertDataInNewTransaction(List<Data> data) {
//insert data to db
repository.saveAll(data);
//call verify proc
repository.verifyData();
}
但如果您真的需要一个新的单独交易,请使用 Propagation.REQUIRES_NEW
而不是 Propagation.REQUIRED
。