我有一个与此非常相似的代码:
dslContext.transaction(new TransactionalRunnable()
{
@Override
public void run(Configuration arg0) throws Exception
{
dao1.insert(object1);
//Object 1 is inserted in the database
//despite the exception that is being thrown
if(true)
throw new RuntimeException();
dao2.insert(object2)
}
});
这是我用来创建 dsl 上下文和使用 JOOQ 生成的 daos 的代码。
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
comboPooledDataSource.setDriverClass(org.postgresql.Driver.class.getName());
comboPooledDataSource.setJdbcUrl("jdbc:postgresql://localhost:5432/database?searchpath=schema");
comboPooledDataSource.setUser("user");
comboPooledDataSource.setPassword("password");
comboPooledDataSource.setMinPoolSize(5);
comboPooledDataSource.setAcquireIncrement(5);
comboPooledDataSource.setMaxPoolSize(25);
Configuration configuration=new DefaultConfiguration().set(comboPooledDataSource).set(
SQLDialect.POSTGRES);
DSLContext dslContext=DSL.using(configuration);
Dao1 dao1=new Dao1(configuration);
Dao2 dao2=new Dao2(configuration);
为什么我会出现这种行为?
最佳答案
您的 DAO
的配置与您的交易不同。这意味着每个 DAO 在新的自动提交事务中运行其代码,即使您将该逻辑放入 TransactionalRunnable
中也是如此。
这会起作用:
dslContext.transaction(new TransactionalRunnable()
{
@Override
public void run(Configuration arg0) throws Exception
{
new Dao1(arg0).insert(object1);
if(true)
throw new RuntimeException();
new Dao2(arg0).insert(object2)
}
});
请注意,[DSLContext.transaction(TransactionalRunnable][1])
不会修改 dslContext
及其随附的Configuration
。这意味着如果您的数据源无法正常工作,例如像 JavaEE 或 Spring TransactionAwareDataSourceProxy
,那么您必须使用 run()
方法的参数 Configuration
来运行进一步的查询,或者通过使用 DSL 包装它。 using(configuration)
或将其传递给您的 daos。
一个更简单的选择是使用事务感知的数据源(即,它将事务绑定(bind)到线程),这样同一个线程将始终从 获取相同的事务处理 JDBC Connection
数据源。
关于java - JOOQ 中事务未回滚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43026947/