全局事务管理- Jboss:正在为您关闭连接

jjhzyzn0  于 2022-11-08  发布在  其他
关注(0)|答案(3)|浏览(171)

我们在JBoss 7服务器上部署了Spring应用程序。
应用程序使用通过JNDI从JBoss获得的多个数据源。
Java EE容器也提供了事务管理(我们使用Spring JtaTransactionManager)
应用程序架构是一个遗留架构,其中DAO扩展了hib模板(使用Spring Hibernate DaoSupport)。
事务在服务层中使用@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,但即使在单个事务中实际上只写入一个数据源,它也不总是同一个。

omtl5h9j

omtl5h9j1#

当遇到注解时,事务管理器如何知道事务中将涉及哪些数据源?
只要您具备:

<tx:annotation-driven/>

Spring应该使用一个TransactionInterceptor来拦截您的服务方法调用,并将请求 Package 在一个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触发,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需要知道从哪里获取已注册数据源的JBoss AS JNDI。

8nuwlpux

8nuwlpux2#

我认为了解Jta事务管理器如何工作以及它如何处理多个数据源的最好方法是参考[Java Transaction API (JTA) specification][1]。下载后,请看一下3.3 Transaction interface3.4 XA Ressource interface部分。

eqqqjvef

eqqqjvef3#

我把鼹鼠山变成了一座山。
事实上,对数据源的一些访问超出了事务范围,因为Hibernate连接释放模式设置为after_transaction,连接永远不会被释放。
我只是添加了一些缺少的@Transactional注解,它就解决了这个问题。

注意:即使调用方不在事务作用域内,设置为support的传播似乎也会触发连接释放

相关问题