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)
希望有用
好的伙计们。我已经阅读了很多文档。我不知道为什么会这样。
像许多其他人一样,我们有一个与 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)
希望有用