[英]Spring JDBC's transactions handling doesn't work with Google Guice
I use Google Guice and jOOQ in my project. 我在我的项目中使用Google Guice和jOOQ 。 Currently I decided to introduce transaction handling using Spring JDBC.
目前我决定使用Spring JDBC引入事务处理。
So I did the following. 所以我做了以下几点。
I set a data source and a transaction manager in Guice module. 我在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));
}
Then I inject my transaction manager to a persistence facade 然后我将我的事务管理器注入持久性Facade
@Inject
public PersistenceFacade(final DataSourceTransactionManager transactionManager) {
this.dataSource = transactionManager.getDataSource();
this.transactionManager = transactionManager;
}
Later, I use this data source to create jOOQ factory: new Factory(dataSource, ...)
. 后来,我使用这个数据源来创建jOOQ工厂:
new Factory(dataSource, ...)
。
Finaly I run my database access code: 最后我运行我的数据库访问代码:
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;
}
So far, so good. 到现在为止还挺好。 It works as expected .
它按预期工作 。
So, my next step is to introduce @Transactional
annotation using Guice AOP. 所以,我的下一步是使用Guice AOP引入
@Transactional
注释。 I created an interceptor 我创建了一个拦截器
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;
}
}
}
And configured it in configure()
method of Guice module: 并在Guice模块的
configure()
方法中配置它:
TransactionalMethodInterceptor transactionalMethodInterceptor = new TransactionalMethodInterceptor();
requestInjection(transactionalMethodInterceptor);
bindInterceptor(Matchers.any(), Matchers.annotatedWith(Transactional.class), transactionalMethodInterceptor);
And now the issues begin . 现在问题就开始了 。 I can see, using debugger, that control flow reaches interceptor.
我可以看到,使用调试器,控制流到达拦截器。 In particular, it reaches
transactionManager.rollback(...)
invocation. 特别是,它到达
transactionManager.rollback(...)
调用。 But the transaction is not actually roll backed . 但事务实际上并没有支持 。
I have no clue what's the reason. 我不知道是什么原因。 Any ideas?
有任何想法吗? I'll be grateful.
我将不胜感激。 Thanks!
谢谢!
I finally managed to come back to this one and I think I found a solution. 我终于设法回到这个,我想我找到了一个解决方案。
First of all, I need to mention I introduced a bit of misunderstanding, when I said it all works without AOP. 首先,我需要提一下我介绍了一些误解,当我说这一切都没有AOP。 Today I couldn't reproduce it and I noticed that the connection that is rolled back is different than the one that jOOQ is using.
今天我无法重现它,我注意到回滚的连接与jOOQ使用的连接不同。 So Alan Vrecko (see comment above) was right!
所以Alan Vrecko(见上面的评论)是对的!
Then I found this answer and this snippet . 然后我找到了这个答案和这个片段 。 I decided to give them a try and it worked!
我决定尝试一下它就行了! However, it appeared that all previous steps are valid and still need to be there (including Google Guice's interceptor).
然而,似乎所有先前的步骤都是有效的,仍然需要在那里(包括Google Guice的拦截器)。
The only I change I had to introduce was to remove DataSourceUtils.releaseConnection(con, dataSource);
我必须引入的唯一更改是删除
DataSourceUtils.releaseConnection(con, dataSource);
from SpringExceptionTranslationExecuteListener. exception(ExecuteContext ctx)
来自
SpringExceptionTranslationExecuteListener. exception(ExecuteContext ctx)
SpringExceptionTranslationExecuteListener. exception(ExecuteContext ctx)
. SpringExceptionTranslationExecuteListener. exception(ExecuteContext ctx)
。 So finally the method looks like 所以最后这个方法看起来像
@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));
}
Then all seems to work properly. 然后一切似乎都正常。 Thank you all for comments.
谢谢大家的意见。 Of course I'm still open to new/better solutions.
当然,我仍然愿意接受新的/更好的解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.