java - Spring + Hibernate4 + JTA + JBossTS

标签 java spring hibernate jta

为了使用独立的 Java 应用程序设置 JTA,我已经苦苦挣扎了 2 天多,但不幸的是 id 不起作用,我将不胜感激。

一般信息:

  • Spring 版本:3.2.3
  • hibernate 版本:4.2.3
  • Jbossts 版本: 4.17.7,我只将 narayana-jta.jar 添加到我的类路径中。

Spring配置文件:

<bean class="com.arjuna.ats.jta.TransactionManager" factory-method="transactionManager" id="arjunaTransactionManager" />
<bean class="com.arjuna.ats.jta.UserTransaction" factory-method="userTransaction" id="arjunaUserTransaction" />

<bean class="org.springframework.transaction.jta.JtaTransactionManager" id="transactionManager">
    <property name="transactionManager">
        <ref bean="arjunaTransactionManager" />
    </property>
    <property name="userTransaction">
        <ref bean="arjunaUserTransaction" />
    </property>
</bean>

<tx:annotation-driven />

hibernate 配置文件:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
  "-//Hibernate/Hibernate Configuration DTD//EN"
  "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- Database connection settings -->
        <property name="connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
        <property name="connection.url">jdbc:sqlserver://localhost:1433;databaseName=TestDB</property>
        <property name="connection.username">user</property>
        <property name="connection.password">password</property>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.SQLServerDialect</property>

        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">jta</property>

        <!-- Disable the second-level cache -->
        <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>

        <property name="transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
        <property name="transaction.jta.platform">org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform</property>
    </session-factory>
</hibernate-configuration>

此时我需要创建 hibernate session 工厂,我想以编程方式创建它,为此我使用了以下代码片段,我在其中创建了一个 spring LocalSessionFactoryBean 将 hibernate 配置资源传递给它并检索 SessionFactory使用 .getObject() 方法从中获取。

此代码工作正常并创建了一个 SessionFactory 对象,此对象将在下一个代码片段中使用。

LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
JtaTransactionManager trxManager = applicationContext.getBean(JtaTransactionManager.class);
sessionFactoryBean.setJtaTransactionManager(trxManager);
sessionFactoryBean.setConfigLocation(resource);
sessionFactoryBean.afterPropertiesSet();
SessionFactory sessionFactory = sessionFactoryBean.getObject();

之后,我有一个服务类可以插入到表中:

package com.core.service;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
@Scope("prototype")
public class TestService {

    @Transactional
    public void testTrx() throws Exception {
        SessionFactory sessionFactory = // retrieve session factory created before

        Session session = sessionFactory.getCurrentSession();
        Query query = session.createSQLQuery("insert into TABLE1 (col1, col2) values (:v1, :v2)");
        query.setParameter("v1", "value1");
        query.setParameter("v2", "value2");

        query.executeUpdate();
    }
}

最后是加载 Spring 上下文并初始化所有内容的 JUnit 测试,然后执行以下行:

@Test
public void testTransactionRollback() throws Exception {
    TestService testService = applicationContext.getBean(TestService.class);
    testService.testTrx();
}

问题:当我执行 JUnit 测试时,我得到一个绿色条,我看到有一个 SQL 语句插入到表中,我看到一个事务已打开并提交,但是,如果我转到数据库,我看不到插入的行。

我的结论:我尝试设置 hibernate 配置 connection.autocommit=true 并且在数据库中正确创建了该行,所以我假设是的 JTA 事务是打开和关闭,但 Hibernate session 工厂没有使用它们,而是使用它自己的。我是否缺少某些配置?

