我在项目中使用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工厂: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(...)
调用。但该交易实际上并非后备支持。
我不知道是什么原因。有任何想法吗?我将不胜感激。谢谢!
答案 0 :(得分:1)
我终于设法回到这个,我想我找到了解决方案。
首先,我需要提一下我介绍了一些误解,当我说这一切都没有AOP时。今天我无法重现它,我注意到回滚的连接与jOOQ使用的连接不同。所以Alan Vrecko(见上面的评论)是对的!
然后我找到了this answer和this snippet。我决定尝试一下它就行了!但是,似乎所有先前的步骤都是有效的,仍然需要在那里(包括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));
}
然后一切似乎都正常。谢谢大家的意见。当然,我仍然愿意接受新的/更好的解决方案。