2017-03-26 9 views
1

にロールバックされませんこの1:取引は、私は非常によく似ているコードを持って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のコンテキストを作成するために使用していたコードとで生成されたDAOSですJOOQ。

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

なぜこの現象が発生しますか?

+0

'私はこの1つに非常によく似ているコードがありますか? – PeterMmm

+0

あなたはどのjOOQバージョンを使用していますか? 'comboPooledDataSource'の設定方法を教えてください。 –

+0

@ LukasEder私はJOOQのバージョン3.9.1を使用しています。質問を更新しました。 – Thunder

答えて

0

DAOは、トランザクションとは異なる設定で構成されています。これは、たとえそのロジックをTransactionalRunnableの内部に入れたとしても、各DAOは新しい自動コミットされたトランザクションでそのコードを実行することを意味します。

これは動作します:

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に渡します。

より簡単な選択肢は、同じスレッドが常に同じトランザクションされたJDBC Connectionをデータソースから取得するように、トランザクションを認識する(つまり、トランザクションをスレッドにバインドする)データソースを使用することです。

0

私は春にjOOQでトランザクションを処理させています。

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

あなたはここにどのようにこれを動作させるにはクラスパスにそれらの瓶が必要です:`、そしてあなたが投稿したコードを実行すると、あなたは同じ動作を持っている:spring-tx.jarspring-aop.jarspring-expression.jarspring-core.jarspring-beans.jarspring-jdbc.jarspring-context.jar :)

関連する問題