web-dev-qa-db-ja.com

Spring Data JPA:複数のデータベース/ Entitymanager構成のリポジトリー

2つのEntitymanagerBean構成があります。それぞれが異なるスキーマを持つ個別のデータベースを指しています(1つはOracle、もう1つはインメモリH2です)

各リポジトリに使用するEntitymanagerのあいまいさを解決するにはどうすればよいですか?現在、このエラーが発生しています。

 No unique bean of type [javax.persistence.EntityManagerFactory] is defined:
 expected single bean but found 2

次のようなものを使用するだけでクイックフィックスを提供できると思います

<jpa:repositories base-package="com.foo.repos.ora"
 entity-manager-factory-ref="entityManagerFactoryA">

<jpa:repositories base-package="com.foo.repos.m2"
 entity-manager-factory-ref="entityManagerFactoryB">

しかし、うまくいけば、より良い解決策があります。

編集:

私はあなたに現在のシナリオのアイデアを与えます:

Spring-Config:2つのEMがあります

<jpa:repositories base-package="com.foo.repos.ora" entity-manager-factory-ref="entityManagerFactory"/>
<jpa:repositories base-package="com.foo.repos.m2" entity-manager-factory-ref="entityManagerFactory2"/>
<context:component-scan base-package="com.foo" />  ....

これ以降はすべて「packagecom.foo.repos.ora」にあります。 カスタムリポジトリの作成方法 のパターンに従って、2つのインターフェイス「ARepository」、「ARepositoryCustom」、およびその実装 'ARepositoryImpl'のように

@Repository
public interface ARepository extends ARepositoryCustom, JpaRepository<myEntity, BigDecimal>, QueryDslPredicateExecutor {

}

public interface ARepositoryCustom {
    FooBar lookupFooBar()
}

public class ARepositoryImpl extends QueryDslRepositorySupport implements ARepositoryCustom {
    ARepositoryImpl(Class<?> domainClass) {
        super(domainClass.class)
    }

    ARepositoryImpl() {
        this(myEntity.class)
    }

    @Override
    FooBar lookupFooBar() {
        JPQLQuery query = ....
        ....
        return found
    }
}

次のエラーメッセージが表示されます。

原因:org.springframework.beans.factory.BeanCreationException: 'aRepositoryImpl'という名前のBeanの作成中にエラーが発生しました:永続性の依存関係の挿入に失敗しました。ネストされた例外はorg.springframework.beans.factory.NoSuchBeanDefinitionExceptionです:タイプ[javax.persistence.EntityManagerFactory]の一意のBeanが定義されていません:単一のBeanが必要ですが、2

もちろん正しいですが、EM Beanは2つありますが、EM#1別名「entityManagerFactory」をパッケージ「com.foo.repos.ora」のみに制限したため、正確なEMBeanを参照する方法がまだわかりません。

11
simou

ボンネットの下には魔法はありません。

<jpa:repositories base-package="com.foo.repos.ora" entity-manager-factory-ref="entityManagerFactory"/>

カスタムインターフェイスの実装にはまったく役立ちません。私が見つけた最善の方法は、カスタム実装を通常のBeanとして扱うことです。そのため、Spring構成で「sharedEntitManager」Beanを次のように定義しました。

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
       ...
</bean>
<bean id="sharedEntityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
        <property name = "entityManagerFactory" ref="entityManagerFactory"/>
</bean>

その後、EntityManagerを実装Beanに挿入するだけです。

<bean id="aRepositoryImpl" class="comm.foo.repos.ora.ARepositoryImpl">
    <property name="entityManager" ref="sharedEntityManager"/>
</bean>

'entity-manager-factory-ref'属性は、異なるentitymanagerファクトリを区別しますが、ストレートSpringデータリポジトリのみ(つまり、インターフェイスのみ)です。ただし、どの実装にも関係ありません。

まとめると

1)カスタム実装のない標準のSpring Dataリポジトリに依存している場合は、「entity-manager-factory-ref」属性を使用してデータベースを区別します。

2a)さらに、カスタム実装を使用する場合は、適切なEntityManagerを実装クラスに直接挿入します。ワイヤーリングは、Springxml構成の制御下で行われます。何らかの理由で、@ Autowireアノテーションを@Qualifierとともに使用して、正しいEntityManagerを参照することができませんでした。 [〜#〜] edit [〜#〜]@ Resource アノテーションについて学びました

@Resource(name =  "sharedEntityManagerA")
EntityManager entityManager


<bean id="sharedEntityManagerA" name="sharedEntityManagerA" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
        <property name = "entityManagerFactory" ref="entityManagerFactory"/>
</bean>

これにより、使用するEntityMAngerの選択が簡単になります。コンテキストxmlですべてを一緒に配管する必要はありません。

2b)自分のものを接続するためのSpringのxml構成の代わりに、

@PersistenceContext(unitName = "nameOfPersistenceUnit")

正しいEntitymanagerFactoryを注入します

'nameOfPersistenceUnit'は、標準のJPApersistence.xmlにある永続性を指します。

ただし、2b)は、EntityManagerインスタンスを想定しているため、「QueryDslRepositorySupport」とはうまくいきません。しかし、「QueryDslRepositorySupport」はとにかく多くのサポートを提供していないことがわかったので、それを削除しました。

13
simou