Database 当Spring Propagation.REQUIRES\u NEW嵌套在Propagation.nested中时的行为
我有这样的代码Database 当Spring Propagation.REQUIRES\u NEW嵌套在Propagation.nested中时的行为,database,spring,postgresql,spring-transactions,Database,Spring,Postgresql,Spring Transactions,我有这样的代码 @Transactional(propagation = Propagation.NESTED) @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) public class C1 { ... public void xxx() { try { obj.someMethod(); } catch (E
@Transactional(propagation = Propagation.NESTED)
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class C1 {
...
public void xxx() {
try {
obj.someMethod();
} catch (Exception e) {
C2.yyy();
}
}
}
public class C2 {
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false)
public void yyy() {
...
}
}
我的假设是当obj.someMethod()时
抛出一个约束冲突异常C2.yyy()
应该仍然能够将内容保存到数据库中
然而,我看到的是,当C2.yyy()
被称为Postgres reports时
错误:当前事务中止,在事务块结束之前忽略命令
它为什么要这样做?毕竟,C2.yyy()
应该在不同的事务中运行,该事务不受调用代码中发生的情况的影响。没有
更新
关于进一步的调试,这里是我发现的——假设调用堆栈是这样的
@Transactional(readOnly = false, propagation = Propagation.NESTED)
b1.m1()
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
b2.m2()
b3.m3()
b4.m4()
我的假设是,由于b2.m2()上的注释,m4()中的DB代码将在新事务中执行。但中的代码似乎只查看当前方法上的事务注释,而不查看堆栈上的事务注释。如果在m4()上找不到任何@transactional,则假定需要。这不是不对吗 这里的回答是:“当一个查询产生错误并且您试图运行另一个查询而不首先回滚事务时,postgres就是这样做的”
这意味着您的“obj”应该在它自己的事务中运行,并在异常时回滚
关于更新中的问题:REQUIRES_NEW始终创建一个新事务,它是经过测试的。但是“其他查询”应该在它自己的(新)事务中运行,因此不受以前运行的事务状态的影响。这不是一个新的保证吗?好问题。我的理解是需要一个新的连接,所以你是对的,理论上你的代码应该可以工作。。。我建议启用“org.springframework.transaction”的日志记录并重新运行您的示例。或者只需在AbstractPlatformTransactionManager.getTransaction(…)中放置一个断点,您是否使用普通的JDBC、Hibernate或其他方法?还有一个问题:您确定错误消息是由c2.yy()调用引起的吗?您不会重新引发异常,因此调用c2.yyy()后的代码将尝试使用断开的连接。无休眠。普通JDBC。我确实会重新显示异常,但在此之前会发生错误-即,只要您尝试在yyy()中执行第一个DB操作,即使它是select。我还注意到Postgres tx_id保持不变(来自Postgres日志)。澄清Postgres不支持嵌套事务。如果没有嵌套的tx支持,我甚至不知道这将如何工作。也许是基于保存点!