2009-12-07 13 views
6

estoy ejecutando una aplicación con los siguientes componentes:fue de 6.1, JPA con JTA, Hibernate, Spring: problema de la recuperación de datos

  • Oracle 9i
  • ERA 6.1.0.23 con WS y EJB3 ofrece paquete
  • JPA con Hibernate 3.3.2.GA como proveedor (con Hibernate-EntityManager 3.4.0) gestor de transacciones
  • resorte por fue: UowTransactionManager (primavera 2.5.6) WebFlow
  • del resorte con persistencia gestionada por flujo (2.0. 8), es decir, el El administrador de entidades se serializa en la sesión http y se restaura en cada solicitud.

En cada solicitud que va desde el controlador web para la capa de servicio (anotado con @Transactional de primavera), me he dado cuenta que por cada consulta SQL que Hibernate realiza durante la invocación del servicio dentro de la transacción, un nuevo connnection origen de datos es solicitado por jndi DataSource por el proveedor de conexión de Hibernate, hasta que el DataSource se quede sin conexiones gratuitas y finalmente se cuelgue.

Estas son partes de la configuración:

  1. primavera:

    <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. Servicio

    @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(...); 
        } 
    } 
    

Nota la transacción es de sólo lectura, que es normal para el flujo de persistencia: sólo la última transición (con cometer = true) invoca un método transaccional no readOnly. Al encender el indicador readOnly, el modo de lavado de Hibernate se convierte automáticamente en MANUAL.

mientras hace algo de depuración, me di cuenta de lo siguiente:

  • El administrador de transacciones UOW se invoca correctamente en la cadena de intercepción del servicio, lo que sugiere que una transacción está activo
  • Hibernate pide una conexión invocando DataSource.getConnection() en el DataSource sin procesar que se inyecta en el EMF; La estrategia para obtener una conexión es del InjectedDataSourceConnectionProvider de Hibernate, y esta clase hace referencia al WAS DataSource (no un proxy que tenga conocimiento de una transacción activa, o tal).

Supongo que el problema está en este segundo punto, pero no puedo encontrar un error en mi configuración. ¿Alguien puede ayudar?

Gracias por su ayuda.

Respuesta

2

algunas conjeturas salvajes de nuestro config

  • hibernación prop - hibernate.connection.release_mode = after_statement
  • Web.xml ref recurso de fuente de datos de configuración - < res de intercambio de alcance > Shareable </res para compartir -scope sessionFactory config >
  • primavera - useTransactionAwareDataSource = "true"

incluso podría ser un problema de configuración en el interior

+0

La segunda es la respuesta correcta. El alcance compartido de DataSource era Unsharable. Muchas gracias. – Gaetan

0

Creo (y espero) que sus problemas se deriven del hecho de que al usar la propiedad dataSource se establece de manera predeterminada en "nonJtaDataSource".La configuración predeterminada (simple) está realmente optimizada para sistemas transaccionales de menor calidad (tomcat/SE) y no para la pila más hardcore que está utilizando.

Vas a necesitar configurar la fábrica del administrador de entidades para que tenga un origen de datos jta. La forma en que hice esto fue crear mi propio JtaPersistenceUnitPostProcessor donde pude configurar esto.

Al hacerlo de esta manera, pude configurar el EMF para utilizar un JtaDatasource, no estoy seguro de si hay una mejor manera de hacerlo. Simplemente, como POC, agregue la referencia de fuente de datos jta a su persistence.xml.

+0

Al mirar el código Spring para DefaultPersistenceUnitManager y PersistenceUnitReader, noté que el DataSource que se inyecta en el LocalContainerEntityManagerFactoryBean se usa tal como está para definir el jta y el no-jta-datasource de la unidad de persistencia (si tal elemento correspondiente se declara en persistence.xml, con cualquier valor). Eventualmente, si no se especifica ningún elemento que no sea jta-data-source en la PU, esa misma fuente de datos se inyectará como la fuente no-jta-datasource. Por lo tanto, agregué un elemento jta-data-source en mi persistence.xml, y todavía se comporta igual. – Gaetan

+0

Spring proporciona 3 implementaciones para la interfaz de ConnectionProvider de Hibernate: LocalDataSourceConnectionProvider y 2 subclases, LocalJtaDataSourceConnectionProvider y TransactionAwareDataSourceConnectionProvider; todos están en el paquete orm.hibernate3 (no en jpa), esto no creo que deban usarse para JPA. Al ejecutar mi aplicación, el proveedor de conexión que está configurado es InjectedDataSourceConnectionProvider de Hibernate; Esperaría algún tipo de DataSource sensible a las transacciones (a menos que la transacción se delegue por completo a WAS DataSource) ... – Gaetan

Cuestiones relacionadas