How to use Atomikos Transaction Essentials with Hibernate >= 4.3

前端 未结 5 454
悲&欢浪女
悲&欢浪女 2020-12-09 05:54

I switched from Hibernate 4.2 to Hibernate 4.3 and my project is not working any more. I\'m getting an

HibernateException: Unable to locate current JT

相关标签:
5条回答
  • 2020-12-09 06:14

    Can you try setting the jtaTransactionManager property of org.springframework.orm.hibernate4.LocalSessionFactoryBean to Spring's JtaTransactionManager? I have similar problem but solved by this. By the way, the HibernateTemplate is back on Spring 4.0.1. Although it's not recommended, but I like to use it. It helped take care of a lot of things. (I am using Spring 4.0.5 + Hibernate 4.3.5 + Atomikos 3.9.3)

    <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close" depends-on="userTransactionService">
       <property name="forceShutdown" value="true" />
    </bean>
    
    <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" depends-on="userTransactionService">
       <property name="transactionTimeout" value="180" />
    </bean>
    
    <bean id="JtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
       <property name="transactionManager" ref="atomikosTransactionManager" />
       <property name="userTransaction" ref="atomikosUserTransaction" />
       <property name="allowCustomIsolationLevels" value="true"></property>
    </bean>
    
    <bean id="rentSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource"><ref bean="rentXADataSource" /></property>
        <property name="mappingLocations" value="classpath:com/kj/model/web/*.hbm.xml"/>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
                <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory</prop>          
                <prop key="hibernate.cache.use_query_cache">true</prop> 
                <prop key="hibernate.cache.use_second_level_cache">true</prop>
                <prop key="hibernate.format_sql">false</prop>
                <prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>
            </props>
        </property>
        <property name="jtaTransactionManager" ref="JtaTransactionManager"></property>
    </bean>
    
    0 讨论(0)
  • 2020-12-09 06:15

    To use Hibernate JTA Platform with Spring write and compile this code

    package my.domain.spring.hibernate.jta;
    
    import javax.transaction.TransactionManager;
    import javax.transaction.UserTransaction;
    
    import org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform;
    import org.springframework.transaction.jta.JtaTransactionManager;
    import org.springframework.util.Assert;
    
    @SuppressWarnings("serial")
    public class SpringJtaPlatformAdapter extends AbstractJtaPlatform {
    
        private static TransactionManager sTransactionManager;
        private static UserTransaction sUserTransaction;
    
    
        @Override
        protected TransactionManager locateTransactionManager() {
            Assert.notNull(sTransactionManager, "TransactionManager has not been setted");
            return sTransactionManager;
        }
    
    
        @Override
        protected UserTransaction locateUserTransaction() {
            Assert.notNull(sUserTransaction, "UserTransaction has not been setted");
            return sUserTransaction;
        }
    
    
        public void setJtaTransactionManager(JtaTransactionManager jtaTransactionManager) {
            sTransactionManager = jtaTransactionManager.getTransactionManager();
            sUserTransaction = jtaTransactionManager.getUserTransaction();
        }
    
    
        public void setTransactionManager(TransactionManager transactionManager) {
            sTransactionManager = transactionManager;
        }
    
    
        public void setUserTransaction(UserTransaction userTransaction) {
            sUserTransaction = userTransaction;
        }
    
    }
    

    Add into your spring-configuration

      <bean id="txObjcoreManager" class="org.springframework.transaction.jta.JtaTransactionManager">
            <property name="transactionManager">
                <bean class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
                    <property name="forceShutdown" value="true" />
                </bean>
            </property>
            <property name="userTransaction">
                <bean class="com.atomikos.icatch.jta.UserTransactionImp">
                    <property name="transactionTimeout" value="300" />
                </bean>
            </property>
        </bean>
    
        <bean id="springJtaPlatformAdapter" class="my.domain.spring.hibernate.jta.SpringJtaPlatformAdapter">
            <property name="jtaTransactionManager" ref="txObjcoreManager" />
        </bean>
    

    Don't forget to add a dependency

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
            depends-on="springJtaPlatformAdapter">
    

    And finally change a hibernate configuration like this one hibernate.transaction.jta.platform=my.domain.spring.hibernate.jta.SpringJtaPlatformAdapter

    0 讨论(0)
  • 2020-12-09 06:24

    Some hint for Spring users - just use this implementation if you setup stuff with the factory bean:

    public class AtomikosPlatform extends AbstractJtaPlatform {
    
      private static final long serialVersionUID = -1L;
    
      @Override
      protected TransactionManager locateTransactionManager() {
        return new J2eeTransactionManager();
      }
    
      @Override
      protected UserTransaction locateUserTransaction() {
        return new J2eeUserTransaction();
      }
    
    }
    
    0 讨论(0)
  • 2020-12-09 06:25

    In Hibernate 4.3 the long deprecated TransactionManagerLookup got removed. Now the JTA provider must implement org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform. An abstract implementation of JTA Platform is already available within Hibernate namely org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform. Using this it is quite simple to write a JTA Platform for Atomikos:

    package test;
    
    import javax.transaction.TransactionManager;
    import javax.transaction.UserTransaction;
    import org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform;
    import com.atomikos.icatch.jta.UserTransactionManager;
    
    public class AtomikosJtaPlatform extends AbstractJtaPlatform {
    
      private static final long serialVersionUID = 1L;
      private UserTransactionManager utm;
    
      public AtomikosJtaPlatform() {
        utm = new UserTransactionManager();
      }
    
      @Override
      protected TransactionManager locateTransactionManager() {
        return utm;
      }
    
      @Override
      protected UserTransaction locateUserTransaction() {
        return utm;
      }
    }
    

    In addition the name of the platform implementation class must be added to the hibernate configuration:

    <property name="hibernate.transaction.jta.platform">test.AtomikosJtaPlatform</property>
    
    0 讨论(0)
  • 2020-12-09 06:26

    The following is an alternative approach that works with Spring configuration. This is different from Anton's approach in that is does not rely on instance method writes to a static field (which is generally considered bad practice).

    @SuppressWarnings("serial")
    public class AtomikosJtaPlatform extends AbstractJtaPlatform {
    
        private static TransactionManager transactionManager;
        private static UserTransaction userTransaction;
    
        public static void factoryInit(TransactionManager transactionManager, UserTransaction userTransaction) {
            AtomikosJtaPlatform.transactionManager = transactionManager;
            AtomikosJtaPlatform.userTransaction = userTransaction;
        }
    
        @Override
        protected TransactionManager locateTransactionManager() {
            return transactionManager;
        }
    
        @Override
        protected UserTransaction locateUserTransaction() {
            return userTransaction;
        }
    
    }
    

    Then in Spring configuration:

        <bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init"
            destroy-method="close">
            <property name="startupTransactionService" value="false" />
            <property name="forceShutdown" value="false" />
        </bean>
    
        <bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
            <property name="transactionTimeout" value="300" />
        </bean>
    
        <!-- AtomikosJtaPlatform is created by Hibernate using reflection. This ensures it uses our Spring configured beans --> 
        <bean id="JtaPlatformInitializer" class="org.springframework.beans.factory.config.MethodInvokingBean">
            <property name="targetClass" value="com.mycompany.a.b.AtomikosJtaPlatform" />
            <property name="targetMethod" value="factoryInit" />
            <property name="arguments">
                <list>
                    <ref bean="AtomikosTransactionManager" />
                    <ref bean="AtomikosUserTransaction" />
                </list>
            </property>
        </bean>
    
    <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="JtaPlatformInitializer">
            <property name="jpaProperties">
                <props>
                    <prop key="hibernate.transaction.jta.platform">com.mycompnay.a.b.AtomikosJtaPlatform</prop>
     ...
    
    0 讨论(0)
提交回复
热议问题