Транзакции JTA не фиксируются и не откатываются - JBossTS, Arjuna - PullRequest
1 голос
/ 20 июня 2019

Я пытаюсь настроить JTA автономно, используя JBossTs, так как необходимо обновить два источника данных.Однако базовая функциональность транзакции не работает.

Проще говоря, если мой DAO пытается вставить две записи, а вторая не удается, первая по-прежнему фиксируется в базе данных.

Мой DAO:

Нараяна-JTA: 4.17.43.Final org.springframework: 5.1.7.RELEASE hibernate-core: 5.3.10 .Final

public void insertRow2(String name, String model) {

    try {
        getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException {

                // the table has a primary key on columns MODEL and NAME
                // First call to the method works and this hard-coded row 
                // is inserted.

                // CASE1: In the second call, rec1 saveOrUpdate throws exception and nothing is
                // inserted.

                // CASE2: If the inputs in the method violate the PRIMARY KEY ON table, 
                // and rec1 does not, rec1 still gets inserted, instead of the entire
                // transaction getting rolled back
                TestJTARecord rec1 = new TestJTARecord();
                rec1.setModel("model1");
                rec1.setName("name1");
                session.saveOrUpdate(rec1);


                TestJTARecord rec = new TestJTARecord();
                rec.setModel(model);
                rec.setName(name);
                session.saveOrUpdate(rec);
                session.flush();
                return rec.getModelId();
            }
        });
    }catch (Exception e) {
        throw new RuntimeException("INSERTROW2");
    }

}

LOG:

2019-06-20 12:50:54,783 DEBUG  org.springframework.transaction.jta.JtaTransactionManager Creating new transaction with name [xxxServiceImpl.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-java.lang.Exception [getTransaction:372 {}] 
2019-06-20 12:50:54,783 DEBUG  org.hibernate.SQL select hibernate_sequence.nextval from dual [logStatement:94 {}] 
2019-06-20 12:50:54,805 DEBUG  org.hibernate.SQL select hibernate_sequence.nextval from dual [logStatement:94 {}] 
2019-06-20 12:50:54,807 DEBUG  org.hibernate.SQL insert into TESTJTA (model, name, modelid) values (?, ?, ?) [logStatement:94 {}] 
2019-06-20 12:50:54,812 TRACE  org.hibernate.type.descriptor.sql.BasicBinder binding parameter [1] as [VARCHAR] - [model1] [bind:65 {}] 
2019-06-20 12:50:54,813 TRACE  org.hibernate.type.descriptor.sql.BasicBinder binding parameter [2] as [VARCHAR] - [name1] [bind:65 {}] 
2019-06-20 12:50:54,813 TRACE  org.hibernate.type.descriptor.sql.BasicBinder binding parameter [3] as [INTEGER] - [14501] [bind:65 {}] 
2019-06-20 12:50:54,820 DEBUG  org.hibernate.SQL insert into TESTJTA (model, name, modelid) values (?, ?, ?) [logStatement:94 {}] 
2019-06-20 12:50:54,821 TRACE  org.hibernate.type.descriptor.sql.BasicBinder binding parameter [1] as [VARCHAR] - [test2] [bind:65 {}] 
2019-06-20 12:50:54,821 TRACE  org.hibernate.type.descriptor.sql.BasicBinder binding parameter [2] as [VARCHAR] - [test1] [bind:65 {}] 
2019-06-20 12:50:54,821 TRACE  org.hibernate.type.descriptor.sql.BasicBinder binding parameter [3] as [INTEGER] - [14502] [bind:65 {}] 
2019-06-20 12:50:54,822 ERROR  xxxServiceImpl ========> EXCEPTION CAUGHT [error:240 {}] 
java.lang.RuntimeException: INSERTROW2
    at xxxDAOImpl.insertRow2(xxxDAOImpl.java:199) ~[xxx.jar:?]
    at xxxServiceImpl.save(xxxServiceImpl.java:84) ~[xxx.jar:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_66]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_66]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_66]
    at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_66]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295) [spring-tx-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) [spring-tx-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) [spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) [spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at com.sun.proxy.$Proxy71.save(Unknown Source) [?:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_66]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_66]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_66]
    at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_66]

2019-06-20 12:50:54,823 DEBUG  org.springframework.transaction.jta.JtaTransactionManager Initiating transaction rollback [processRollback:836 {}] 

Caused by: java.lang.RuntimeException: INSERTROW2
    at xxxDAOImpl.insertRow2(xxxDAOImpl.java:199) ~[xxx.jar:?]
    at xxxServiceImpl.save(xxxServiceImpl.java:84) ~[xxx.jar:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_66]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_66]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_66]
    at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_66]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295) ~[spring-tx-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at com.sun.proxy.$Proxy71.save(Unknown Source) ~[?:?]
    ... 9 more

Кажется, что каждый SQL-оператор, выполняемый DAO, находится в отдельной транзакции вместо всего метода.Кроме того, вызов flush () или нет не оказывает никакого влияния.

Тот же код работает, как и ожидалось, если я использую HibernateTransactionManager.

<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 id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager" ref="arjunaTransactionManager" />
        <property name="userTransaction" ref="arjunaUserTransaction" />
    </bean> 

Источник даты

<bean id="testJTA" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName">
       <value>com.arjuna.ats.jdbc.TransactionalDriver</value>
      </property>
      <property name="url" value="${database.url}"/>

      <property name="username">
            <value>testjta</value>
        </property>
        <property name="password">
            <value>testjta</value>
        </property>
  </bean>

Hibernate Config

<bean id="testJTASessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <description>
            Hibernate session support bean. Additional mappings go into mappingResources list.
        </description>
        <property name="dataSource" ref="testJTA"/>
        <property name="jtaTransactionManager" ref="transactionManager"/>
        <property name="mappingResources">
            <list>
               <value>hibernate/TestJTA.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
            <prop key="hibernate.dialect">${database.hibernate.dialect}</prop>
                <!-- <prop key="hibernate.connection.isolation">3</prop> -->
                <prop key="hibernate.connection.autocommit">false</prop>
                <!-- <prop key="hibernate.flushMode">COMMIT</prop> -->

                <prop key="hibernate.transaction.coordinator_class">jta</prop>
                <prop key="hibernate.current_session_context_class">jta</prop>
                <prop key="hibernate.transaction.jta.platform">org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform</prop>
                <prop key="hibernate.jta.allowTransactionAccess">true</prop>
                </props>
        </property>
    </bean>

Обновление 1: использование org.apache.tomcat.jdbc.pool.XADataSource и установка defaultAutoCommit=false не работают, поскольку в базе данных ничего не фиксируется.Не вижу ошибок.Если я выполню метод еще раз, будет сгенерировано исключение, говорящее о нарушении уникального ограничения, но таблица в БД пуста.Кажется, что принятие или откат транзакции JTA, кажется, не имеет никакого влияния.

Обновление 2: с изменением выше, SQL выполняется, но ничего не фиксируется.Если я выполню код снова, я получу исключение уникального ограничения SQL, но таблица в БД пуста.

...