在交易块之外会发生什么?

时间:2019-09-01 03:22:44

标签: java sql jooq

JOOQ Transaction Management文档中的细节有些浅。请帮助我了解以下4种情况之间的区别:

DSLContext outer = DSL.using(jdbcConnection, SQLDialect.POSTGRES);

// case 1
outer.insertInto(someTable).set(...).execute();

outer.transaction(transactional ->
{
    DSLContext inner = DSL.using(transactional);

    // case 2
    outer.insertInto(someTable).set(...).execute();

    // case 3
    inner.insertInto(someTable).set(...).execute();

    inner.transaction(transactional2 ->
    {
      DSLContext inner2 = DSL.using(transactional2);

      // case 4
      inner2.insertInto(someTable).set(...).execute();
    }
});

我的猜测是:

  • 案例1针对自动提交事务运行。
  • 案例2与案例1相同,即使案例2在TransactionalRunnable块中,因为它不使用transactional
  • 案例3针对不会自动提交且与案例1或案例2使用的交易无关的交易。
  • 案例4针对不会自动提交且嵌套在案例3使用的事务内的事务。

这正确吗?

1 个答案:

答案 0 :(得分:0)

默认情况下,jOOQ不会管理您的交易,甚至不关心您的交易。所以:

  • 案例1可以在jOOQ之外指定的任何事务管理下运行,例如JDBC的自动提交标志,默认情况下可以打开或不打开。如果您没有任何外部事务管理(例如Spring),那么您可能是对的,因为大多数驱动程序默认将autocommit = true。
  • 第2种情况将执行接收false参数的lambda的JDBC自动提交标志设置为transactional,并将其设置回lambda之前的状态。由于您的outertransactional最终都将在同一jdbcConnection上运行,因此情况2与情况1 相同。它也会“偶然地”出现在同一jOOQ管理的事务中运行。如果您将DataSource传递给outer,则有可能实现您描述的行为(见下文)。
  • 第3种情况与第1种情况的交易无关,但在第2种情况下会“偶然”在同一笔交易中运行。
  • 案例4确实是transactional定义的交易的嵌套交易

从您的代码示例中我可以看到情况2看起来令人困惑,但是如果您考虑jOOQ的TransactionProviderConnectionProvider SPI如何相互作用,这确实有意义:

  • ConnectionProvider为jOOQ提供JDBC连接以执行单个查询。
    • 如果您向jOOQ传递一个Connection,则它将包装在DefaultConnectionProvider中,后者总是再次生成相同的JDBC Connection。在案例2中,jOOQ无法产生独立于当前正在运行的事务的新JDBC Connection,因为在JDBC中,Connection一次只能有一个事务。
    • 如果您向jOOQ传递了一个DataSource,则它将包装在DataSourceConnectionProvider中。现在,DataSource可以选择是否向jOOQ提供新的JDBC Connection,具体取决于是否已有事务在进行。在这种情况下,可以通过适当的TransactionProvider
    • 实现案例2
  • 每当您调用jOOQ的各种TransactionProvider方法之一时,
  • DSLContext::transaction就会管理事务生命周期。它确保lambda的DSLContext参数将不再查询ConnectionProvider的连接,而是将其存储在内部,并确保您将继续使用已附加事务的JDBC Connection对此。这种机制还可以像您的案例4一样嵌套事务。

如果在大多数地方使用Spring的@Transactional注释,则采用不同的方式,但是以某种方式设法访问了在Spring Connection上下文外部某处初始化的“原始” JDBC @Transactional ,那么您将具有相同的效果。您还将“意外地”继承@Transactional上下文。