2010-09-16 7 views
6

Ho due gestori di entità nel mio applicationContext.xml che corrisponde a due diversi database. Posso facilmente interrogare database1 con entityManager1, ma quando provo ad accedere a database2 con entityManager2, non ottengo alcun risultato. Sto usando Spring + Hibernate + JPA.Problema di gestore di più entità in primavera quando si utilizza più di un'origine dati

Ecco il mio ApplicationContext.xml

<?xml version="1.0" encoding="UTF-8"?> 

    <beans default-autowire="byName" 
    xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xsi:schemaLocation=" 
     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 
     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> 

<bean 
    class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 


<bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="jpaVendorAdapter"> 
    <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
    <property name="database" value="INFORMIX" /> 
    <property name="showSql" value="true" /> 
    </bean> 
    </property> 
    <property name="persistenceUnitManager" ref="persistenceUnitManager" /> 
    <property name="persistenceUnitName" value="PU1" /> 
</bean> 



<bean id="entityManagerFactory2" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="dataSource2" /> 
    <property name="jpaVendorAdapter"> 
    <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
    <property name="database" value="INFORMIX" /> 
    <property name="showSql" value="true" /> 
    </bean> 
    </property> 
    <property name="persistenceUnitManager" ref="persistenceUnitManager" /> 
    <property name="persistenceUnitName" value="PU2" /> 
</bean> 



<!-- Data Sources --> 

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 
    destroy-method="close"> 
    <property name="driverClassName" value="com.ibm.db2.jcc.DB2Driver" /> 
    <property name="url" 
    value="jdbc:db2://HOST_NAME:PORT_NO/DB_NAME:INFORMIXSERVER=SERVER_NAME;DELIMIDENT=y;" /> 
    <property name="username" value="username" /> 
    <property name="password" value="password" /> 
    <property name="minIdle" value="2" /> 
</bean> 

<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" 
    destroy-method="close"> 
    <property name="driverClassName" value="com.ibm.db2.jcc.DB2Driver" /> 
    <property name="url" 
    value="jdbc:db2://HOST_NAME:PORT_NO/DB_NAME2:INFORMIXSERVER=SERVER_NAME;DELIMIDENT=y;" /> 
    <property name="username" value="username" /> 
    <property name="password" value="password" /> 
    <property name="minIdle" value="2" /> 
</bean> 

<bean 
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" 
    lazy-init="false"> 
    <property name="targetObject" ref="dataSource" /> 
    <property name="targetMethod" value="addConnectionProperty" /> 
    <property name="arguments"> 
    <list> 
    <value>characterEncoding</value> 
    <value>UTF-8</value> 
    </list> 
    </property> 
</bean> 

<bean 
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" 
    lazy-init="false"> 
    <property name="targetObject" ref="dataSource2" /> 
    <property name="targetMethod" value="addConnectionProperty" /> 
    <property name="arguments"> 
    <list> 
    <value>characterEncoding</value> 
    <value>UTF-8</value> 
    </list> 
    </property> 
</bean> 

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" 
    scope="prototype"> 
    <property name="dataSource" ref="dataSource" /> 
</bean> 



<bean id="persistenceUnitManager" 
    class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager"> 
    <property name="persistenceXmlLocations"> 
    <list> 
    <value>classpath*:META-INF/persistence.xml</value> 
    <value>classpath*:META-INF/persistence2.xml</value> 
    </list> 
    </property> 
    <property name="dataSources"> 
    <map> 
    <entry key="localDataSource" value-ref="dataSource" /> 
    <entry key="dataSource2" value-ref="dataSource2" /> 
    </map> 
    </property> 
    <property name="defaultDataSource" ref="dataSource" /> 
</bean> 



<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory" /> 
</bean> 

<bean id="transactionManager2" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory2" /> 
</bean> 

<tx:annotation-driven transaction-manager="transactionManager" /> 
<tx:annotation-driven transaction-manager="transactionManager2" /> 

<!-- MORE Action and DAO beans --> 


</beans> 

Questo è il mio codice di livello di servizio che funziona bene con enityManager1:

