Spring @Transactional 在出现异常时不断回滚事务

Spring @Transactional is consistantly rolling back transaction upon exception

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

像许多其他人一样,我们有一个与 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"

看,它试图按预期回滚。但问题是 stuffA 在数据库中徘徊会 stuffB 而 stuffC 不是。这种情况只有 1% 的概率会发生。 (又名,有时尽管回滚失败,没有 'stuff' 会在数据库中。

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

p.s。物有所值。自动提交默认为开启。但是我读到当某些东西是@Transactional

时没有考虑到它

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

也就是说,在某些数据库上,有一些方法可以在您的应用程序或 Spring 不可见的外部事务中执行自主事务。我知道 Oracle 允许这样做。你检查过桌子上的所有触发器了吗?我开发了一个应用程序,它有一个审计触发器,在这种情况下会强制孤立数据进入某些表。你能告诉我们你使用的是哪个数据库吗?

来自Database JDBC Developer's Guide

If the auto-commit mode is disabled and you close the connection without explicitly committing or rolling back your last changes, then an implicit COMMIT operation is run.

也许您 运行 就是这种情况。

试试这个:

@Transactional(propagation = Propagation.REQUIRES_NEW)

希望有用