WAS 6.1, JPA с JTA, Hibernate, Spring: проблема поиска данных - PullRequest
6 голосов
/ 07 декабря 2009

Я запускаю приложение со следующими компонентами:

  • Oracle 9i
  • WAS 6.1.0.23 с пакетом функций WS и EJB3
  • JPA с Hibernate 3.3.2.GA в качестве поставщика (с Hibernate-EntityManager 3.4.0)
  • Менеджер транзакций Spring для WAS: UowTransactionManager (весна 2.5.6)
  • Веб-поток Spring с управляемым потоком постоянством (2.0.8), т. Е. Менеджер сущностей сериализуется в сеанс http и восстанавливается при каждом запросе.

В каждом запросе, переходящем от веб-контроллера к уровню обслуживания (аннотированному с помощью SpringT @ Transactional), я заметил, что для каждого запроса SQL, который Hibernate выполняет во время вызова службы внутри транзакции, новое соединение DataSource запрашивается из JNDI DataSource от Hibernate ConnectionProvider, пока DataSource не исчерпает свободные соединения и в конечном итоге зависает.

Вот части конфигурации:

  1. Spring:

    <tx:annotation-driven />
    <context:component-scan base-package="org.home.myapp" />
    <jee:jndi-lookup id="dataSource" jndi-name="jdbc/DS" resource-ref="true"/>
    <bean id="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
    <bean id="EMF" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
      <property name="dataSource" ref="dataSource"/>
      <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
      </property>
    </bean>
    
  2. persistence.xml

    <persistence-unit name="persistence" transaction-type="JTA">
      <properties>
        <property name="hibernate.archive.autodetection" value="class"/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle9iDialect"/>
        <property name="hibernate.current_session_context_class" value="jta"/>
        <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
        <property name="hibernate.format_sql" value="true"/>
        <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.default_batch_fetch_size" value="20"/>
        <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup"/>   
      </properties>
    </persistence-unit>
    
  3. Услуга

    @Transactional(readOnly=true) @Service
    public class MyServiceImpl implements MyService {
      @Autowired MyDao dao;
      public void getSomething() {
        dao.findSomething();
      }
    }
    
  4. DAO

    @Repository
    public class MyDaoJap implements MyDao {
      @PersistenceContext EntityManager em;
      public void findSomething() {
        em.find(...);
      }
    }
    

Обратите внимание, что транзакция доступна только для чтения, что является нормальным для постоянства потока: только последний переход (с commit = true) вызывает не транзакционный метод readOnly. Включение флага readOnly автоматически переводит режим сброса в спящий режим в РУЧНОЙ.

Во время отладки я заметил следующее:

  • Менеджер транзакций UOW корректно вызывается в цепочке перехвата службы, что указывает на то, что транзакция активна
  • Hibernate запрашивает соединение, вызывая DataSource.getConnection () для необработанного DataSource, который вводится в EMF; Стратегия получения соединения взята из InjectedDataSourceConnectionProvider в Hibernate, и этот класс ссылается на WAS DataSource (а не на прокси-сервер, который знает об активной транзакции или тому подобное).

Полагаю, проблема в этом втором пункте, но я не могу найти ошибку в моей конфигурации. Кто-нибудь может помочь?

Спасибо за вашу помощь.

Ответы [ 2 ]

2 голосов
/ 13 июля 2010

некоторые дикие догадки из нашего конфига

  • спящий режим - hibernate.connection.release_mode = after_statement
  • config.atml источника данных web.xml config - Совместно используемый </ res-shared-scope>
  • весенний сессионный файл конфигурации - useTransactionAwareDataSource = "true"

это даже может быть проблема конфигурации внутри была

0 голосов
/ 08 декабря 2009

Я думаю (и надеюсь), что ваши проблемы проистекают из того факта, что при использовании свойства dataSource по умолчанию устанавливается «nonJtaDataSource». Стандартная (простая) конфигурация действительно оптимизирована для транзакционных систем более низкого уровня (tomcat / SE), а не для более жесткого стека, который вы используете.

Вам необходимо настроить фабрику диспетчера сущностей для получения источника данных jta. Способ, которым я это сделал, - создать свой собственный JtaPersistenceUnitPostProcessor, где я мог бы это настроить.

Делая это таким образом, я смог настроить EMF для использования JtaDatasource, я не уверен, есть ли лучший способ сделать это. Вы можете просто как POC добавить ссылку на источник данных jta в ваш файл persistence.xml.

...