Spring 将OneTONE/ManyTONE与JPA和多个数据源一起使用时出错

Spring 将OneTONE/ManyTONE与JPA和多个数据源一起使用时出错,spring,hibernate,jpa,datasource,multiple-instances,Spring,Hibernate,Jpa,Datasource,Multiple Instances,我已经成功地用多个数据源配置了JPA,但在启动我的服务器(Websphere liberty)时出现以下错误: org.hibernate.AnnotationException:@OneToOne或@ManyToOne onxxx.AccountBalance.currency引用未知实体:xxx.currency 位于org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(T oOneFkSecondPass.java:109) 在org.hiber

我已经成功地用多个数据源配置了JPA,但在启动我的服务器(Websphere liberty)时出现以下错误:

org.hibernate.AnnotationException:@OneToOne或@ManyToOne onxxx.AccountBalance.currency引用未知实体:xxx.currency
位于org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(T oOneFkSecondPass.java:109)
在org.hibernate.cfg.Configuration.processEndOfQueue(Configuration.java:1521)上
在org.hibernate.cfg.Configuration.processFkSecondPas sInOrder(Configuration.java:1446)上
位于org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1351)
位于org.hibernate.cfg.Configuration.buildSessionFactor y(Configuration.java:1733)
位于org.hibernate.ejb.EntityManagerFactoryImpl。(EntityManagerFactoryImpl.java:94)
位于org.hibernate.ejb.Ejb3Configuration.buildEntityMan agerFactory(Ejb3Configuration.java:905)
如果所有DAO都在同一个数据库中声明,那么应用程序将正确部署,但是如果我将它们中的任何一个移动到另一个数据库,应用程序将失败。是否可以使用多个数据源的JPA包(OneToOne、ManyToOne、ManyToMany)

配置的相关部分:

上下文:

<jee:jndi-lookup id="dataSource" jndi-name="jdbc/xxxwas"
cache="true" resource-ref="true" lookup-on-startup="false"
proxy-interface="javax.sql.DataSource" />

<bean id="h2dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url"
value="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;TRACE_LEVEL_SYSTEM_OUT=3" />
<property name="username" value="test" />
<property name="password" value="test" />
</bean>

<tx:jta-transaction-manager />

<bean id="persistenceUnitManager"
class="org.springframework.orm.jpa.persistenceunit .DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>classpath:META-INF/persistence.xml</value>
</list>
</property>
<property name="dataSources">
<map>
<entry key="h2" value-ref="h2dataSource" />
<entry key="mysql" value-ref="dataSource" />
</map>
</property>
<!-- if no datasource is specified, use this one -->
<property name="defaultDataSource" ref="dataSource" />
</bean>

<bean id="integrationEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerE ntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceUnitName" value="integrationEntityManagerFactoryPU" />
<property name="jtaDataSource" ref="h2dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.Hibernat eJpaVendorAdapter">
<!-- <property name="showSql" value="true" /> -->
<property name="database" value="H2" />
<!-- <property name="generateDdl" value="true" /> -->
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerE ntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceUnitName" value="databaseEntityManagerFactoryPU" />
<property name="jtaDataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.Hibernat eJpaVendorAdapter">
<!-- <property name="showSql" value="true" /> -->
<property name="database" value="MYSQL" />
</bean>
</property>
</bean>

<jpa:repositories base-package="xxx.impl.repository.integration"
query-lookup-strategy="create-if-not-found"
entity-manager-factory-ref="integrationEntityManagerFactory">
</jpa:repositories>

<!-- Configures Spring Data JPA and sets the base package of my DAOs. -->
<jpa:repositories base-package="xxx.impl.repository"
query-lookup-strategy="create-if-not-found"
entity-manager-factory-ref="entityManagerFactory">
</jpa:repositories>

类路径:META-INF/persistence.xml
更新
Server.xml

  <dataSource id="xxxwas" jndiName="jdbc/xxxwas" supplementalJDBCTrace="true" type="javax.sql.XADataSource">
        <jdbcDriver javax.sql.ConnectionPoolDataSource="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource" javax.sql.DataSource="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" javax.sql.XADataSource="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" libraryRef="MySQLLib"/>
        <properties databaseName="xxx" password="xxx" portNumber="3306" serverName="localhost" user="root"/>
    </dataSource>