15:14:20.423 [main]            DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'testService'
15:14:20.425 [main]            DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'transactionManager'
15:14:20.432 [main]            DEBUG o.s.t.jta.JtaTransactionManager - Creating new transaction with name [com.core.service.TestService.testTrx]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
15:14:20.448 [main]            INFO  com.arjuna.ats.arjuna - ARJUNA012163: Starting service com.arjuna.ats.arjuna.recovery.ActionStatusService on port 36097
15:14:20.453 [main]            INFO  com.arjuna.ats.arjuna - ARJUNA012337: TransactionStatusManagerItem host: 127.0.0.1 port: 36097
15:14:20.460 [main]            INFO  com.arjuna.ats.arjuna - ARJUNA012170: TransactionStatusManager started on port 36097 and host 127.0.0.1 with service com.arjuna.ats.arjuna.recovery.ActionStatusService
15:14:20.488 [main]            DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'sessionFactoryManagerImpl'
15:14:20.524 [main]            DEBUG o.h.e.j.i.LogicalConnectionImpl - Connection provider reports to not support aggressive release; overriding
15:14:20.533 [main]            DEBUG o.h.e.t.i.TransactionCoordinatorImpl - successfully registered Synchronization
15:14:20.565 [main]            DEBUG org.hibernate.SQL - insert into TABLE1 (col1, col2) values (?, ?)
Hibernate: insert into TABLE1 (col1, col2) values (?, ?)
15:14:20.566 [main]            DEBUG o.h.e.j.i.LogicalConnectionImpl - Obtaining JDBC connection
15:14:20.566 [main]            DEBUG o.h.e.j.i.LogicalConnectionImpl - Obtained JDBC connection
15:14:20.575 [main]            DEBUG o.h.e.q.spi.NativeSQLQueryPlan - bindNamedParameters() value1 -> v1 [1]
15:14:20.582 [main]            DEBUG o.h.e.q.spi.NativeSQLQueryPlan - bindNamedParameters() value2 -> v2 [2]
15:14:20.589 [main]            DEBUG o.s.t.jta.JtaTransactionManager - Initiating transaction commit
15:14:20.590 [main]            DEBUG o.h.e.j.i.LogicalConnectionImpl - Aggressively releasing JDBC connection
15:14:20.590 [main]            DEBUG o.h.e.j.i.LogicalConnectionImpl - Releasing JDBC connection
15:14:20.590 [main]            DEBUG o.h.e.j.i.LogicalConnectionImpl - Released JDBC connection
15:14:20.595 [Listener:36097]  DEBUG com.arjuna.ats.arjuna - Recovery listener existing com.arjuna.ats.arjuna.recovery.ActionStatusService

最佳答案

我想是因为你的数据库连接没有绑定(bind)JTA。您只将 hibernate 与 JTA 同步。 您应该使用 com.arjuna.ats.jdbc.TransactionalDriver 来创建连接:

TransactionalDriver arjunaJDBC2Driver = new TransactionalDriver();
Connection connection = arjunaJDBC2Driver.connect(url, dbProps);

Spring 示例:

 <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName">
   <value>com.arjuna.ats.jdbc.TransactionalDriver</value>
  </property>
  <property name="url" value="jdbc:arjuna:mysql://host:3306/dbName"/>
  <property name="connectionProperties">
    <ref bean="dsProps"/>
  </property>
 </bean>

希望对你有帮助

关于java - Spring + Hibernate4 + JTA + JBossTS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19051881/

相关文章:

java - PMD+Maven+JAVA 错误::找不到资源规则集/comments.xml。确保资源是有效的文件或 URL 或者在 CLASSPATH 上

java - 如何创建一个新的 SequenceGenerator 来生成唯一值?

java - 字符串中字符的快速排序

java - 是在属性文件中保持字符串常量更好还是作为静态值更好

java - 根据实体列表查找实体

java - 在kotlin中获取两个ISO格式时间之间的分钟数

java - 在 XML 配置中引用 JavaConfig 时获取 NoSuchBeanDefinitionException

java - Spring Boot 子域国际化

NHibernate - 更新带有触发器的表会导致错误 - 意外的行数 : 2; expected: 1

mysql - 是否 hibernate 关闭连接?