首页 > 解决方案 > Spring @Transactional 在异常时始终如一地回滚事务

问题描述

好吧,伙计们。我已经阅读了很多文档。我不知道为什么会这样。

像许多其他人一样,我们有一个与 Oracle 数据库接口的服务。这是一个非常标准的设置

@Service
public class DaoService {

    private JdbcTemplate jdbcTemplate;

    private SimpleJdbcInsert insertA;
    private SimpleJdbcInsert insertB;
    private SimpleJdbcInsert insertC;

    @Autowired
    public Dao(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
        // Assume all Inserts are initialized
    }

    @Transactional(rollbackFor = Exception.class)
    public void insertStuff(Stuff stuff) {
         insertA.execute(stuff.A);
         // Suppose a connection failed here
         insertB.executeBatch(stuff.B);
         insertC.executeBatch(stuff.C);
}

现在这就是我们的问题。对于 99% 的回滚,它们是正常的。

当连接因未知原因而关闭时,就会出现问题。异常消息是

 TransactionSystemException: Could not roll back JDBC transaction;
     nested exception is java.sql.SQLException: "The connection is closed"

看,它试图按预期回滚。但问题是在 DB 中的 stuffA 会在 stuffB 中徘徊,而 stuffC 不会。这种情况只发生在 1% 的时间里。(又名,有时尽管回滚失败,但数据库中不会有任何“东西”。

我理解错了吗?我认为spring只在成功交易结束时提交?尽管在@Transactional 中进行,任何人都知道如何停止这些部分提交?

ps 值多少钱。自动提交默认为开启。但是我读到当某事是@Transactional 时没有考虑到它

标签: javaspringspring-datarollbacktransactional

解决方案


根据这个答案,Spring 只为您提供事务管理器的接口,实现可能会有所不同。但是,大多数事务管理器实现将在 @Transactional 调用期间关闭自动提交,然后在提交后将其返回到先前的状态。

话虽如此,在某些数据库上,有一些方法可以在您的应用程序或 Spring 可能看不到的外部事务中执行自治事务。我知道甲骨文允许这样做。您是否检查了表上的所有触发器?我开发了一个应用程序,它有一个审计触发器,在这种情况下会强制将孤立数据放入某些表中。您能告诉我们您使用的是哪个数据库吗?


推荐阅读