2009-12-07 12 views
6

sto correndo un programma con i seguenti componenti:WAS 6.1, JPA con JTA, Hibernate, Spring: problema di reperimento dei dati

  • Oracle 9i
  • WAS 6.1.0.23 con WS e EJB3 caratteristiche pacchetto
  • JPA con Hibernate 3.3.2.GA come fornitore (con Hibernate-EntityManager 3.4.0)
  • primavera gestore delle transazioni per WAS: UowTransactionManager (primavera 2.5.6) webflow
  • primavera con la persistenza del flusso gestiti (2.0. 8), cioè il il gestore di entità viene serializzato nella sessione http e ripristinato su ogni richiesta.

In ogni richiesta che va dal controller Web al livello di servizio (annotato con @Transactional di primavera), ho notato che per ogni query SQL che Hibernate effettua durante l'invocazione del servizio all'interno della transazione, una nuova connnection DataSource è richiesto da jndi DataSource da ConnectionProvider di Hibernate, fino a quando DataSource esaurisce le connessioni libere e alla fine si blocca.

Ecco parti della configurazione:

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

    @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 della transazione è di sola lettura, che è normale per il flusso di persistenza: solo l'ultimo di transizione (con commit = true) invoca un metodo transazionale non readOnly. L'attivazione del flag readOnly attiva automaticamente la modalità di scarico Hibernate su MANUAL.

Mentre si fa un po 'di debug, ho notato quanto segue:

  • Il gestore delle transazioni UOW è correttamente invocato nella catena intercettazione del servizio, il che suggerisce che una transazione è attiva
  • Hibernate richiede una connessione invocando DataSource.getConnection() sul DataSource non elaborato che viene iniettato nell'EMF; La strategia per ottenere una connessione proviene da InjectedDataSourceConnectionProvider di Hibernate e questa classe fa riferimento a WAS DataSource (non un proxy a conoscenza di una transazione attiva o simile).

Immagino che il problema sia in questo secondo punto, ma non riesco a trovare un errore nella mia configurazione. Qualcuno può aiutare?

Grazie per il vostro aiuto.

risposta

2

alcune congetture selvagge del nostro config

  • hibernate prop - hibernate.connection.release_mode = after_statement
  • web.xml risorsa rif origine dati di configurazione - < res-sharing-scope > Condivisibile </res-sharing -Scope >
  • primavera sessionFactory config - useTransactionAwareDataSource = "true"

potrebbe anche essere un problema di configurazione all'interno era

+0

La seconda è la risposta corretta. L'ambito di condivisione di DataSource era Unsharable. Grazie mille. – Gaetan

0

Penso (e spero) che i tuoi problemi derivino dal fatto che utilizzando la proprietà dataSource è impostato su "nonJtaDataSource".La configurazione predefinita (semplice) è davvero ottimizzata per i sistemi transazionali di livello inferiore (tomcat/SE) e non per lo stack più hardcore che si sta utilizzando.

Avrete bisogno di configurare il factory manager di entità per avere un'origine dati jta. Il modo in cui ho fatto questo è quello di creare il mio JtaPersistenceUnitPostProcessor in cui ho potuto impostare questo.

In questo modo sono riuscito a impostare l'EMF per l'utilizzo di JtaDatasource, non sono sicuro se c'è un modo migliore per farlo. Potresti semplicemente, come POC, aggiungere il riferimento all'origine dati jta al tuo persistence.xml.

+0

Guardando il codice Spring per DefaultPersistenceUnitManager e PersistenceUnitReader, ho notato che il DataSource che viene iniettato in LocalContainerEntityManagerFactoryBean viene utilizzato così com'è per definire l'origine dati jta e non-jta di l'unità di persistenza (se tale elemento corrispondente è dichiarato in persistence.xml, con qualsiasi valore). Alla fine, se nell'unità di elaborazione non è specificato alcun elemento non-jta-source-source, la stessa origine dati viene iniettata come origine non-jta-datasource. Così, ho aggiunto un elemento jta-data-source nel mio persistence.xml, e si comporta ancora allo stesso modo. – Gaetan

+0

Spring fornisce 3 implementazioni per l'interfaccia di ConnectionProvider di Hibernate: LocalDataSourceConnectionProvider e 2 sottoclassi, LocalJtaDataSourceConnectionProvider e TransactionAwareDataSourceConnectionProvider; sono tutti nel pacchetto orm.hibernate3 (non jpa), questo non penso che dovrebbero essere usati per JPA. Durante l'esecuzione della mia app, il provider di connessione configurato è InjectedDataSourceConnectionProvider di Hibernate; Mi aspetto un qualche tipo di DataSource sensibile alle transazioni (a meno che la transazione non sia interamente delegata a WAS DataSource) ... – Gaetan

Problemi correlati