JOOQ:单个语句是隐式事务性的,还是我还需要将它包装在事务块中?

时间:2016-12-21 08:25:13

标签: orm transactions spring-transactions jooq transactional

假设我们在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();

}

以下陈述:

  1. 在数据库中执行语句并回滚整个语句(没有提交插入)时,第一个查询将失败(最迟)DataAccessException

  2. 第二个查询虽然已经执行且没有错误,但会在抛出异常时回滚。

  3. 正确?

    最后,在以下情况中:

    { // non transactional code block
        insertInto(TABLE)
        // list of sets that are OK
        .execute();
    
        throw new RuntimeException();
    }
    

    插入将在数据库上执行,但在抛出异常时将回滚,因为它不在事务上下文中。

    这一切都是正确的,还是我误解了什么?

1 个答案:

答案 0 :(得分:2)

  

在数据库中执行语句时,第一个查询将失败(最迟)使用DataAccessException

正确

  

并回滚整个声明

好吧,在事务回滚中没有“回滚”。声明失败

  

(没有提交插入)。

正确(在任何情况下,没有任何内容从声明中提交)

  

第二个查询虽然已经执行但没有错误,但会在抛出异常时回滚。

正确。

  

插入将在数据库上执行,但在抛出异常时不会回滚,因为它不在事务上下文中。

正确。

  

我误解了什么吗?

是。这与jOOQ并不严格相关,而是与SQL语句有关。首先,JDBC具有自动提交模式,默认情况下有时会处于活动状态。

使用JDBC自动提交

当它处于活动状态时,则:

  • 每个声明都会被提交。
  • 这意味着如果成功,语句的更改将通过提交应用于数据库。
  • 这也意味着如果失败,该语句无效,因为它失败了。然而,还有一个提交。

请注意,自动提交是JDBC功能,而不是jOOQ功能。所以jOOQ在这里继承了JDBC设置。

没有JDBC自动提交

如果自动提交处于非活动状态,则每个新语句都将在JDBC中启动事务。当您使用jOOQ的transaction() API时,jOOQ将覆盖JDBC自动提交标志以变为非活动状态并为您启动事务。现在,

  • 如果Transactional块/ lambda成功,则会发出提交。您的所有更改都将通过提交写入数据库。
  • 如果Transactional块/ lambda因异常而失败,则会发出回滚。您的所有更改都将通过回滚进行还原。
  • 提交
  • 时,声明仍然需要成功