【问题标题】:Spring transaction not rolled back after an exception is thrown抛出异常后Spring事务未回滚
【发布时间】:2022-07-22 16:30:27
【问题描述】:

我有一个带有方法的服务,它没有用@Transactional注解:

@Service
@RequiredArgsConstructor
public class MainService {

    private final ServiceA serviceA;    

    public void processData() {
        List<EntityA> list = serviceA.getList();
        list.forEach(item -> {
        try {
            serviceA.doSomeDbOperations(item);
        } catch(Exception e) {
            // some processing here
        } finally {
            // some processing and DB interactions here
        }
        })
    }

}

目标是在抛出异常时回滚 try 块 (serviceA.doSomeDbOperations(item)) 中发生的更改。所以我在ServiceA中用@Transactional注释了这个方法:

@Service
public class ServiceA {
    // dependencies

    @Transactional
    public void doSomeDbOperations(EntityA item) {
        // some logic here
        repositoryA.save(item)
        serviceB.deleteSomething(input)
    }
}

serviceB.deleteSomething(input) 可能会抛出异常:

@Service
public class ServiceB {
    // dependencies
    
    public void deleteSomething(EntityA item) {
        // some logic here
        if(condition) {
            Throw new Exception();
        }        
    }
}

问题是当抛出异常时,try 块中的更改并没有回滚,数据不一致。知道问题出在哪里吗?

【问题讨论】:

  • 能否确认一下ServiceA和ServiceB也被@Service注解了?
  • Rolling back a declarative transaction: "从事务方法抛出的检查异常在默认配置中不会导致回滚"
  • @cdr89 是的。我更新了问题。

标签: java spring-boot hibernate spring-data spring-transactions


【解决方案1】:

我猜在 ServiceB 中您正在使用已检查的异常。 在 Spring 中,默认情况下事务仅在未经检查的异常上回滚,因此请尝试在 ServiceB.deleteSomething() 方法中抛出例如 RuntimeException。

如果你需要一个检查异常,你可以在你的 ServiceA.doSomeDbOperations() 方法中做这样的事情:

@Transactional(rollbackFor = Throwable.class)

一些参考资料:

https://www.baeldung.com/java-checked-unchecked-exceptions

How to make Spring @Transactional roll back on all uncaught exceptions?

【讨论】:

    猜你喜欢
    • 2015-10-03
    • 1970-01-01
    • 1970-01-01
    • 2018-08-09
    • 1970-01-01
    • 2020-09-24
    • 2016-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多