4

プロジェクトで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));
}

次に、永続化ファサードにトランザクション マネージャーを挿入します。

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

後で、このデータ ソースを使用して jOOQ factory: を作成します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;
}

ここまでは順調ですね。期待どおりに動作します。

そこで、私の次のステップは、@TransactionalGuice AOP を使用したアノテーションを導入することです。インターセプターを作成しました

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

configure()Guiceモジュールのメソッドで構成しました:

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

そして今、問題が始まります。デバッガーを使用して、制御フローがインターセプターに到達することを確認できます。transactionManager.rollback(...)特に、それは呼び出しに達します。しかし、トランザクションは実際にはロールバックされません

何が原因かわかりません。何か案は?感謝します。ありがとう!

4

1 に答える 1

1

私はついにこれに戻ることができました、そして私は解決策を見つけたと思います。

まず、AOPがなくてもすべて機能すると言ったときに、少し誤解を招いたことを述べておきます。今日は再現できず、ロールバックされた接続がjOOQが使用している接続とは異なることに気づきました。したがって、Alan Vrecko(上記のコメントを参照)は正しかったです!

次に、この回答このスニペットを見つけました。私は彼らに試してみることにしました、そしてそれはうまくいきました!ただし、これまでのすべての手順は有効であり、まだ存在している必要があるようです(Google Guiceのインターセプターを含む)。

DataSourceUtils.releaseConnection(con, dataSource);私が紹介しなければならなかった唯一の変更は、から削除することでした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));
}

その後、すべてが正常に動作しているようです。コメントありがとうございます。もちろん、私はまだ新しい/より良い解決策を受け入れています。

于 2013-03-04T21:02:16.630 に答える