1

春の非WebアプリケーションApacheJames(Java Mailサーバー)があります。

openjpaを使用しています。永続性ユニットとデータソースおよびentitymanagerファクトリ定義があります。

外部DB用にもう1つの永続性ユニットを使用するように操作する必要があります。

もう1つのユニットを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>

spring-server.xmlで2番目のエンティティマネージャーファクトリを定義しません。代わりに、次のコマンドを使用して独自のエンティティマネージャーファクトリを生成します。

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

2 に答える 2

0

次のコードは、JPA + spring を使用して複数の永続ユニットを構成する方法を説明しています。

まず、persistence.xml で 2 つの永続化ユニットを定義し、それぞれ unit1 と 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 参照を定義します。

application-context.xml 内から、これらの持続性ユニットは次のように参照されます。

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

あとは、DAO で @PersistenceContext を次のように指定するだけです。

@Required
  @PersistenceContext(unitName = "Unit1")
  public void setEntityManager(final EntityManager entityManager) {
      this.entityManager = entityManager;
  }
于 2012-09-28T16:06:32.750 に答える
0

myPUJTA トランザクションを使用するように構成されています。JTA を使用しているときにentityManager.getTransaction()を呼び出すと、このメソッドはRESOURCE_LOCALトランザクション タイプで使用することになっているため、例外が発生します。

投稿された例外メッセージがこれによるものかどうかはわかりませんが、<persistence-unit>のを次のように変更してみてくださいmyPU:

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

同じトランザクションで両方のデータベースにアクセスする必要がある場合は、JTA を使用する必要があることに注意してください。

于 2012-09-28T13:59:21.303 に答える