假设我们在wrirting JOOQ查询时遇到以下情况:
insertInto(TABLE)
.set(TABLE.NAME, "...")
.set(TABLE.FK, null) -- breaks FK constraint!
//...
.execute();
和
transactional(configuration -> {
insertInto(TABLE)
// list of sets that are OK
.execute();
throw new RuntimeException();
}
以下陈述:
在数据库中执行语句并回滚整个语句(没有提交插入)时,第一个查询将失败(最迟)DataAccessException
。
第二个查询虽然已经执行且没有错误,但会在抛出异常时回滚。
正确?
最后,在以下情况中:
{ // non transactional code block
insertInto(TABLE)
// list of sets that are OK
.execute();
throw new RuntimeException();
}
插入将在数据库上执行,但在抛出异常时将不回滚,因为它不在事务上下文中。
这一切都是正确的,还是我误解了什么?
答案 0 :(得分:2)
在数据库中执行语句时,第一个查询将失败(最迟)使用DataAccessException
正确
并回滚整个声明
好吧,在事务回滚中没有“回滚”。声明失败
(没有提交插入)。
正确(在任何情况下,没有任何内容从声明中提交)
第二个查询虽然已经执行但没有错误,但会在抛出异常时回滚。
正确。
插入将在数据库上执行,但在抛出异常时不会回滚,因为它不在事务上下文中。
正确。
我误解了什么吗?
是。这与jOOQ并不严格相关,而是与SQL语句有关。首先,JDBC具有自动提交模式,默认情况下有时会处于活动状态。
当它处于活动状态时,则:
请注意,自动提交是JDBC功能,而不是jOOQ功能。所以jOOQ在这里继承了JDBC设置。
如果自动提交处于非活动状态,则每个新语句都将在JDBC中启动事务。当您使用jOOQ的transaction()
API时,jOOQ将覆盖JDBC自动提交标志以变为非活动状态并为您启动事务。现在,
Transactional
块/ lambda成功,则会发出提交。您的所有更改都将通过提交写入数据库。Transactional
块/ lambda因异常而失败,则会发出回滚。您的所有更改都将通过回滚进行还原。