30 votes

Base de données multiple avec Spring + Hibernate + JPA

Je suis en train de configurer Spring+Hibernate+JPA pour le travail avec les deux bases de données (MySQL et MSSQL)

mon datasource-context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
 xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
  http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd"
 xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:util="http://www.springframework.org/schema/util">

 <!--
 Data Source config 
  -->
 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
  destroy-method="close" p:driverClassName="${local.jdbc.driver}" p:url="${local.jdbc.url}"
  p:username="${local.jdbc.username}" p:password="${local.jdbc.password}">
 </bean>

 <bean id="dataSourceRemote" class="org.apache.commons.dbcp.BasicDataSource"
  destroy-method="close" p:driverClassName="${remote.jdbc.driver}"
  p:url="${remote.jdbc.url}" p:username="${remote.jdbc.username}"
  p:password="${remote.jdbc.password}" />

 <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
  p:entity-manager-factory-ref="entityManagerFactory" />

 <!-- 
    JPA config   
    -->
 <tx:annotation-driven transaction-manager="transactionManager" />

 <bean id="persistenceUnitManager"
  class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
        <property name="persistenceXmlLocations">
   <list value-type="java.lang.String">
    <value>classpath*:config/persistence.local.xml</value>
    <value>classpath*:config/persistence.remote.xml</value>
   </list>
  </property>

  <property name="dataSources">
   <map>
    <entry key="localDataSource" value-ref="dataSource" />
    <entry key="remoteDataSource" value-ref="dataSourceRemote" />
   </map>
  </property>
  <property name="defaultDataSource" ref="dataSource" />
 </bean>

 <bean id="entityManagerFactory"
  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="jpaVendorAdapter">
   <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
    p:showSql="true" p:generateDdl="true">
   </bean>
  </property>
  <property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceUnitName" value="localjpa"/>
 </bean>

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

</beans>

chaque persistence.xml contient une unité, comme ceci:

<persistence-unit name="remote" transaction-type="RESOURCE_LOCAL">
  <properties>
   <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy" />
   <property name="hibernate.dialect" value="${remote.hibernate.dialect}" />
   <property name="hibernate.hbm2ddl.auto" value="${remote.hibernate.hbm2ddl.auto}" />
  </properties>
 </persistence-unit>

PersistenceUnitManager cause exception suivante:

Ne peut pas résoudre référence aux haricots 'persistenceUnitManager' pendant le réglage bean propriété 'persistenceUnitManager'; imbriqué exception est org.springframework.les haricots.usine.BeanCreationException: Erreur lors de la création de haricots avec le nom 'persistenceUnitManager" défini dans la le chemin de classe de ressource [config/datasource-context.xml]: Initialisation du bean n'a pas; imbriqué exception est org.springframework.les haricots.TypeMismatchException: Impossible de convertir la valeur de la propriété type [java.util.ArrayList] requis type [java.lang.String] pour les biens 'persistenceXmlLocation'; imbriqué exception est java.lang.IllegalArgumentException: Ne peut pas convertir une valeur de type [java.util.ArrayList] de type [java.lang.String] pour les biens 'persistenceXmlLocation": pas de correspondance les éditeurs ou stratégie de conversion trouvé

Si laissé seul persistence.xml sans liste, tout fonctionne très bien mais j'ai besoin de 2 unités...

J'ai aussi essayer de trouver une autre solution pour le travail avec les deux bases de données dans Spring+Hibernate contexte, donc j'apprécierais toute solution

nouvelle erreur après le passage à persistenceXmlLocations

Pas un seul défaut unité de persistance défini dans {classpath:config/persistence.local.xml, classpath:config/persistence.remote.xml}

Mise à JOUR: - Je ajouter persistenceUnitName, cela fonctionne, mais seulement avec une unité, encore besoin d'aide

Mise à JOUR: merci, ChssPly76

J'ai modifié les fichiers de configuration: datasource-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
    	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
    	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util">

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    	destroy-method="close" p:driverClassName="${local.jdbc.driver}" p:url="${local.jdbc.url}"
    	p:username="${local.jdbc.username}" p:password="${local.jdbc.password}">
    </bean>

    <bean id="dataSourceRemote" class="org.apache.commons.dbcp.BasicDataSource"
    	destroy-method="close" p:driverClassName="${remote.jdbc.driver}"
    	p:url="${remote.jdbc.url}" p:username="${remote.jdbc.username}"
    	p:password="${remote.jdbc.password}">
    </bean>

    <bean
    	class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
    	<property name="defaultPersistenceUnitName" value="pu1" />
    </bean>

    <bean id="persistenceUnitManager"
    	class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
    	<property name="persistenceXmlLocation" value="${persistence.xml.location}" />
    	<property name="defaultDataSource" ref="dataSource" /> <!-- problem -->
    	<property name="dataSources">
    		<map>
    			<entry key="local" value-ref="dataSource" />
    			<entry key="remote" value-ref="dataSourceRemote" />
    		</map>
    	</property>
    </bean>

    <bean id="entityManagerFactory"
    	class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    	<property name="jpaVendorAdapter">
    		<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
    			p:showSql="true" p:generateDdl="true">
    		</bean>
    	</property>
    	<property name="persistenceUnitManager" ref="persistenceUnitManager" />
    	<property name="persistenceUnitName" value="pu1" />
    	<property name="dataSource" ref="dataSource" />
    </bean>

    <bean id="entityManagerFactoryRemote"
    	class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    	<property name="jpaVendorAdapter">
    		<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
    			p:showSql="true" p:generateDdl="true">
    		</bean>
    	</property>
    	<property name="persistenceUnitManager" ref="persistenceUnitManager" />
    	<property name="persistenceUnitName" value="pu2" />
    	<property name="dataSource" ref="dataSourceRemote" />
    </bean>

    <tx:annotation-driven />

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
    	p:entity-manager-factory-ref="entityManagerFactory" />


    <bean id="transactionManagerRemote" class="org.springframework.orm.jpa.JpaTransactionManager"
    	p:entity-manager-factory-ref="entityManagerFactoryRemote" />

