J'essaie de configurer Spring + Hibernate + JPA pour travailler avec 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>
La cause de PersistenceUnitManager est la suivante:
Impossible de résoudre la référence au bean 'persistenceUnitManager' lors du réglage propriété de haricot 'persistenceUnitManager'; imbriqué exception est org.springframework.beans.factory.BeanCreationException: Erreur lors de la création du bean avec le nom 'persistenceUnitManager' défini dans ressource de chemin de classe [config/datasource-context.xml]: L'initialisation du bean a échoué; imbriqué exception est org.springframework.beans.TypeMismatchException: Impossible de convertir la valeur de la propriété de tapez [Java.util.ArrayList] sur requis tapez [Java.lang.String] pour la propriété 'persistenceXmlLocation'; imbriqué exception est Java.lang.IllegalArgumentException: Impossible de convertir la valeur de type [Java.util.ArrayList] au type requis [Java.lang.String] pour la propriété 'persistenceXmlLocation': pas de correspondance éditeurs ou stratégie de conversion trouvés
S'il ne reste qu'un seul fichier persistence.xml, tout fonctionne correctement Mais il me faut 2 unités ...
J'essaie également de trouver une solution de remplacement pour le travail avec deux bases de données dans le contexte Spring + Hibernate. J'apprécierais donc toute solution.
Nouvelle erreur après le passage à persistenceXmlLocations
:
Aucune unité de persistance par défaut définie dans {classpath: config/persistence.local.xml, classpath: config/persistence.remote.xml}
Mettre à jour:
J'ajoute persistenceUnitName, cela fonctionne, mais avec une seule unité, toujours besoin d'aide.
Mettre à jour:
J'ai changé 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
[main] INFO org.hibernate.ejb.Ejb3Configuration - Processing PersistenceUnitInfo [
name: pu1
...]
[main] INFO org.hibernate.cfg.SettingsFactory - RDBMS: Microsoft SQL Server
[main] INFO org.hibernate.ejb.Ejb3Configuration - Processing PersistenceUnitInfo [
name: pu2
...]
[main] INFO org.hibernate.cfg.SettingsFactory - RDBMS: Microsoft SQL Server (but must MySQL)
Je suggère que l'utilisation uniquement de dataSource, dataSourceRemote (pas de substitution) n'est pas travaillée. C'est mon dernier problème.
Vous devez utiliser la propriété persistenceXmlLocations
(notez le pluriel) plutôt que persistenceXmlLocation
. C'est un tableau de chaînes, il sera donc automatiquement converti à partir de list:
<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é sur l'édition)
Votre entityManagerFactory
ne spécifie pas la propriété persistenceUnitName
. Vous devez le faire explicitement car vous définissez plusieurs unités de persistance et entityManagerFactory
doit savoir laquelle utiliser.
Justin, le numéro 3 peut être fait de manière plus standard comme ceci:
Dans votre contexte de printemps:
<context:annotation-config />
Dans vos DAO gérés par Spring (notez la propriété unitName):
@PersistenceContext(unitName = "pu1"`) protected EntityManager entityManager;
Ainsi, un EntityManager correctement connecté correspondant à l'unité de persistance nommée "pu1" serait injecté dans les DAO correspondantes.
Si vous suivez ce didacticiel, http://www.javacodegeeks.com/2010/05/jboss-42x-spring-3-jpa-hibernate.html vous pouvez apporter les modifications suivantes pour accéder à deux bases de données:
pour chaque DAO auquel vous souhaitez accéder, vous devez notamment:
@Autowired
private EntityManagerFactory entityManagerFactoryDB2;
@PostConstruct
public void init() {
super.setEntityManagerFactory(entityManagerFactoryDB2);
}
C'est tout!
Lors des cours de printemps, utilisez les DAO comme d'habitude!
Consultez cette page wiki http://code.google.com/p/gwt-spring-jpa-lucene/wiki/PersistenceUnitSetup qui explique comment configurer spring avec persistenceXmlLocations et les annotations dans DAO
basculer entre ceux entity entityageragerFactories ceux qui seront injectés