Spring 找到预先绑定的JDBC连接

Spring 找到预先绑定的JDBC连接,spring,hibernate,db2,Spring,Hibernate,Db2,我们有一个在WebSphere7中使用hibernate、spring和DB2的应用程序。我们有审计触发器,我们需要进行设置,以便触发器能够知道登录的用户(我们使用对数据库的通用登录)。我们提出了一个新方案,用于在新应用程序中设置此项,以便它可以自动加入新事务。我们推翻了事务管理器,在doBegin中完成了工作 这些方案在一个应用程序中效果很好,在第二个应用程序中效果也很好,但是现在,几周后,而且并不一致(行为是间歇性的,在本地开发中不会发生),我们发现了这个预先绑定的JDBC连接错误。通过在线

我们有一个在WebSphere7中使用hibernate、spring和DB2的应用程序。我们有审计触发器,我们需要进行设置,以便触发器能够知道登录的用户(我们使用对数据库的通用登录)。我们提出了一个新方案,用于在新应用程序中设置此项,以便它可以自动加入新事务。我们推翻了事务管理器,在doBegin中完成了工作

这些方案在一个应用程序中效果很好,在第二个应用程序中效果也很好,但是现在,几周后,而且并不一致(行为是间歇性的,在本地开发中不会发生),我们发现了这个预先绑定的JDBC连接错误。通过在线查看,大多数帖子都说这是在对一个数据源使用两个事务管理器时发生的。这就是我们现在正在做的

我还读过一篇帖子,想知道这是否是因为他混合了注释和基于AOP的事务。这个应用程序可以做到这一点。我真的不相信那个理论,但我想我应该提一下

例外情况:

Caused by: 
org.springframework.transaction.IllegalTransactionStateException: Pre-bound JDBC Connection found! HibernateTransactionManager does not support running within DataSourceTransactionManager if told to manage the DataSource itself. It is recommended to use a single HibernateTransactionManager for all transactions on a single DataSource, no matter whether Hibernate or JDBC access.
at java.lang.Throwable.<init>(Throwable.java:67)
at org.springframework.core.NestedRuntimeException.<init>(NestedRuntimeException.java:54)
at org.springframework.transaction.TransactionException.<init>(TransactionException.java:34)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:475)
at gov.usdoj.afms.umc.utils.hibernate.AfmsHibernateTransactionManager.doBegin(AfmsHibernateTransactionManager.java:28)

与其修改事务管理器,不如在数据源周围创建一个包装器(从spring扩展
DelegatingDataSource
)并覆盖2个getConnection方法。对于清理,您可以将连接包装在代理中并截获close方法

这应该是一种比尝试摆弄事务管理器更安全(我想也更容易)的方法,只要使用包装好的数据源,它适用于每种技术(JDBC、Hibernate、JPA等)。(注册可以使用
BeanPostProcessor
完成,该处理器检测
DataSource
实例,并简单地将它们包装到委托中)


如果这是激进的(因为这意味着更改当前应用程序而不是更新库)。这可能是一个配置问题,请确保只加载一次配置(因此DataSource和TransactionManager),复制bean实例可能会导致类似的行为。

我刚刚意识到我从未回答过这个问题。事实证明,该异常与我们的Tx经理无关。事实上,这个特定的EAR中有两个应用程序,每个应用程序都指向同一个数据源。显然,这混淆了hibernate。我们计划有朝一日将这些应用程序分开,但创建一个相同的(除了名称)数据源并将这些应用程序分别指向它们暂时解决了这个问题。

对于子孙后代,我刚刚发现了这个问题,这里的答案并没有太大帮助。我们通过删除包含AOP事务管理器定义的核心XML文件的双重导入来解决此问题:

<tx:annotation-driven transaction-manager="..."
    proxy-target-class="true" />

我认为这会导致两个事务管理器重叠在同一名称空间上。为了解决这个问题,我们将导入移动了一圈,这样就只需执行一次


希望这对其他人有帮助。

我不明白为什么这样“更安全”。这似乎是相同的原则,只有tx mgr在事务开始之前我不会这样做,这确实是正确的时机(只读连接不需要像审核触发器那样设置客户端id)。是的,我相信我只加载一次配置。更安全的是,如果有人忘记@Transactional(或者如果您的切入点不匹配)属性仍然设置(每个人都必须使用数据源)。但这当然是正确的。传递到
doBegin
方法的第一个参数应该是
HibernateTransactionObject
这应该有一个正确连接的句柄(在
super.doBegin()
之后)。不要使用hibernate,而是使用来自
HibernateTransactionObject
的已绑定连接。可能与
<tx:annotation-driven transaction-manager="..."
    proxy-target-class="true" />