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();
}
});
我的猜测是:
TransactionalRunnable
块中,因为它不使用transactional
。这正确吗?
答案 0 :(得分:0)
默认情况下,jOOQ不会管理您的交易,甚至不关心您的交易。所以:
false
参数的lambda的JDBC自动提交标志设置为transactional
,并将其设置回lambda之前的状态。由于您的outer
和transactional
最终都将在同一jdbcConnection
上运行,因此情况2与情况1 不相同。它也会“偶然地”出现在同一jOOQ管理的事务中运行。如果您将DataSource
传递给outer
,则有可能实现您描述的行为(见下文)。transactional
定义的交易的嵌套交易从您的代码示例中我可以看到情况2看起来令人困惑,但是如果您考虑jOOQ的TransactionProvider
和ConnectionProvider
SPI如何相互作用,这确实有意义:
ConnectionProvider
为jOOQ提供JDBC连接以执行单个查询。
Connection
,则它将包装在DefaultConnectionProvider
中,后者总是再次生成相同的JDBC Connection
。在案例2中,jOOQ无法产生独立于当前正在运行的事务的新JDBC Connection
,因为在JDBC中,Connection
一次只能有一个事务。DataSource
,则它将包装在DataSourceConnectionProvider
中。现在,DataSource
可以选择是否向jOOQ提供新的JDBC Connection
,具体取决于是否已有事务在进行。在这种情况下,可以通过适当的TransactionProvider
TransactionProvider
方法之一时,DSLContext::transaction
就会管理事务生命周期。它确保lambda的DSLContext
参数将不再查询ConnectionProvider
的连接,而是将其存储在内部,并确保您将继续使用已附加事务的JDBC Connection
对此。这种机制还可以像您的案例4一样嵌套事务。如果在大多数地方使用Spring的@Transactional
注释,则采用不同的方式,但是以某种方式设法访问了在Spring Connection
上下文外部某处初始化的“原始” JDBC @Transactional
,那么您将具有相同的效果。您还将“意外地”继承@Transactional
上下文。