全局事务管理 - Jboss : 为你关闭一个连接
Posted
技术标签:
【中文标题】全局事务管理 - Jboss : 为你关闭一个连接【英文标题】:Global transaction management - Jboss : Closing a connection for you 【发布时间】:2014-07-17 19:08:19 【问题描述】:我们在 jboss 7 服务器上部署了一个 spring 应用程序。
应用程序使用通过 jndi 从 jboss 获得的多个数据源。
事务管理也由 Java EE 容器提供(我们使用 Spring JtaTransactionManager)
应用架构是一个遗留的架构,DAO 扩展了休眠模板(使用 Spring HibernateDaoSupport)。
事务在服务层使用@Transactional
注解进行管理。
我的第一个问题是:
遇到注解时,事务管理器如何知道事务中会涉及到哪些数据源?
它何时有效地检索 JDBC 连接以及在哪些数据源上?它什么时候有效地打开交易? (只有 DAO 获得了对绑定到特定数据源的 sessionFactory 的引用)。
我们使用的驱动不支持分布式(XA)事务,在大多数情况下我们不需要多阶段提交,因为只写入一个数据源。无论如何,当我们在同一事务中访问(只读)其他数据源时,我们会在日志中收到消息:
INFO [org.jboss.jca.core.api.connectionmanager.ccm.CachedConnectionManager] (http--0.0.0.0-8080-4) IJ000100: Closing a connection for you. Please close them yourself: org.jboss.jca.adapters.jdbc.jdk6.WrappedConnectionJDK6@691644c: java.lang.Throwable: STACKTRACE
at org.jboss.jca.core.connectionmanager.ccm.CachedConnectionManagerImpl.registerConnection(CachedConnectionManagerImpl.java:265)
at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.allocateConnection(AbstractConnectionManager.java:495)
at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:129)
at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:81) [spring-orm-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446) [hibernate-core-3.3.1.GA.jar:3.3.1.GA]
[...]
在这种情况下,有没有办法在不使用 XA 数据源的情况下正确管理连接释放?
否则可以安全地忽略这些消息还是它们表示真正的问题? (日志级别为 INFO)
[编辑]
一些额外的配置数据:
数据源声明示例
<!-- JNDI datasource -->
<bean id="customersDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/$shared.datasource" />
</bean>
关联的会话工厂
<bean id="sharedSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="customersDataSource" />
<property name="configLocation" value="classpath:hibernate.shared.cfg.xml" />
<property name="hibernateProperties">
<props>
<!-- jboss specific transaction management -->
<prop key="transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</prop>
<prop key="transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</prop>
<prop key="hibernate.connection.release_mode">after_transaction</prop>
<prop key="hibernate.transaction.auto_close_session">true</prop>
[...]
</props>
</property>
</bean>
我们正在考虑使用hibernate.connection.release_mode
,但即使在单个事务中实际上只写入了一个数据源,它也不总是同一个。
【问题讨论】:
相关帖子:reddymails.blogspot.fr/2013/10/… 【参考方案1】:遇到注解,事务管理器怎么办 知道交易将涉及哪些数据源?
只要你有:
<tx:annotation-driven/>
Spring 应该使用 TransactionInterceptor 拦截您的服务方法调用并将请求包装在 JTA 事务中。
Spring 没有真正的 XA 事务管理器,JtaTransactionManager 只是一个需要后端 JTA 提供者(如 JBoss AS 事务管理器)的外观。
您仍然需要配置 Jboss TM,如下所示:
<bean id="jbossTransactionManager" class="com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple">
</bean>
它何时有效地检索 JDBC 连接以及在哪个 数据源 ?它什么时候有效地打开交易? (仅 DAO 获得了对绑定到特定数据源的 sessionFactory 的引用)。
事务由 JtaTransactionManager 触发,它将实际的事务初始化请求委托给 JBoss TM。
所有数据源都必须符合 XA 标准,不能将 JTA 与资源本地数据源混合使用。某些事务管理器可能会使用LastResourceCommit
优化,允许您最多登记一个非 XA 数据源。
在需要数据库连接的那一刻,数据源被登记在当前事务中:
DataSource.getConnection()
从此连接将参与当前事务,因此将根据事务结果提交或回滚。
我认为你不应该使用LocalDataSourceConnectionProvider
。你需要设置:
<jta-data-source>java:/WareHouseDS</jta-data-source>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />
Hibernate 需要知道从何处获取已注册 DataSource 的 JBoss AS JNDI。
【讨论】:
感谢您的回答并抱歉您的反应时间。即使问题可能不是很清楚(英语很抱歉),您似乎对上下文也有很好的理解。但是,正如您在上次编辑中看到的那样,Jboss TM 已经配置和使用。LocalDataSourceConnectionProvider
来自docs.spring.io/spring/docs/3.1.0.RELEASE/javadoc-api/org/…,它与本地资源 DS 无关,因此应该在这里工作。 LastResourceCommit
方法如果支持多个非 xa DS 就可以了
这里真正的问题是我们的多个数据源都不是 XA 兼容的,但是我们的问题并不是真正要确保与分布式事务的数据一致性(因为理论上只有一个数据源被写入事务中)而是正确处理连接管理。
我认为您不需要设置“hibernate.transaction.auto_close_session”配置。如果您使用contextual sessions,则可以使用“线程本地”或JTA 上下文。由于您不需要一致性,因此您可以拥有多个数据源,每个数据源都有自己的会话工厂。这样您就可以使用线程本地内置支持,因此您实际上会打开多个会话,每个会话对应您使用的每个数据源。
“您可以拥有多个数据源,每个数据源都有自己的会话工厂”。实际上就是这样,据我了解,每个数据源和 jta 事务都有一个休眠会话。还是很有趣的链接谢谢
谢谢。我也喜欢你发布最终解决方案。【参考方案2】:
我认为了解 Jta 事务管理器如何工作以及它如何处理多个数据源的最佳方式是参考 [Java Transaction API (JTA) specification][1]
。
下载后,看看3.3 Transaction interface
和3.4 XA Ressource interface
部分。
【讨论】:
【参考方案3】:嗯,我是在用鼹鼠山造山。
事实上,对数据源的某些访问超出了事务范围,因为休眠连接释放模式设置为after_transaction
连接永远不会释放。
我刚刚添加了一些缺少的 @Transactional 注释,它解决了问题。
注意:似乎设置为support
的传播会触发连接释放,即使调用者不在事务范围内
【讨论】:
以上是关于全局事务管理 - Jboss : 为你关闭一个连接的主要内容,如果未能解决你的问题,请参考以下文章