Spring Data JPA:多个数据库/ Entitymanger配置的存储库

时间:2013-05-14 18:17:37

标签: entitymanager spring-data-jpa multiple-databases

我有两个Entitymanager bean配置。每个指向具有不同模式的单独数据库(一个是Oracle,另一个是内存中的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:有两个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" />  ....

此处的所有内容都在“package com.foo.repos.ora”中 按照how to make a custom repository的模式,我得到两个接口'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,但由于我限制EM#1又称'entityManagerFactory'只打包'com.foo.repos.ora',我仍然不确定如何引用确切的EM bean。

1 个答案:

答案 0 :(得分:13)

引擎盖下没有魔法。

<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'属性区分不同的实体管理器工厂,但仅限于直接的Spring Data Repositories(即仅用于接口)。但是,它并不关心您的任何实现。

总结一下

1)如果您只依赖于没有自定义实现的标准Spring Data存储库,请使用“entity-manager-factory-ref”属性来区分数据库。

2a)此外,如果您使用任何自定义实现,请将相应的EntityManager直接注入实现类。 Wirering是在spring xml配置的控制下完成的。出于某种原因,我无法使用带有@Qualifier的@Autowire注释来引用正确的EntityManager。 编辑我刚刚了解了@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'引用了标准JPA persistence.xml中的持久性

然而,2b)与'QueryDslRepositorySupport'不匹配,因为它需要一个EntityManager实例。但我发现'QueryDslRepositorySupport'无论如何都没有提供太多支持,所以我删除了它。