Java Spring数据JPA CDI与多个持久化单元的集成

Java Spring数据JPA CDI与多个持久化单元的集成,java,spring-data,spring-data-jpa,eclipselink,cdi,Java,Spring Data,Spring Data Jpa,Eclipselink,Cdi,我是Spring新手,尝试在WebLogic12c上集成Spring数据、EclipseLink和EJB 我想使用CDI将Spring数据存储库注入到无状态EJB中,因此我遵循Spring数据CDI集成指令,并成功地使用了单个持久化单元 由于应用程序需要两个持久性单元来连接两个不同的数据库,因此我在persistence.xml中配置了两个具有不同名称的持久性单元 问题来了:我如何创建两个Spring数据存储库,以便RepositoryA使用持久化单元A而RepositoryB使用持久化单元B

我是Spring新手,尝试在WebLogic12c上集成Spring数据、EclipseLink和EJB

我想使用CDI将Spring数据存储库注入到无状态EJB中,因此我遵循Spring数据CDI集成指令,并成功地使用了单个持久化单元

由于应用程序需要两个持久性单元来连接两个不同的数据库,因此我在persistence.xml中配置了两个具有不同名称的持久性单元

问题来了:我如何创建两个Spring数据存储库,以便
RepositoryA
使用持久化单元A而
RepositoryB
使用持久化单元B

persistence.xml

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
             http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
             version="2.1">
    <persistence-unit name="PRIMARY_PU" transaction-type="JTA">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>jdbc/EMP_DS</jta-data-source>
        <class>com.smec.eis.example.springbooteval.model.Employee</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
    </persistence-unit>
    <persistence-unit name="SECONDARY_PU" transaction-type="JTA">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>jdbc/HR_DS</jta-data-source>
        <class>com.smec.eis.example.springbooteval.model.Job</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
    </persistence-unit>
</persistence>
TL;博士 使用限定符声明哪个存储库应该使用哪个
EntityManager

解释 Spring数据JPA存储库默认在单个
EntityManager
上实现。CDI扩展将任何限定符从存储库接口传播到其
EntityManager
选择。由于限定符实际上是空的(不计入
@Default
@Any
),因此扩展使用上面代码中的单个
EntityManager

创建和添加自己的限定符批注将为您完成以下工作:

限定词 存储库接口 您的
EntityManagerFactoryProducer
: 上面的代码假设您使用的实体类型在两个数据源中不同。如果您需要使用相同的实体类型,那么您将创建一个基本存储库接口,用
@NoRepositoryBean
和两个派生接口对其进行注释,类似于上面的代码。

TL;博士 使用限定符声明哪个存储库应该使用哪个
EntityManager

解释 Spring数据JPA存储库默认在单个
EntityManager
上实现。CDI扩展将任何限定符从存储库接口传播到其
EntityManager
选择。由于限定符实际上是空的(不计入
@Default
@Any
),因此扩展使用上面代码中的单个
EntityManager

创建和添加自己的限定符批注将为您完成以下工作:

限定词 存储库接口 您的
EntityManagerFactoryProducer

上面的代码假设您使用的实体类型在两个数据源中不同。如果您需要使用相同的实体类型,那么您将创建一个基本存储库接口,用
@NoRepositoryBean
和两个派生接口对其进行注释,类似于上面的代码。

基于mp911de的答案。EntityManagerFactoryProducer需要两个更接近的方法,否则在Weblogic上部署失败

public class EntityManagerFactoryProducer {

    @Produces
    @ApplicationScoped
    @PrimaryEM
    public EntityManagerFactory createEntityManagerFactory() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("PRIMARY_PU");
        return emf;
    }

    @Produces
    @Dependent
    @PrimaryEM
    public EntityManager createEntityManager(@PrimaryEM EntityManagerFactory entityManagerFactory) {
        EntityManager em = entityManagerFactory.createEntityManager();
        return em;
    }

    @Produces
    @ApplicationScoped
    @SecondaryEM
    public EntityManagerFactory createSecondaryEntityManagerFactory() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("SECONDARY_PU");
        return emf;
    }

    @Produces
    @Dependent
    @SecondaryEM
    public EntityManager createSecondaryEntityManager(@SecondaryEM EntityManagerFactory entityManagerFactory) {
        EntityManager em = entityManagerFactory.createEntityManager();
        return em;
    }

    public void close(@Disposes @PrimaryEM EntityManager entityManager) {
        entityManager.close();
    }


    public void close(@Disposes @PrimaryEM EntityManagerFactory entityManagerFactory) {
        entityManagerFactory.close();
    }

    public void closeSecondary(@Disposes @SecondaryEM EntityManager entityManager) {
        entityManager.close();
    }

    public void closeSecondary(@Disposes @SecondaryEM EntityManagerFactory entityManagerFactory) {
        entityManagerFactory.close();
    }

基于mp911de的答案。EntityManagerFactoryProducer需要两个更接近的方法,否则在Weblogic上部署失败

public class EntityManagerFactoryProducer {

