web-dev-qa-db-ja.com

SpringとJPAを使用して複数のデータソースを設定する方法

このアプリケーションでは、SpringとJPAを使用して複数のデータソースを設定します。したがって、2つのentityManagerFactory、2つのデータソース、および2つのトランザクションマネージャーを作成しました。

web.xml

 <param-value>
    /WEB-INF/a_spring.xml
    /WEB-INF/b_spring.xml
 </param-value>

Persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.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_1_0.xsd">
    <persistence-unit name="db1" transaction-type="RESOURCE_LOCAL">
        <class>com.rh.domain.RcA</class>
    </persistence-unit>

      <persistence-unit name="db2" transaction-type="RESOURCE_LOCAL">
      <class>com.rh.domain.Rcb</class>
    </persistence-unit>
</persistence>

a_spring.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:tx="http://www.springframework.org/schema/tx" 
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

      <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>  
      <bean id = "RcMaintenanceService" class="com.rh.services.RcAbcMaintenanceServiceImpl" autowire="byName" />

    <aop:config>
            <aop:pointcut id="rOperation" expression="execution(* com.rh.services.*.*(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="rOperation"/>
        </aop:config>

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                   <tx:method name="*"/>
            </tx:attributes>
        </tx:advice>

    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiName" value="Java:comp/env/jdbc/db1" />
        </bean> 
        <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
            <property name="entityManagerFactory" ref="entityManagerFactory"/>
            <property name="dataSource" ref="dataSource"/>
        </bean>

        <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
               <property name="persistenceUnitName" value="db1" />     
            <property name="dataSource" ref="dataSource"/>
            <property name="jpaVendorAdapter">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
                    <property name="showSql" value="true"/>
                    <property name="generateDdl" value="false"/>
                    <property name="database" value="MYSQL" />
                    <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
                </bean>
            </property>
            <property name="jpaDialect">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect">
                </bean>
            </property>
        </bean>

また、別のentityManagetFactory、Transaction Manager、およびdataSourceをb_spring.xmlに宣言します。

エラー

Beanの初期化に失敗しました。ネストされた例外はorg.springframework.beans.factory.NoSuchBeanDefinitionExceptionです:タイプ[javax.persistence.EntityManagerFactory]の一意のBeanが定義されていません:単一のBeanが必要ですが、見つかりました2原因:org.springframework.beans.factory.NoSuchBeanDefinitionException:一意のBeanがありませんタイプ[javax.persistence.EntityManagerFactory]が定義されています:単一のBeanが必要ですが、org.springframework.beans.factory.BeanFactoryUtils.beanOfTypeInclusiveAncestors(BeanFactoryUtils.Java:303)のorg.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessorで2つ見つかりました。 org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.Java:428)のfindDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.Java:451)org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor $ AnnotatedMember 582)org.springframework.orm.jpa.suppoでrt.PersistenceAnnotationBeanPostProcessor $ AnnotatedMember.resolve(PersistenceAnnotationBeanPostProcessor.Java:553)at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor $ AnnotatedMember.inject(PersistenceAnnotationBeanPostProcessor.Java:489)

16
Hoo

複数のデータソース構成の場合、どれをプライマリデータソースと見なすかを定義する必要があります。 Java configまたはXMLBeanconfigの@Primaryprimary=trueアノテーションを使用して指定できます。

XMLで作成されているエンティティマネージャーは2つあるため、@Qualifierを使用して、どのBeanをどこに注入するかを指定する必要があります。あなたの場合、このようなもの。

@PersistenceContext(unitName = "db1")
public void setEntityManager(@Qualifier("entityManagerFactory") EntityManager entityMgr) {
    this.em = entityMgr;
}

xML構成の場合、次のようなことができます

<bean id="BaseService" class="x.y.z.BaseService">
    <property name="em" ref="entityManagerFactory"/>
    <property name="em1" ref="entityManagerFactory1"/>
</bean>

<bean id = "RcMaintenanceService" class="com.rh.services.RcAbcMaintenanceServiceImpl" autowire="byName" parent="BaseService"/>
7
lucid

