2010-09-16 3 views
6

Ich habe zwei Entitätsmanager in meiner applicationContext.xml, die zwei verschiedenen Datenbanken entspricht. Ich kann database1 mit entityManager1 leicht abfragen, aber wenn ich versuche, auf database2 mit entityManager2 zuzugreifen, erhalte ich keine Resultate. Ich benutze Spring + Hibernate + JPA. HierProblem mit mehreren Entitätsmanagern im Frühjahr, wenn mehr als eine Datenquelle verwendet wird

ist mein 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> 

Dies ist meine Service-Layer-Code, der mit enityManager1 gut funktioniert:

@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; 
    } 

} 

    } 

Meine beiden persitence.xml Dateien wie folgt aussehen:

<?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> 

und

<?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> 

Wenn ich meine Serviceebene (wie unten gezeigt) ändere, erhalte ich keine Ergebnisse. Grundsätzlich ist die Größe der Liste ist Null:

@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; 
    } 

} 

} 

Also im Grunde können Sie sehen, ist, dass ich zwei Entitäten (Staaten) mit genau derselben Struktur und um voneinander zu unterscheiden ich sie in separate Pakete geschnürt haben

Nach meinem Wissen mache ich hier nichts Verrücktes, aber es scheint nicht zu funktionieren. Wie wird dieses Problem verursacht und wie kann ich das lösen?

Follow-up: Eine Sache, die ich vergessen zu erwähnen, ist, dass, obwohl es zwei verschiedene Datenbanken gibt, aber der Name des Datenbankservers ist gleich. Ich weiß nicht, ob das eine nützliche Information sein könnte.

Dies ist die Ausnahme, die ich jetzt immer bin:

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

Sie injizieren immer noch ein EM für PU1 in der obigen Probe, ist es ein Tippfehler? Und warum hast du eigentlich zwei Versionen des 'State'? Was ist der Punkt? –

+0

Hallo Pascal, ja! Das ist ein Tippfehler. Ich habe es auch mit der Single-State-Version versucht, aber immer noch das gleiche Problem. Der Grund, warum zwei Zustände sind, weil in einer Datenbank die Zustandstabelle eine Eins-zu-Viele-Beziehung hat und in der zweiten Datenbank nicht. Auch wenn die Struktur identisch ist, aber die Einschränkungen sind unterschiedlich. –

+0

Bitte korrigieren Sie den Tippfehler. Dies ist ein Ablenkungsmanöver. – BalusC

Antwort

11

ich exakt das gleiche Problem getroffen habe, aber mit mehreren Hibernate Sitzung Fabriken: 2 DBs mit der gleichen Struktur, ich will nicht haben, 2 identische Sätze von DAOs usw. Während meiner Erfahrung mit Hibernate, vermute ich, dass Sie die gleiche Lösung verwenden könnten: Spring AbstractRoutingDataSource. Sie können Ihre App so konfigurieren, dass sie zur Laufzeit feststellt, welche Datenquelle verwendet werden soll, basierend auf einem Wert, der unter ThreadLocal festgelegt wurde. Eine Einführung finden Sie unter http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/. Was passiert ist, dass die dataSource Ref in Ihrer Fabrik nicht auf eine fest codierte dataSource Bean, sondern auf die AbstractRoutingDataSource. Um die Umschaltfunktion pro Thread festzulegen, verwenden Sie ein @Aspect, um zu ermitteln, welche Datenbank betroffen ist.