将OneToOne / ManyToOne与JPA和多个数据源一起使用时出错

时间:2014-01-15 09:08:57

标签: spring hibernate jpa datasource multiple-instances

我设法使用多个数据源配置JPA,但是在启动我的服务器时出现以下错误(Websphere liberty):

org.hibernate.AnnotationException: @OneToOne or @ManyToOne onxxx.AccountBalance.currency references an unknown entity: xxx.Currency
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(T oOneFkSecondPass.java:109)
at org.hibernate.cfg.Configuration.processEndOfQueue( Configuration.java:1521)
at org.hibernate.cfg.Configuration.processFkSecondPas sInOrder(Configuration.java:1446)
at org.hibernate.cfg.Configuration.secondPassCompile( Configuration.java:1351)
at org.hibernate.cfg.Configuration.buildSessionFactor y(Configuration.java:1733)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>( EntityManagerFactoryImpl.java:94)
at 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>

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

Web.xml中

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

的persistence.xml

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

1 个答案:

答案 0 :(得分:0)

我知道为时已晚,但是我遇到了同样的问题。 我正在使用Oracle数据库,具有两个模式(用户)的同一数据库 我的解决方案是让第一用户访问第二用户架构中的所有表。 之后,在“ JPA实体”批注上,为每个实体调整模式。

通过这种方式,hibernate使用schema生成SQL查询:

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

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