</beans>

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence 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"
    version="1.0">

    <persistence-unit name="pu1" transaction-type="RESOURCE_LOCAL">
    	<properties>
    		<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy" />
    		<property name="hibernate.dialect" value="${local.hibernate.dialect}" />
    		<property name="hibernate.hbm2ddl.auto" value="${local.hibernate.hbm2ddl.auto}" />    						
    	</properties>
    </persistence-unit>

    <persistence-unit name="pu2" transaction-type="RESOURCE_LOCAL">
    	<properties>
    		<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy" />
    		<property name="hibernate.dialect" value="${remote.hibernate.dialect}" />
    		<property name="hibernate.hbm2ddl.auto" value="${remote.hibernate.hbm2ddl.auto}" />
    	</properties>
    </persistence-unit>

</persistence>

Maintenant, il construit deux entityManagerFactory, mais les deux sont pour Microsoft SQL Server [principal] INFO org.mise en veille prolongée.ejb.Ejb3Configuration - Traitement PersistenceUnitInfo [ nom: pu1 ...] [principal] INFO org.mise en veille prolongée.cfg.SettingsFactory - SGBD: SQL Server de Microsoft

[principal] INFO org.mise en veille prolongée.ejb.Ejb3Configuration - Traitement PersistenceUnitInfo [ nom: pu2 ...] [principal] INFO org.mise en veille prolongée.cfg.SettingsFactory - SGBD: SQL Server de Microsoft (mais doit MySQL)

- Je suggérer que l'utilisation seule source de données, dataSourceRemote (pas de substitution) n'est pas travaillé. C'est mon dernier problème

15voto

ChssPly76 Points 53452

Vous devez utiliser la propriété persistenceXmlLocations (notez le pluriel) plutôt que persistenceXmlLocation . Il s'agit d'un tableau de chaînes, il sera donc automatiquement converti à partir de la liste:

 <bean id="persistenceUnitManager"
      class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
  <property name="persistenceXmlLocations"><list>
    <value>classpath*:config/persistence.local.xml</value>
    <value>classpath*:config/persistence.remote.xml</value>
  </list></property>
  ...
 

Mise à jour (basée sur la modification)

Votre entityManagerFactory ne spécifie pas la propriété persistenceUnitName . Vous devez le faire explicitement car vous définissez plus d'une unité de persistance et entityManagerFactory doit savoir laquelle utiliser.

8voto

Cristian Ebbens Points 296

Justin, le numéro 3 peut être fait de manière plus standard comme ceci:

  1. Dans votre contexte printanier:

     <context:annotation-config />
     
  2. Dans vos DAO gérés par Spring (notez la propriété unitName):

     @PersistenceContext(unitName = "pu1"`) protected EntityManager entityManager;
     

De cette façon, un EntityManager correctement initié correspondant à l'unité de persistance nommée "pu1" serait injecté dans les DAO correspondants.

6voto

Justin Cater Points 51

Si vous suivez ce tutoriel, http://www.javacodegeeks.com/2010/05/jboss-42x-spring-3-jpa-hibernate.html vous pouvez apporter les modifications suivantes à l'accès à deux bases de données différentes:

  1. persistence.xml définir un deuxième pesristence-unité pour votre deuxième base de données.
  2. spring.xml définir un deuxième entityManagerFactory bean sous un nom différent, permet de dire "entityManagerFactoryDB2" et le configurer pour utiliser la persistance de l'unité pour la deuxième base de données.
  3. pour chaque DAO vous souhaitez accéder à la deuxième base de données sont les suivants :

    @Autowired
    private EntityManagerFactory entityManagerFactoryDB2;
    
    @PostConstruct
    public void init() {
        super.setEntityManagerFactory(entityManagerFactoryDB2);
    }
    

C'est tout!

Au printemps les classes de service, utiliser le DAOs comme d'habitude!

0voto

Giulio Roggero Points 646

Consultez cette page wiki http://code.google.com/p/gwt-spring-jpa-lucene/wiki/PersistenceUnitSetup qui détaille comment configurer Spring avec persistenceXmlLocations et les annotations dans DAO

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X