    @Produces
    @ApplicationScoped
    @PrimaryEM
    public EntityManagerFactory createEntityManagerFactory() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("PRIMARY_PU");
        return emf;
    }

    @Produces
    @Dependent
    @PrimaryEM
    public EntityManager createEntityManager(@PrimaryEM EntityManagerFactory entityManagerFactory) {
        EntityManager em = entityManagerFactory.createEntityManager();
        return em;
    }

    @Produces
    @ApplicationScoped
    @SecondaryEM
    public EntityManagerFactory createSecondaryEntityManagerFactory() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("SECONDARY_PU");
        return emf;
    }

    @Produces
    @Dependent
    @SecondaryEM
    public EntityManager createSecondaryEntityManager(@SecondaryEM EntityManagerFactory entityManagerFactory) {
        EntityManager em = entityManagerFactory.createEntityManager();
        return em;
    }

    public void close(@Disposes @PrimaryEM EntityManager entityManager) {
        entityManager.close();
    }


    public void close(@Disposes @PrimaryEM EntityManagerFactory entityManagerFactory) {
        entityManagerFactory.close();
    }

    public void closeSecondary(@Disposes @SecondaryEM EntityManager entityManager) {
        entityManager.close();
    }

    public void closeSecondary(@Disposes @SecondaryEM EntityManagerFactory entityManagerFactory) {
        entityManagerFactory.close();
    }

为什么要在JavaEE容器中使用Spring数据?看看DeltaSpike:DeltaSpike是完全适合JavaEEI的CDI扩展。我想看看DeltaSpike。但如果我想让Spring数据同时在JEE容器和Spring容器中工作,那么使用Spring数据作为数据访问层是否是合理的理由呢?当然!但我的意见是要么使用Spring,要么使用JavaEE。使用Spring,您可以使用任何servlet容器,如Tomcat或Spring。加上Spring提供了比普通JavaEEI更方便的功能,我尝试过DeltaSpike,我喜欢它。DeltaSpike似乎通过更好地支持容器管理的事务,使JEE容器中的事情变得更容易。因为我们使用的是EJB和CMT,所以DeltaSpike可能是更好的选择。DeltaSpike是CDI扩展,其中as Spring是一个依赖项注入容器,它与EJB和CDI竞争。我决不会把这两者混为一谈。为什么要在JavaEE容器中使用Spring数据?看看DeltaSpike:DeltaSpike是完全适合JavaEEI的CDI扩展。我想看看DeltaSpike。但如果我想让Spring数据同时在JEE容器和Spring容器中工作,那么使用Spring数据作为数据访问层是否是合理的理由呢?当然!但我的意见是要么使用Spring,要么使用JavaEE。使用Spring,您可以使用任何servlet容器,如Tomcat或Spring。加上Spring提供了比普通JavaEEI更方便的功能,我尝试过DeltaSpike,我喜欢它。DeltaSpike似乎通过更好地支持容器管理的事务,使JEE容器中的事情变得更容易。因为我们使用的是EJB和CMT,所以DeltaSpike可能是更好的选择。DeltaSpike是CDI扩展,其中as Spring是一个依赖项注入容器,它与EJB和CDI竞争。我决不会把这两个混为一谈。非常感谢你的解释!我明天会尝试解决方案。非常感谢您的解释!我明天会试试这个解决办法。
@MyFirstDatabase
public interface SomeRepository extends CrudRepository<MyEntity, Long> { … }

@MySecondDatabase
public interface SomeOtherRepository extends CrudRepository<OtherEntity, Long> { … }
public class MyComponent {

    @Inject
    @MyFirstDatabase 
    SomeRepository someRepo;

    @Inject    
    @MySecondDatabase 
    SomeOtherRepository someOtherRepo;
}
public class EntityManagerFactoryProducer {

    @Produces
    @ApplicationScoped
    @MyFirstDatabase
    public EntityManagerFactory createEntityManagerFactory() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("PRIMARY_PU");
        return emf;
    }

    @Produces
    @ApplicationScoped
    @MySecondDatabase
    public EntityManagerFactory createEntityManagerFactory() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("SECONDARY_PU");
        return emf;
    }

    public void close(@Disposes EntityManagerFactory entityManagerFactory) {
        entityManagerFactory.close();
    }

    @Produces
    @Dependent
    @MyFirstDatabase
    public EntityManager createEntityManager(@MyFirstDatabase EntityManagerFactory entityManagerFactory) {
        return entityManagerFactory.createEntityManager();
    }

    @Produces
    @Dependent
    @MySecondDatabase
    public EntityManager createEntityManager(@MySecondDatabase EntityManagerFactory entityManagerFactory) {
        return entityManagerFactory.createEntityManager();
    }

    public void close(@Disposes EntityManager entityManager) {
        entityManager.close();
    }
}
public class EntityManagerFactoryProducer {

    @Produces
    @ApplicationScoped
    @PrimaryEM
    public EntityManagerFactory createEntityManagerFactory() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("PRIMARY_PU");
        return emf;
    }

    @Produces
    @Dependent
    @PrimaryEM
    public EntityManager createEntityManager(@PrimaryEM EntityManagerFactory entityManagerFactory) {
        EntityManager em = entityManagerFactory.createEntityManager();
        return em;
    }

    @Produces
    @ApplicationScoped
    @SecondaryEM
    public EntityManagerFactory createSecondaryEntityManagerFactory() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("SECONDARY_PU");
        return emf;
    }

    @Produces
    @Dependent
    @SecondaryEM
    public EntityManager createSecondaryEntityManager(@SecondaryEM EntityManagerFactory entityManagerFactory) {
        EntityManager em = entityManagerFactory.createEntityManager();
        return em;
    }

    public void close(@Disposes @PrimaryEM EntityManager entityManager) {
        entityManager.close();
    }


    public void close(@Disposes @PrimaryEM EntityManagerFactory entityManagerFactory) {
        entityManagerFactory.close();
    }

    public void closeSecondary(@Disposes @SecondaryEM EntityManager entityManager) {
        entityManager.close();
    }

    public void closeSecondary(@Disposes @SecondaryEM EntityManagerFactory entityManagerFactory) {
        entityManagerFactory.close();
    }