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

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

问题描述

我正在尝试配置 Spring+Hibernate+JPA 以使用两个数据库(MySQL 和 MSSQL).

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

我的数据源-context.xml:

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>

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

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 导致以下异常:

PersistenceUnitManager cause following exception:

无法解析对 bean 的引用'persistenceUnitManager' 设置时豆属性'persistenceUnitManager';嵌套例外是org.springframework.beans.factory.BeanCreationException:使用名称创建 bean 时出错'persistenceUnitManager' 定义在类路径资源[配置/数据源-context.xml]:bean 初始化失败;嵌套例外是org.springframework.beans.TypeMismatchException:无法转换属性值输入 [java.util.ArrayList] 到需要输入 [java.lang.String] 作为属性'persistenceXmlLocation';嵌套例外是java.lang.IllegalArgumentException:无法转换类型的值[java.util.ArrayList] 到所需类型[java.lang.String] 属性'persistenceXmlLocation':不匹配找到编辑器或转换策略

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

如果只留下一个没有列表的persistence.xml,每个都可以正常工作但我需要 2 个单位...

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

我还尝试在 Spring+Hibernate 上下文中找到使用两个数据库的替代解决方案,所以我很感激任何解决方案.

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

更改为persistenceXmlLocations后的新错误:

在 {classpath:config/persistence.local.xml, classpath:config/persistence.remote.xml} 中没有定义单一的默认持久化单元

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

更新:

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

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

更新:

我更改了配置文件:数据源-context.xml

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>

持久性.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>

现在它构建了两个entityManagerFactory,但都是针对Microsoft SQL Server

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)

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

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

推荐答案

您需要使用 persistenceXmlLocations 属性(注意复数)而不是 persistenceXmlLocation.这是一个字符串数组,所以它会从列表中自动转换:

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

更新(基于编辑)

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

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天全站免登陆