<resource-ref>
    <res-ref-name>jdbc/xxxwas</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
    <persistence-unit name="databaseEntityManagerFactoryPU" transaction-type="JTA">
        <class>xxx.impl.bo.AccountBalance</class>
       <!-- WORKS IF DEFINED HERE -->
        <!-- <class>xxx.impl.bo.Currency</class> -->
         <properties>
             <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>
            <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" />
            <!-- <property name="hibernate.current_session_context_class"value="thread" /> -->
            <!--<prop key="hibernate.transaction.flush_before_completion">false</prop>-->
            <!--<prop key="hibernate.transaction.auto_close_session">true</prop>-->
            <!--<prop key="hibernate.current_session_context_class">thread</prop>-->
            <!--<prop key="javax.persistence.transactionType">JTA</prop>-->
            <!--<prop key="hibernate.connection.release_mode">auto</prop>-->

            <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
            <property name="hibernate.cache.use_query_cache" value="true"/>
            <property name="hibernate.cache.use_second_level_cache" value="true"/>
            <property name="net.sf.ehcache.configurationResourceName" value="ehcache_database.xml"/>
            <property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider"/>

            <!-- <property name="hibernate.archive.autodetection" value="class, hbm"/> -->
             <!-- <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>  -->
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy"/>
            <property name="hibernate.use_sql_comments" value="true"/>
            <property name="hibernate.generate_statistics" value="true"/>
        </properties>
    </persistence-unit>
     <persistence-unit name="integrationEntityManagerFactoryPU" transaction-type="JTA">
           <!-- DOES NOT WORK IF DEFINED HERE -->
        <class>xxx.impl.bo.Currency</class>
        <properties>
             <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>
            <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" />
             <property name="hibernate.hbm2ddl.auto" value="create" />
        </properties>
    </persistence-unit>
</persistence>

Web.xml

  <dataSource id="xxxwas" jndiName="jdbc/xxxwas" supplementalJDBCTrace="true" type="javax.sql.XADataSource">
        <jdbcDriver javax.sql.ConnectionPoolDataSource="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource" javax.sql.DataSource="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" javax.sql.XADataSource="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" libraryRef="MySQLLib"/>
        <properties databaseName="xxx" password="xxx" portNumber="3306" serverName="localhost" user="root"/>
    </dataSource>
<resource-ref>
    <res-ref-name>jdbc/xxxwas</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
    <persistence-unit name="databaseEntityManagerFactoryPU" transaction-type="JTA">
        <class>xxx.impl.bo.AccountBalance</class>
       <!-- WORKS IF DEFINED HERE -->
        <!-- <class>xxx.impl.bo.Currency</class> -->
         <properties>
             <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>
            <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" />
            <!-- <property name="hibernate.current_session_context_class"value="thread" /> -->
            <!--<prop key="hibernate.transaction.flush_before_completion">false</prop>-->
            <!--<prop key="hibernate.transaction.auto_close_session">true</prop>-->
            <!--<prop key="hibernate.current_session_context_class">thread</prop>-->
            <!--<prop key="javax.persistence.transactionType">JTA</prop>-->
            <!--<prop key="hibernate.connection.release_mode">auto</prop>-->

            <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
            <property name="hibernate.cache.use_query_cache" value="true"/>
            <property name="hibernate.cache.use_second_level_cache" value="true"/>
            <property name="net.sf.ehcache.configurationResourceName" value="ehcache_database.xml"/>
            <property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider"/>

            <!-- <property name="hibernate.archive.autodetection" value="class, hbm"/> -->
             <!-- <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>  -->
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy"/>
            <property name="hibernate.use_sql_comments" value="true"/>
            <property name="hibernate.generate_statistics" value="true"/>
        </properties>
    </persistence-unit>
     <persistence-unit name="integrationEntityManagerFactoryPU" transaction-type="JTA">
           <!-- DOES NOT WORK IF DEFINED HERE -->
        <class>xxx.impl.bo.Currency</class>
        <properties>
             <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>
            <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" />
             <property name="hibernate.hbm2ddl.auto" value="create" />
        </properties>
    </persistence-unit>
</persistence>