投稿したエラーメッセージは、EntityManagerFactoryタイプのオブジェクトをタイプ別に自動配線していることを示しています。これまでに示したコードにはそのようなインジェクションが含まれていません。これは、おそらくまだ投稿していないコードに含まれていることを意味します。

エラーの完全なスタックトレースを投稿する場合は、スタックをたどって、どのBeanにEntityManagerFactoryオブジェクトへの不十分な参照が含まれているかを確認できます。これにより、参照方法を変更できます。必要な特定のBeanへの参照を許可します。

更新

あなたが提供した詳細情報(ありがとう)といくつかのグーグルに基づいて、他のユーザーが同様に、unitNameを指定するだけでは正しいEntityManagerを注入できないことに気付いたようです。オンラインのいくつかの投稿は、@ Qualifierアノテーションを使用してSpringに正しいBeanを選択させるという@lucidの推奨を裏付けていますが、残念ながら そのアノテーションは2.5で導入されました なので、アップグレードした場合にのみ利用できます。 (使用しているSpringフレームワークの時代を考えると、これはおそらく良い考えですが、それは別の会話です。)

ただし、 数人のユーザーが示しています それぞれが単一のデータソースを参照する複数の永続性ユニットではなく、複数のデータソースを参照する単一のPersistenceUnitManagerを使用して、2.0.5で代替アプローチが利用可能であることを示しています。 Springの公式ドキュメントから: https://docs.spring.io/spring/docs/2.0.x/reference/orm.html#orm-jpa-multiple-p

全体として、10年以内のバージョンのSpringにアップグレードすることを検討することをお勧めします。これにより、@ lucidの回答ごとに@Qualifierアノテーションを指定できます。ただし、何らかの理由でそれが不可能な場合は、PersistenceUnitManagerアプローチを使用すると、Spring2.0.5内で機能させることができます。

1
Tim

EntityManagerFactory Beanを含むパッケージの詳細を提供しようとしましたか?

Bean定義のプロパティとしてパッケージの詳細を提供できます-

<property name="packagesToScan" value="com.XX.XX.XX.XX" />

このブロックに追加される新しいプロパティ-

<bean id="entityManagerFactory1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
           <property name="persistenceUnitName" value="db2" />     
        <property name="dataSource" ref="dataSource1"/>
  <-- add here for both beans  -->

        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
                <property name="showSql" value="true"/>
                <property name="generateDdl" value="false"/>
                <property name="database" value="MYSQL" />
                <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
            </bean>
        </property>
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect">
            </bean>
        </property>
    </bean>

また、persistenceXmlLocationプロパティがありません-

 <property name="persistenceXmlLocation" value="***/persistence.xml" />
1
user8826113

私には似合わないことがいくつかあります。セッターの名前はプロパティ名と一致しません。これは重要だと思います。2つ目は継承に関することです。一部のアノテーションは、基本クラスではなく具象クラスでのみ機能する場合があります。基本サービスを次のように変更してみます。

public class BaseService {

@PersistenceContext(unitName = "db2")
private EntityManager em;

@PersistenceContext(unitName = "db1")
private EntityManager em1;

public EntityManager getEm() {
    return em;
}

protected EntityManager getEm2() {
    return em1;
}

public void setEm(EntityManager entityMgr) {
    this.em = entityMgr;
}

public void setEm1(EntityManager entityMgr) {
    this.em = entityMgr;
}
}

それが機能しない場合は、おそらく基本クラスを削除して、それを機能させることができる具象クラスの下にアノテーションを配置するかどうかを確認します。アノテーションだけをRcAbcMaintenanceServiceImplクラスに移動して、 BaseServiceから継承するextendステートメント

また、PersistenceContextアノテーションに別のパラメータがあることに気づきました https://docs.Oracle.com/javaee/6/api/javax/persistence/PersistenceContext.html 名前も使用して、Bean定義のIDと一致するようにしてください。

0
Koitoer