多个数据库与Spring + Hibernate + JPA [英] Multiple database with Spring+Hibernate+JPA

查看:188
本文介绍了多个数据库与Spring + Hibernate + JPA的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图为两个数据库(MySQL和MSSQL)配置Spring + Hibernate + JPA。



我的datasource-context.xml:

 <?xml version =1.0encoding =UTF-8?> 
< beans xmlns =http://www.springframework.org/schema/beans
xmlns:xsi =http://www.w3.org/2001/XMLSchema-instancexmlns :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/pxmlns :tx =http://www.springframework.org/schema/tx
xmlns:util =http://www.springframework.org/schema/util>

<! -
数据源配置
- >
< bean id =dataSourceclass =org.apache.commons.dbcp.BasicDataSource
destroy-method =closep:driverClassName =$ {local.jdbc.driver} p:url =$ {local.jdbc.url}
p:username =$ {local.jdbc.username}p:password =$ {local.jdbc.password}>
< / bean>

destroy-method =closep:driverClassName =$ {remote.jdbc .driver}
p:url =$ {remote.jdbc.url}p:username =$ {remote.jdbc.username}
p:password =$ {remote.jdbc.password }/>

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

<! - -
JPA config
- >
< tx:注解驱动的事务管理器=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 =localDataSourcevalue-ref =dataSource/>
< entry key =remoteDataSourcevalue-ref =dataSourceRemote/>
< / map>
< / property>
< property name =defaultDataSourceref =dataSource/>
< / bean>

< bean id =entityManagerFactory
class =org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean>
< property name =jpaVendorAdapter>
< bean class =org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter
p:showSql =truep:generateDdl =true>
< / bean>
< / property>
< property name =persistenceUnitManagerref =persistenceUnitManager/>
< property name =persistenceUnitNamevalue =localjpa/>
< / bean>

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

< / beans>

每个persistence.xml包含一个单元,如下所示:

 < persistence-unit name =remotetransaction-type =RESOURCE_LOCAL> 
<属性>
< property name =hibernate.ejb.naming_strategyvalue =org.hibernate.cfg.DefaultNamingStrategy/>
< property name =hibernate.dialectvalue =$ {remote.hibernate.dialect}/>
< property name =hibernate.hbm2ddl.autovalue =$ {remote.hibernate.hbm2ddl.auto}/>
< / properties>
< / persistence-unit>

PersistenceUnitManager导致以下异常:


无法在设置
bean属性
'persistenceUnitManager'时解析对bean
'persistenceUnitManager'的引用。嵌套的
异常是
org.springframework.beans.factory.BeanCreationException:
创建名为
的'persistenceUnitManager'中定义的bean的错误
类路径资源
[config / datasource-context.xml]:
初始化bean失败;嵌套的
异常是
org.springframework.beans.TypeMismatchException:
无法将
的类型[java.util.ArrayList]的属性值转换为所需的
类型[java .lang.String]属性
'persistenceXmlLocation';嵌套的
异常是
java.lang.IllegalArgumentException:
无法将
[java.util.ArrayList]类型的值转换为所需的类型
[java.lang.String ] for property
'persistenceXmlLocation':没有匹配的
编辑器或找到的转换策略


如果只留下一个持久性.xml没有列表,每一个工作正常
,但我需要2个单位... ...

我也试图找到替代解决方案的工作与两个数据库在Spring + Hibernate的上下文,所以我会很感激任何解决方案。



在更改为 persistenceXmlLocations 之后出现新错误:


在{classpath:config / persistence.local.xml,classpath:config / persistence.remote.xml}中定义的单个默认持久性单元


更新:

我添加了persistenceUnitName,它可以工作,但只有一个单元,仍然需要帮助。

更新:



我更改配置文件:
datasource-context.xml

 <?xml version =1.0encoding =UTF -8\" >?; 
< beans xmlns =http://www.springframework.org/schema/beans
xmlns:xsi =http://www.w3.org/2001/XMLSchema-instancexmlns :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/pxmlns :tx =http://www.springframework.org/schema/tx
xmlns:util =http://www.springframework.org/schema/util>

destroy-method =closep:driverClassName =$ {local.jdbc .driver}p:url =$ {local.jdbc.url}
p:username =$ {local.jdbc.username}p:password =$ {local.jdbc.password}> ;
< / bean>

destroy-method =closep: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 =defaultPersistenceUnitNamevalue =pu1/>
< / bean>

