簡體   English   中英

Spring JDBC的事務處理不適用於Google Guice

[英]Spring JDBC's transactions handling doesn't work with Google Guice

我在我的項目中使用Google Guice和jOOQ 目前我決定使用Spring JDBC引入事務處理。

所以我做了以下幾點。

我在Guice模塊中設置了數據源和事務管理器。

@Provides
@Singleton
DataSource provideDataSource(IExternalSettings settings) {
    Jdbc3PoolingDataSource dataSource = new Jdbc3PoolingDataSource();
    // configuring DataSource
    return dataSource;
}


@Provides
@Singleton
DataSourceTransactionManager provideDataSourceTransactionManager(DataSource dataSource) {
    return new DataSourceTransactionManager(new TransactionAwareDataSourceProxy(dataSource));
}

然后我將我的事務管理器注入持久性Facade

@Inject
public PersistenceFacade(final DataSourceTransactionManager transactionManager) {
    this.dataSource = transactionManager.getDataSource();
    this.transactionManager = transactionManager;
}

后來,我使用這個數據源來創建jOOQ工廠: new Factory(dataSource, ...)

最后我運行我的數據庫訪問代碼:

DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
TransactionStatus transaction = transactionManager.getTransaction(transactionDefinition);
try {
    // db code in transaction
    transactionManager.commit(transaction);
    return result;
} catch (Exception e) {
    transactionManager.rollback(transaction);
    throw e;
}

到現在為止還挺好。 按預期工作

所以,我的下一步是使用Guice AOP引入@Transactional注釋。 我創建了一個攔截器

class TransactionalMethodInterceptor implements MethodInterceptor {

    @Inject
    private DataSourceTransactionManager transactionManager;

    @Override
    public Object invoke(final MethodInvocation invocation) throws Throwable {
        DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
        TransactionStatus transaction = transactionManager.getTransaction(transactionDefinition);
        try {
            Object result = invocation.proceed();
            transactionManager.commit(transaction);
            return result;
        } catch (Exception e) {
            transactionManager.rollback(transaction);
            throw e;
        }
    }
}

並在Guice模塊的configure()方法中配置它:

TransactionalMethodInterceptor transactionalMethodInterceptor = new TransactionalMethodInterceptor();
requestInjection(transactionalMethodInterceptor);
bindInterceptor(Matchers.any(), Matchers.annotatedWith(Transactional.class), transactionalMethodInterceptor);

現在問題就開始了 我可以看到,使用調試器,控制流到達攔截器。 特別是,它到達transactionManager.rollback(...)調用。 但事務實際上沒有支持

我不知道是什么原因。 有任何想法嗎? 我將不勝感激。 謝謝!

我終於設法回到這個,我想我找到了一個解決方案。

首先,我需要提一下我介紹了一些誤解,當我說這一切都沒有AOP。 今天我無法重現它,我注意到回滾的連接與jOOQ使用的連接不同。 所以Alan Vrecko(見上面的評論)是對的!

然后我找到了這個答案這個片段 我決定嘗試一下它就行了! 然而,似乎所有先前的步驟都是有效的,仍然需要在那里(包括Google Guice的攔截器)。

我必須引入的唯一更改是刪除DataSourceUtils.releaseConnection(con, dataSource); 來自SpringExceptionTranslationExecuteListener. exception(ExecuteContext ctx) SpringExceptionTranslationExecuteListener. exception(ExecuteContext ctx) 所以最后這個方法看起來像

@Override
public void exception(ExecuteContext ctx) {
    SQLException ex = ctx.sqlException();
    Statement stmt = ctx.statement();
    Connection con = ctx.getConnection();
    DataSource dataSource = ctx.getDataSource();
    JdbcUtils.closeStatement(stmt);
    ctx.exception(getExceptionTranslator(dataSource).translate("jOOQ", ctx.sql(), ex));
}

然后一切似乎都正常。 謝謝大家的意見。 當然,我仍然願意接受新的/更好的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM