2012-09-28 59 views
1

有一個Spring no-web應用Apache James(Java郵件服務器)。Spring,OpenJPA,多個持久化單元

它使用openjpa。它有一個持久性單元和數據源以及實體管理器的工廠定義。

我必須操縱它來爲外部數據庫使用一個更多的持久性單元。

我增加了一個單元到的persistence.xml

<persistence-unit name="James" transaction-type="RESOURCE_LOCAL"> 
     <!-- Mailbox stuff--> 
     <class>org.apache.james.mailbox.jpa.mail.model.JPAMailbox</class> 
     <class>org.apache.james.mailbox.jpa.mail.model.JPAUserFlag</class> 
     <class>org.apache.james.mailbox.jpa.mail.model.openjpa.AbstractJPAMessage</class> 
     <class>org.apache.james.mailbox.jpa.mail.model.openjpa.JPAMessage</class> 
     <class>org.apache.james.mailbox.jpa.mail.model.openjpa.JPAMessage</class> 
     <class>org.apache.james.mailbox.jpa.mail.model.JPAProperty</class> 
     <class>org.apache.james.mailbox.jpa.user.model.JPASubscription</class> 
     <class>org.apache.james.domainlist.jpa.model.JPADomain</class> 
     <class>org.apache.james.user.jpa.model.JPAUser</class> 
     <class>org.apache.james.rrt.jpa.model.JPARecipientRewrite</class> 

     <properties> 
      <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/> 
      <property name="openjpa.jdbc.MappingDefaults" value="ForeignKeyDeleteAction=cascade, JoinForeignKeyDeleteAction=cascade"/> 
      <property name="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)"/> 
      <property name="openjpa.jdbc.QuerySQLCache" value="false"/> 
     </properties> 

    </persistence-unit> 


    <persistence-unit name="myPU" transaction-type="JTA"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <class>package.EmailAddress</class> 
    <class>package.Message</class> 
     <properties> 
      <property name="javax.persistence.jdbc.user" value="root" /> 
      <property name="javax.persistence.jdbc.password" value="root" /> 
      <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/kepsDb" /> 
      <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> 
      <property name="hibernate.hbm2ddl.auto" value="none" /> 
      <property name="hibernate.show_sql" value="false" /> 
      <property name="hibernate.dialect" value=" org.hibernate.dialect.MySQLDialect" /> 

      <property name="hibernate.max_fetch_depth" value="0" /> 
      <property name="hibernate.cache.use_second_level_cache" value="true" /> 
      <property name="hibernate.cache.use_query_cache" value="false" /> 
      <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory" /> 

      <property name="hibernate.ejb.naming_strategy" value="web.app.persistence.util.AppImprovedNamingStrategy"/> 

     </properties> 

    </persistence-unit> 

我不彈簧server.xml中定義第二個實體管理器工廠,相反,我生成我自己的EntityManager的工廠內聯:

EntityManagerFactory emf=Persistence.createEntityManagerFactory("myPU"); 
     EntityManager entityManager=emf.createEntityManager(); 
entityManager.getTransaction().begin(); 

但我得到異常:

Caused by: org.springframework.beans.FatalBeanException: Unable to execute lifecycle method on beanmailetcontext; nested exception is <openjpa-2.1.0-r422266:1071316 nonfatal user error> org.apache.openjpa.persistence.InvalidStateException: This operation cannot be performed while a Transaction is active. 
+1

您使用「myPU」單位創建EMF和它使用的OpenJPA你的問題,但似乎使用Hibernate ... – DataNucleus

回答

0

myPU被配置爲使用JTA事務。在使用JTA時調用entityManager.getTransaction()將導致異常,因爲此方法應與RESOURCE_LOCAL事務類型一起使用。

我不知道,如果您發佈的異常信息是由於這一點,但你可以嘗試的myPU<persistence-unit>更改爲:

<persistence-unit name="myPU" transaction-type="RESOURCE_LOCAL"> 

請注意,如果你要訪問的這兩個數據庫同樣的交易,你必須使用JTA。

+0

感謝您的回覆,改變類型,同樣的錯誤 – merveotesi

+0

我沒有你的例外是什麼想法。但是即使你解決了這個異常,如果你使用'entityManager.getTransaction()。begin()'來開始一個轉換,你仍然必須把事務類型改爲「RESOURCE_LOCAL」。順便說一下,'DataNucleus'是對的,你同時使用OpenJPA和休眠嗎?爲什麼你說你使用OpenJPA,但'myPU'包含hibernate的配置? –

0

下面的代碼說明了如何配置多個持久化單元與JPA +春:

首先,我們定義了兩個持久性單元在persistence.xml,讓分別打電話給他們1單元和UNIT2:

<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="Unit1" transaction-type="RESOURCE_LOCAL"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <properties> 
     <property name="hibernate.archive.autodetection" value="class" /> 
     <property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver" /> 
     <property name="hibernate.connection.url" value="jdbc:oracle:thin:@my.company.com:1522:D1" /> 
     <property name="hibernate.connection.password" value="my_user" /> 
     <property name="hibernate.connection.username" value="my_password" /> 
    </properties> 
    </persistence-unit> 

    <persistence-unit name="Unit2" transaction-type="RESOURCE_LOCAL"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <properties> 
     <property name="hibernate.archive.autodetection" value="class" /> 
     <property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver" /> 
     <property name="hibernate.connection.url" value="jdbc:oracle:thin:@my.company.com:1522:D2" /> 
     <property name="hibernate.connection.password" value="my_user" /> 
     <property name="hibernate.connection.username" value="my_password" /> 
    </properties> 
    </persistence-unit> 
</persistence> 

由於我們處理獨立的Java應用程序,因此我們在Spring應用程序上下文中定義了數據源,但對於Web應用程序,通常會在persistence.xml文件本身中定義對這些數據源的JNDI引用。

從應用程序的context.xml中的這些persisetence單位被稱爲像這樣:

<?xml version="1.0" encoding="UTF-8"?> 

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:p="http://www.springframework.org/schema/p" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-2.5.xsd 
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd"> 

    <context:annotation-config /> 
    <tx:annotation-driven /> 

    <bean id="dataSource1" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 
    <property name="driverClass" value="oracle.jdbc.driver.OracleDriver" /> 
    <property name="jdbcUrl" value="jdbc:oracle:thin:@my.company.com:1521:D1" /> 
    <property name="user" value="my_user" /> 
    <property name="password" value="my_password" /> 
    </bean> 

    <bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource"> 
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> 
    <property name="url" value="jdbc:oracle:thin:@my.company.com:1521:D2" /> 
    <property name="username" value="my_user" /> 
    <property name="password" value="my_password" /> 
    </bean> 

    <!-- DEFINITION OF BOTH ENTITY MANAGER FACTORIES --> 

    <bean id="entityManagerFactory" 
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="dataSource1" /> 
    <property name="persistenceUnitName" value="Unit1" /> 
    <property name="persistenceUnitManager" ref="persistenceUnitManager" /> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
     <property name="databasePlatform" 
        value="org.hibernate.dialect.Oracle10gDialect" /> 
     </bean> 
    </property> 
    </bean> 

    <bean id="entityManagerFactory2" 
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="dataSource2" /> 
    <property name="persistenceUnitName" value="Unit2" /> 
    <property name="persistenceUnitManager" ref="persistenceUnitManager" /> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
     <property name="databasePlatform" 
        value="org.hibernate.dialect.Oracle10gDialect" /> 
     </bean> 
    </property> 
    </bean> 

    <!-- PERSISTENCE UNIT MANAGER and TRANSACTION MANAGERS --> 

    <bean id="persistenceUnitManager" 
     class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager"> 
    <property name="dataSources"> 
     <map> 
     <entry key="d1" value-ref="dataSource1" /> 
     <entry key="d2" value-ref="dataSource2" /> 
     </map> 
    </property> 
    </bean> 

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

    <bean id="abwTransactionManager" 
     class="org.springframework.orm.jpa.JpaTransactionManager" 
     p:entity-manager-factory-ref="entityManagerFactory2" /> 
</beans> 

現在所有剩下要做的就是表示@PersistenceContext在你的DAO像這樣:

@Required 
    @PersistenceContext(unitName = "Unit1") 
    public void setEntityManager(final EntityManager entityManager) { 
     this.entityManager = entityManager; 
    } 
+0

如果我定義了多個entityManagerFactory,我沒有得到唯一的entityManagerFactory錯誤。 – merveotesi

+0

您是否指定要注入哪個持久性單元?_ @ PersistenceContext(unitName =「Unit1」)_ – Anshu

+0

在PersistenceContext中指定unitName不會更改任何內容,spring仍然不知道使用哪個工廠來生成entitymanager –

相關問題