jdbc/xxxwas
javax.sql.DataSource
容器
可分享
Persistence.xml

  <dataSource id="xxxwas" jndiName="jdbc/xxxwas" supplementalJDBCTrace="true" type="javax.sql.XADataSource">
        <jdbcDriver javax.sql.ConnectionPoolDataSource="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource" javax.sql.DataSource="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" javax.sql.XADataSource="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" libraryRef="MySQLLib"/>
        <properties databaseName="xxx" password="xxx" portNumber="3306" serverName="localhost" user="root"/>
    </dataSource>
<resource-ref>
    <res-ref-name>jdbc/xxxwas</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
    <persistence-unit name="databaseEntityManagerFactoryPU" transaction-type="JTA">
        <class>xxx.impl.bo.AccountBalance</class>
       <!-- WORKS IF DEFINED HERE -->
        <!-- <class>xxx.impl.bo.Currency</class> -->
         <properties>
             <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>
            <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" />
            <!-- <property name="hibernate.current_session_context_class"value="thread" /> -->
            <!--<prop key="hibernate.transaction.flush_before_completion">false</prop>-->
            <!--<prop key="hibernate.transaction.auto_close_session">true</prop>-->
            <!--<prop key="hibernate.current_session_context_class">thread</prop>-->
            <!--<prop key="javax.persistence.transactionType">JTA</prop>-->
            <!--<prop key="hibernate.connection.release_mode">auto</prop>-->

            <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
            <property name="hibernate.cache.use_query_cache" value="true"/>
            <property name="hibernate.cache.use_second_level_cache" value="true"/>
            <property name="net.sf.ehcache.configurationResourceName" value="ehcache_database.xml"/>
            <property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider"/>

            <!-- <property name="hibernate.archive.autodetection" value="class, hbm"/> -->
             <!-- <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>  -->
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy"/>
            <property name="hibernate.use_sql_comments" value="true"/>
            <property name="hibernate.generate_statistics" value="true"/>
        </properties>
    </persistence-unit>
     <persistence-unit name="integrationEntityManagerFactoryPU" transaction-type="JTA">
           <!-- DOES NOT WORK IF DEFINED HERE -->
        <class>xxx.impl.bo.Currency</class>
        <properties>
             <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>
            <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" />
             <property name="hibernate.hbm2ddl.auto" value="create" />
        </properties>
    </persistence-unit>
</persistence>

xxx.impl.bo.AccountBalance
xxx.impl.bo.Currency

我知道为时已晚,但我也遇到了同样的问题。 我正在处理Oracle数据库,这是一个具有两个模式(用户)的数据库 我的解决方案是让第一个用户访问第二个用户模式中的所有表。 之后,在JPA实体注释上,精确每个实体的模式

这样,hibernate就可以使用模式生成SQL查询:

select field1, field2 from USER1.Table1 INNER JOIN USER2.TABLE2 ON .....

这是因为user1可以通过授权访问user2表,但这两个模式必须在同一数据库中,否则必须创建dblink和同义词。

否。不能在数据库x中有实体x,数据库y中有实体y,然后期望实体x和y一起工作。它们单独工作,但实体x和实体y之间不能有关系。谢谢你的回答,M.戴纳姆。你知道这不可能的原因吗?JPA关系(一对一、一对多、多对多)是通过实体经理还是通过其他机制解决的?了解此功能不可用的原因是很有意思的,如果它真的可用,我相信它在许多多租户场景中都会很有用。相关实体通过相同的
EntityManager
解决,因此不能存在于不同的数据库中。所有内容都必须在同一
EntityManager
中访问。如果要将其拆分到不同的数据库,则必须手动管理。我一直在寻找不同的解决方案,使用
AbtractRoutingDataSource
创建动态路由数据源,并在单个entityManagerFactory中使用它。不幸的是,这种方法(如果可行的话)将被限制在共享同一方言的多个数据库中,对吗?除了删除关系(一对一、一对多、多对多)之外,还有其他方法可以考虑吗?如前所述,手动执行。你不能,imho也不应该,试图在JPA规范下把不属于规范的东西固定在适当的位置。如果这些关系在两个不同的数据库中,你也可能需要重新考虑它们。此外,您的域不必与数据库对象相同!(我建议读一读埃里克·埃文斯的小说。