< bean id =persistenceUnitManager
class =org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager>
< property name =persistenceXmlLocationvalue =$ {persistence.xml.location}/>
< property name =defaultDataSourceref =dataSource/> <! - 问题 - >
< property name =dataSources>
< map>
< entry key =localvalue-ref =dataSource/>
< entry key =remotevalue-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 =truep:generateDdl =true>
< / bean>
< / property>
< property name =persistenceUnitManagerref =persistenceUnitManager/>
< property name =persistenceUnitNamevalue =pu1/>
< property name =dataSourceref =dataSource/>
< / bean>

< bean id =entityManagerFactoryRemote
class =org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean>
< property name =jpaVendorAdapter>
< bean class =org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter
p:showSql =truep:generateDdl =true>
< / bean>
< / property>
< property name =persistenceUnitManagerref =persistenceUnitManager/>
< property name =persistenceUnitNamevalue =pu2/>
< property name =dataSourceref =dataSourceRemote/>
< / bean>

< tx:annotation-driven />

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


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

< / beans>

persistence.xml

 <?xml version =1.0encoding =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 =pu1transaction-type =RESOURCE_LOCAL>
<属性>
< property name =hibernate.ejb.naming_strategyvalue =org.hibernate.cfg.DefaultNamingStrategy/>
< property name =hibernate.dialectvalue =$ {local.hibernate.dialect}/>
< property name =hibernate.hbm2ddl.autovalue =$ {local.hibernate.hbm2ddl.auto}/>
< / properties>
< / persistence-unit>

< persistence-unit name =pu2transaction-type =RESOURCE_LOCAL>
<属性>
< property name =hibernate.ejb.naming_strategyvalue =org.hibernate.cfg.DefaultNamingStrategy/>
< property name =hibernate.dialectvalue =$ {remote.hibernate.dialect}/>
< property name =hibernate.hbm2ddl.autovalue =$ {remote.hibernate.hbm2ddl.auto}/>
< / properties>
< / persistence-unit>

< /持久性>

现在它构建了两个entityManagerFactory,但都是用于Microsoft SQL Server的

  [main] INFO org.hibernate.ejb.Ejb3Configuration  - 处理PersistenceUnitInfo [
名称:pu1
...]
[main] INFO org.hibernate.cfg.SettingsFactory - RDBMS:Microsoft SQL Server
$ b $ [main] INFO org.hibernate.ejb.Ejb3Configuration - 处理PersistenceUnitInfo [
名称:pu2
...]
[main] INFO org.hibernate.cfg.SettingsFactory - RDBMS:Microsoft SQL Server(但必须是MySQL)

我建议,只使用dataSource,dataSourceRemote(无替代)不起作用。这是我的最后一个问题。

解决方案

您需要使用 persistenceXmlLocations 注意复数)而不是 persistenceXmlLocation 。它是一个字符串数组,因此它将从列表中自动转换:

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

更新(基于编辑)



您的 entityManagerFactory 不指定 persistenceUnitName 属性。你必须明确地这样做,因为你定义了多个持久化单元,并且 entityManagerFactory 必须知道使用哪一个。


I'm trying to configure Spring+Hibernate+JPA for work with two databases (MySQL and MSSQL).

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

Each persistence.xml contains one unit, like this:

<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 following exception:

Cannot resolve reference to bean 'persistenceUnitManager' while setting bean property 'persistenceUnitManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'persistenceUnitManager' defined in class path resource [config/datasource-context.xml]: Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type [java.util.ArrayList] to required type [java.lang.String] for property 'persistenceXmlLocation'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [java.util.ArrayList] to required type [java.lang.String] for property 'persistenceXmlLocation': no matching editors or conversion strategy found

If left only one persistence.xml without list, every works fine but I need 2 units...

I also try to find alternative solution for work with two databases in Spring+Hibernate context, so I would appreciate any solution.

New error after changing to persistenceXmlLocations:

No single default persistence unit defined in {classpath:config/persistence.local.xml, classpath:config/persistence.remote.xml}

Update:

I add persistenceUnitName, it works, but only with one unit, still need help.

Update:

I changed config files: 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>

Now it builds two entityManagerFactory, but both are for 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)

I suggest, that use only dataSource, dataSourceRemote (no substitution) is not worked. That's my last problem.

解决方案

You need to use persistenceXmlLocations property (note the plural) rather than persistenceXmlLocation. It's a string array, so it'll be auto-converted from 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>
  ...

Update (based on edit)

Your entityManagerFactory does not specify persistenceUnitName property. You have to do so explicitly because you're defining more than one persistence unit and entityManagerFactory has to know which one to use.

这篇关于多个数据库与Spring + Hibernate + JPA的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