当前位置: 首页 > 知识库问答 >
问题:

Spring Data JPA:用于多个数据库/实体管理器配置的存储库

邢皓
2023-03-14

我有两个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:创建名为“a repositoryImpl”的bean时出错:注入持久性依赖项失败;嵌套异常为org.springframework.beans.factory.NoSuchBeanDefinitionException:未定义类型为[javax.persistence.EntityManagerFactory]的唯一bean:应为单个bean,但找到2个

这当然是正确的,这里有2个EM bean,但是由于我将EM#1(也就是'Entity ManagerFactory')限制为仅打包'com.foo.repos.ora',所以我仍然不确定如何引用确切的EM bean。

共有1个答案

龙德润
2023-03-14

引擎盖下没有魔法。

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

对您的自定义接口实现没有任何帮助。我发现的最好的方法是将您的自定义实现视为常规bean。所以我在spring配置中定义了一个“共享的EntitManager”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数据存储库而没有自定义实现,那么可以使用“entity-manager-factory-ref”属性来区分数据库。

2a)另外,如果您使用任何自定义实现,请将适当的EntityManager直接注入到实现类中。发送是在您的spring xml配置的控制下完成的。由于某些原因,我无法使用带有@限定符的@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'没有提供太多支持,所以我删除了它。

 类似资料:
  • 将现有存储库数据库迁移到其他数据库可能包括迁移到同一服务器中的其他数据库,或迁移到不同操作系统上的数据库(例如,从 Windows 到 macOS)。 如果你想迁移你的存储库数据库,请按照下列步骤操作: 通过运行命令,或使用通知区域或菜单栏中的图标来停止 Navicat Monitor 服务。 在你的数据库管理工具中,将当前的存储库数据库(所有表的结构和数据)复制到新的存储库数据库。 启动 Nav

  • 我有几个实体,并使用Spring Data JPA存储库与规范查询我的数据库。因此,我创建了一个泛型类< code>SpecBuilder来基于查询描述(< code>MyQueryDescriptor)构建我的查询。 我的存储库: 和 现在有三件事我不太确定:< br> 1) 使用泛型SpecBuilder是一个干净的设计吗? 2) 有没有办法避免为每个实体编写这些存储库接口?假设一个通用存储库

  • 我目前正在尝试使用spring数据存储库删除我的一些实体。delete调用工作时没有任何异常/错误消息,但之后不会删除实体。 这些是我的实体: 而且 存储库非常简单: delete调用类似于 有什么想法为什么这个变化没有反映在数据库中吗? 编辑1: 我找到了变通办法,但我还是不明白真正的问题是什么。如果我像这样删除帖子(有几个例外,因为违反了约束,但帖子仍然会被删除),它就“起作用”了: 编辑2:

  • 问题内容: 如果我的实体具有已计算字段,应在保存到数据库(db 或)之前进行更新,如何在Hibernate或Spring Data Repository之前挂接方法调用 问题答案: 我认为最好的选择是使用和注释,为实体侦听器创建配置,然后您将可以访问要保存的每个实例,每次尝试使用以下方法持久化或更新内容时都会调用此方法hibernate或spring数据存储库 您只需要在实体bean上方添加注释

  • 我正试图让我的头绕过DDD,但我卡住了。这就是我如何设置我的项目: 然后,我继续实现UserRepository,这里我遇到了另一个问题:UserRepository接口需要域用户模型,当我试图在DAL中实现接口时,我需要使用域用户模型来实现它,这导致DAO是为域模型而不是DAL模型创建的,这没有任何意义。唯一能修正的就是在域层中引用DAL,这是错误的。 有人能解释一下我在DDD中遗漏了什么吗?

  • 我的应用程序有250多个表,每个表都有ID和name列。我正在尝试用Hibernate5+将我们的应用程序从Hibernate3迁移到Spring-JPA4.3。 在当前的hibernate层中,我有(选项1): 因此,如何在一个JPA存储库中执行以下操作: