11

我有两个Entitymanagerbean 配置。每个都指向具有不同架构的单独数据库(一个是 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”中按照如何制作自定义存储库的模式,我得到了两个接口“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

这当然是正确的,有 2 个 EM bean,但是由于我将 EM #1 aka 'entityManagerFactory' 限制为仅打包 'com.foo.repos.ora',我仍然不确定如何引用确切的 EM bean。

4

1 回答 1

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 直接注入到实现类中。布线是在您的 spring xml 配置的控制下完成的。由于某种原因,我无法将@Autowire 注释与@Qualifier 一起使用来引用正确的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'无论如何都没有提供太多支持,所以我删除了它。

于 2013-05-17T13:52:26.573 回答