@Transactional 
    public class StatesDAO implements IStatesDAO { 
private EntityManager em; 

@PersistenceContext(unitName = "PU1") 
public void setEntityManager(EntityManager em) { 
    this.em = em; 
} 

private EntityManager getEntityManager() { 
    return em; 
} 

@SuppressWarnings("unchecked") 
public List<States> findAll() { 
    logger.info("finding all States instances"); 
    try { 
    final String queryString = "select model from States model"; 

    Query query = getEntityManager().createQuery(queryString); 
    return query.getResultList(); 

    } catch (RuntimeException re) { 
    throw re; 
    } 

} 

    } 

I miei due persitence.xml file simile a questa:

<?xml version="1.0" encoding="UTF-8"?> 
<persistence version="1.0" 
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"> 
<persistence-unit name="PU1" transaction-type="RESOURCE_LOCAL"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <class>com.jpa.entity.States</class> 
</persistence-unit> 
</persistence> 

e

<?xml version="1.0" encoding="UTF-8"?> 
<persistence version="1.0" 
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"> 
<persistence-unit name="PU2" transaction-type="RESOURCE_LOCAL"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <class>com.jpa.other.entity.States</class> 
</persistence-unit> 
</persistence> 

Se cambio il livello di servizio (come mostrato di seguito), non ottengo risultati. Fondamentalmente la dimensione della lista è pari a zero:

@Transactional 
public class StatesDAO implements IStatesDAO { 
private EntityManager em; 

@PersistenceContext(unitName = "PU2") 
public void setEntityManager(EntityManager em) { 
    this.em = em; 
} 

private EntityManager getEntityManager() { 
    return em; 
} 

@SuppressWarnings("unchecked") 
public List<com.jpa.other.entity.States> findAll() { 
    logger.info("finding all States instances"); 
    try { 
     final String queryString = "select model from States model"; 

     Query query = getEntityManager().createQuery(queryString); 
     return query.getResultList(); 

    } catch (RuntimeException re) { 
     throw re; 
    } 

} 

} 

Quindi, in pratica si può vedere è che ho due entità (Stati) con esattamente stessa struttura e al fine di differenziare le une dalle altre le ho messo in pacchetti separati

Secondo la mia conoscenza, non sto facendo niente di pazzo qui, ma ancora non sembra funzionare. Come viene causato questo problema e come posso risolverlo?

Follow-up: Una cosa che ho dimenticato di menzionare è che anche se ci sono due database diversi ma il nome del server del database è lo stesso. Non so se questa potrebbe essere una informazione utile. Ho pensato di condividerlo.

questa è l'eccezione sto ottenendo ora:

16:24:44,732 INFO [STDOUT] Hibernate: select state0_.state as col_0_0_ from states state0_ 
16:24:44,753 WARN [JDBCExceptionReporter] SQL Warning: 36106, SQLState: 01I01 
16:24:44,753 WARN [JDBCExceptionReporter] IDS SQL Warning: SQLCODE=36106, SQLSTATE=01I01, SQLERRMC=0;819;informix;;IDS/NT32;1;1;0;819;0;, DRIVER=4.7.85 
+1

Stai ancora iniettando un EM per PU1 nel campione sopra, è un refuso? E perché hai in realtà due versioni dello 'stato'? Qual e il punto? –

+0

Ciao Pascal, sì! questo è un errore di battitura. Ho provato anche con la versione Single State, ma ho ancora lo stesso problema. Il motivo per cui due stati perché in un database la tabella di stato ha una relazione uno a molti e nel secondo database non lo fa. Anche se la struttura è la stessa ma i vincoli sono diversi. –

+0

Si prega di correggere l'errore di battitura. Questa è una falsa pista. – BalusC

risposta

11

ho colpito lo stesso problema esatto, ma con più fabbriche di sessione Hibernate: 2 DB con la stessa struttura, non volevo avere 2 insiemi identici di DAO, ecc. Mentre la mia esperienza era con Hibernate, ho il sospetto che potessi usare la stessa soluzione: Spring's AbstractRoutingDataSource. Consente di configurare l'app per determinare a runtime quale origine dati utilizzare, in base a un valore impostato su ThreadLocal. Vedi http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/ per un'introduzione. Quello che finisce per accadere è che il ref dataSource nella tua fabbrica punterà non su un bean codificato dataSource, ma allo AbstractRoutingDataSource. Per impostare il commutatore per thread, utilizzare un @Aspect per determinare quale DB colpire.