2016-12-21 1 views
0

Я пытаюсь переместить наше приложение вперед. Теперь он работает под Glassfish 3, JAVA EE 6 и использует Hibernate 3 в качестве реализации JPA. Я написал пример, который показывает проблему с транзакциями. В некоторых циклах приложения необходимо вручную вызвать метод flush() менеджера сущностей. Но даже в среде JTA происходит то, что flush() вызывает физическую фиксацию в базовой базе данных (мы используем драйвер JDBC ojdbc6.jar для подключения к ORACLE X/XI). Это не ожидаемое поведение из-за того, что транзакция JDBC должна присоединиться к транзакции JTA. Если после сброса() исключение возбуждается EJB, сброшенные данные должны быть отброшены. В Hibernate 3 все работает отлично. В Hibernate 4.3.5 это не так.Не удается присоединиться к транзакции JDBC с транзакцией JTA с Hibernate 4/Hibernate 5 на Glassfish 4, когда flush() вызван вручную

отладка кода 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 и здесь проблема AutoJoinTransaction исчезла, большая часть кода транзакции был переписан. В любом случае проблема 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> 

Что мне не хватает? Любая помощь будет оценена по достоинству. Спасибо заранее,

Дэвид Obber

+0

GlassFish обычно не использует Hibernate, но EclipseLink. Как вы интегрировали Hibernate в GlassFish и могла ли эта интеграция быть причиной? –

+0

Мы просто добавили его в EAR. Интеграция может быть проблемой, но ее не должно быть. В GF3 это не так. Hibernate имеет селектор стратегий с конкретной реализацией для Glassfish. Тот же EAR, установленный на Wildfly 9, исправляет транзакцию. Таким образом, проблема может быть в классах Hibernate «Glassfish oriented» или в самой Glassfish. Переход к другой реализации JPA, такой как EclipseLink, не является вариантом, который у нас есть. –

ответ

0

Ну, я вижу, что вы используете EJB, режим по умолчанию транзакций в EJB является Container Managed транзакции (СМТ), в этом режиме, ответственность за управление сделками из контейнера EJB. Он открывается, закрывается, прерывается в соответствии с транзакционным атрибутом каждого метода Session Beans в режиме CMT.

@TransactionManagement (TransactionManagementType . CONTAINER) 
public class YourClass 

См Бина Управляемые транзакции - BMT

@TransactionManagement (TransactionManagementType . BEAN) 
public class YouClass 

Использование ТКМ, вы можете открыть, закрыть, отменить и т.д., и ответственность от приложения

+0

Дело не в этом. Контейнер должен гарантировать, что транзакция, которая управляется, не передает данные при откате транзакции. –

1

Моя ошибка! Я пропустил элемент ref-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>`` 
Смежные вопросы