2017-03-26 1 views
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 컨텍스트를 만드는 데 사용하고 코드와 생성 된 DAO는이다 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

'나는 이것과 매우 유사한 코드가? – PeterMmm

+0

사용중인 jOOQ 버전은 무엇입니까? 'comboPooledDataSource'가 어떻게 구성되어 있는지 보여줄 수 있습니까? –

+0

@ LukasEder JOOQ 버전 3.9.1을 사용하고 있으며 질문을 업데이트했습니다. – Thunder

답변

0

DAO은 트랜잭션과 다른 구성으로 구성됩니다. 즉, 로직을 TransactionalRunnable 안에 넣어도 각 자동 커밋 된 트랜잭션에서 각 DAO가 코드를 실행합니다.

이 작동합니다 : DSLContext.transaction(TransactionalRunnable][1])dslContext을 수정하고 Configuration를 동봉하지 않습니다 [있다는

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

참고. 즉, 데이터 소스가 작동하지 않는 경우입니다. 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); 

을 당신 이것을 작동 시키려면 classpath에 그 항아리가 필요합니다 :`당신이 게시 된 코드를 실행하면, 같은 동작을 :spring-tx.jar, spring-aop.jar, spring-expression.jar, spring-core.jar, spring-beans.jar, spring-jdbc.jarspring-context.jar :