事务未在JOOQ中回滚

时间:2017-03-26 09:06:00

标签: java jooq

我的代码与此代码非常相似:

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);

为什么我会出现这种行为?

2 个答案:

答案 0 :(得分:0)

您的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一样,必须使用Configuration方法的参数run()来运行进一步的查询,方法是用{{1}包装它或者将它传递给你的daos。

一个更简单的选择是使用事务感知的数据源(即它将事务绑定到线程),这样同一个线程将始终从数据源获得相同的事务JDBC DSL.using(configuration)

答案 1 :(得分:0)

我让spring处理与jOOQ的交易。方法如下:

这是spring配置类:

@Configuration
public class SpringConfiguration
{
    @Bean
    public DataSource dataSource() throws PropertyVetoException
    {
        comboPooledDataSource.setDriverClass(org.postgresql.Driver.class.getName());
        comboPooledDataSource
                    .setJdbcUrl("jdbc:postgresql://localhost:5432/database?searchpath=schema");
        comboPooledDataSource.setUser("databaseuser");
        comboPooledDataSource.setPassword("password");

        comboPooledDataSource.setMinPoolSize(5);
        comboPooledDataSource.setAcquireIncrement(5);
        comboPooledDataSource.setMaxPoolSize(25);
        return comboPooledDataSource;
    }

    @Bean
    public DataSourceTransactionManager transactionManager() throws PropertyVetoException
    {
        return new DataSourceTransactionManager(dataSource());
    }

    @Bean
    public TransactionAwareDataSourceProxy transactionAwareDataSource() throws PropertyVetoException
    {
        return new TransactionAwareDataSourceProxy(dataSource());
    }

    @Bean
    public DataSourceConnectionProvider connectionProvider() throws PropertyVetoException
    {
        return new DataSourceConnectionProvider(transactionAwareDataSource());
    }

    @Bean
    public org.jooq.Configuration configuration() throws PropertyVetoException
    {
        return new DefaultConfiguration().set(connectionProvider()).set(transactionProvider()).set(SQLDialect.POSTGRES);
    }

    @Bean
    public TransactionProvider transactionProvider() throws PropertyVetoException
    {
        return new SpringTransactionProvider(transactionManager());
    }

    @Bean
    public DSLContext dslContext() throws PropertyVetoException
    {
        return DSL.using(configuration());
    }
} 

这是SpringTransactionProvider

public class SpringTransactionProvider implements TransactionProvider
{
    DataSourceTransactionManager transactionManager;

    public SpringTransactionProvider(DataSourceTransactionManager transactionManager)
    {
        this.transactionManager = transactionManager;
    }

    @Override
    public void begin(TransactionContext ctx)
    {
        TransactionStatus tx = transactionManager.getTransaction(new DefaultTransactionDefinition(
                TransactionDefinition.PROPAGATION_REQUIRED));
        ctx.transaction(new SpringTransaction(tx));
    }

    @Override
    public void commit(TransactionContext ctx)
    {
        transactionManager.commit(((SpringTransaction) ctx.transaction()).tx);
    }

    @Override
    public void rollback(TransactionContext ctx)
    {
        transactionManager.rollback(((SpringTransaction) ctx.transaction()).tx);
    }

    class SpringTransaction implements Transaction
    {
        final TransactionStatus tx;

        SpringTransaction(TransactionStatus tx)
        {
            this.tx = tx;
        }
    }
}

最后得到DSLContext

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
DSLContext dslContext=applicationContext.getBean(DSLContext.class);

您需要在类路径中使用这些jar才能使其正常工作: spring-tx.jarspring-aop.jarspring-expression.jarspring-core.jarspring-beans.jarspring-jdbc.jarspring-context.jar:)