手动调用 flush() 时,无法将 JDBC 事务与 Glassfish 4 上的 Hibernate 4/Hibernate 5 的 JTA 事务联接



我正在尝试将应用程序向前推向。现在,它在Glassfish 3,Java EE 6下运行,并使用Hibernate 3作为JPA实施。我写了一个示例,显示我的交易问题。在某些情况下,应用程序需要手动调用Entity Manager flush()方法。但是,即使在JTA环境中,也会发生flush()在基础数据库上引起物理提交(我们正在使用ojdbc6.jar jdbc驱动程序连接到Oracle X/XI)。这不是预期的行为,因为JDBC交易应加入JTA交易的事实。如果flush()在EJB提出异常,则应汇回数据。在Hibernate 3中,一切正常。在Hibernate 4.3.5中没有。

调试Hibernate 4.3代码我找到了此

package org.hibernate.jpa.internal.EntityManagerImpl
           @Override
           protected Session internalGetSession() {
                          if ( session == null ) {
                                        ...
                                        SessionBuilderImplementor sessionBuilder = internalGetEntityManagerFactory().getSessionFactory().withOptions();
--->>>>>>          sessionBuilder.autoJoinTransactions( getTransactionType() != PersistenceUnitTransactionType.JTA ); <<<<<<-----
                                        session = sessionBuilder.openSession();
                          }
                          return session;
           }

这将领导org.hibernate.engine.transaction.internal.transactionCoordinatorImpl.AttEmptToreGisterJtasync()方法进入该块中并跳过与JTA平台的同步。

 ....
           final JoinStatus joinStatus = currentHibernateTransaction.getJoinStatus();
           if ( joinStatus != JoinStatus.JOINED ) {
                                        // the transaction is not (yet) joined, see if we should join...
 ---->>>>>            if ( !transactionContext.shouldAutoJoinTransaction() ) {  <<<<<<----
                                                       // we are supposed to not auto join transactions; if the transaction is not marked for join
                                                       // we cannot go any further in attempting to join (register sync).
                                                       if ( joinStatus != JoinStatus.MARKED_FOR_JOINED ) {
                                                                      if (isDebugging) {
                                                                                     LOG.debug( "Skipping JTA sync registration due to auto join checking" );
                                                                      }
                                                                      return;
                                                       }
                                        }
                          }

我试图调试Hibernate 5,在这里自动施加问题消失了,大多数交易代码已重写。在任何情况下,仍然存在flush()问题。

我写了一个证明它的小例子。

@Stateless
public class BaseServicesAdapterImpl implements BaseServicesAdapterInterface {
    @PersistenceContext 
    protected EntityManager em;
    @Resource SessionContext sessionContext;
    public EntityManager getEm() {
        return em;
    }
    public void setEm(EntityManager em) {
        this.em = em;
    }
    @Override
    public String test() {
        persistEntityAndFlush();
        return "finished";
    }

    private void persistEntityAndFlush() {
        persistEntityAndFlush("TST", new Integer(5), new Long(-1), new Long(-1), 
                new Date(), "", null, new Date(), new Integer(10), "test transaction", 
                null, null, null, "");      
    }

    private Long persistEntityAndFlush(String tipoProcesso, Integer tpEntita, Long idEntita, Long progr,
            Date date, String stato, String subStato, Date dtStato, Integer ggTimer,
            String descrizione, String idPrcPerif1, String idPrcPerif2, String idPrcPerif3, String chiave1) {
            Long idProcesso = 0L;
            TestEntity testEntity = new TestEntity();
            testEntity.setTpEntita(tpEntita);
            testEntity.setIdEntita(idEntita);
            testEntity.setIdProcesso(idProcesso);
            //.....
            getEm().persist(testEntity);
            //***** THIS FLUSH COMMITS THE DATA *****
            getEm().flush(); 
            throw new RuntimeException("Too late?");
    }

}

这是perstistence.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
    version="1.0">
    <persistence-unit name="test_pu" transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <jta-data-source>dsName</jta-data-source>
        <properties>
            <property name="hibernate.hbm2ddl.auto" value="none" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="false" />
            <property name="hibernate.use_sql_comments" value="false" />
            <property name="hibernate.generate_statistics" value="false" />
            <property name="hibernate.ejb.metamodel.generation" value="disabled" />
            <!-- removing this does not affect anything -->
            <property name="hibernate.connection.release_mode" value="after_transaction" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
            <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform" />            
        </properties>
    </persistence-unit>
</persistence>

我想念什么?任何帮助将不胜感激。预先感谢,

David Obber

我的错误!我错过了Resource-REF元素!我尚不清楚为什么这会导致问题,但添加了解决问题。

  <servers>
    <server config-ref="server-config" name="server">
  <!-- WITH THE FOLLOWING LINE THE TRANSACTION PROBLEM DISAPPEARS -->
      <resource-ref ref="MyDataSource"></resource-ref>
    </server>
  </servers>``

好吧,我看到您使用EJB,EJB中的默认交易模式是容器托管交易(CMT),在此模式下,管理交易的责任来自EJB容器。它按照CMT模式下的每个会话bean方法的交易属性开放,关闭,中止。

@TransactionManagement ( TransactionManagementType . CONTAINER )
public class YourClass

请参阅Bean托管交易-BMT

@TransactionManagement ( TransactionManagementType . BEAN )
public class YouClass

使用BMT,您可以打开,关闭,流产等,责任来自您的应用程序

最新更新