在一个 Spring Boot 应用程序中使用两个 EntityManagerFactory

Art*_*rov 5 java jpa spring-boot

我正在尝试EntityManagerFactory为一个 Spring Boot 应用程序配置两个。其中每一个EntityManagerFactory都应该使用不同的数据库。如果将其中之一用作默认值(例如,当没有提供明确的信息来说明应使用哪一个时),那就太好了。

这是我的代码:

pkg/Application.java

package pkg;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        new SpringApplicationBuilder(Application.class).run(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

pkg/PrimaryDbConfig.java

package pkg;

import org.h2.jdbcx.JdbcDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

@Configuration
public class PrimaryDbConfig {
    public static final String DB = "primary";

    @Bean
    @Primary
    public DataSource primaryDataSource() {
        JdbcDataSource ds = new JdbcDataSource();
        ds.setURL("jdbc:h2:file:~\\db\\test;AUTO_SERVER=TRUE");
        ds.setUser("sa");
        ds.setPassword("sa");
        return ds;
    }

    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactoryBean() {

        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        factoryBean.setPersistenceUnitName(DB);
        factoryBean.setDataSource(primaryDataSource());
        factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        factoryBean.setPackagesToScan("pkg.entities");
        return factoryBean;
    }

    @Bean
    @Primary
    public PlatformTransactionManager primaryTransactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(primaryEntityManagerFactoryBean().getObject());
        return transactionManager;
    }
}
Run Code Online (Sandbox Code Playgroud)

pkg/SecondaryDbConfig.java

package pkg;

import org.h2.jdbcx.JdbcDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

@Configuration
public class SecondaryDbConfig {
    public static final String DB = "secondary";

    @Bean
    public DataSource secondaryDataSource() {
        JdbcDataSource ds = new JdbcDataSource();
        ds.setURL("jdbc:h2:file:~\\db\\test2;AUTO_SERVER=TRUE");
        ds.setUser("sa");
        ds.setPassword("sa");
        return ds;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactoryBean() {

        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        factoryBean.setPersistenceUnitName(DB);
        factoryBean.setDataSource(secondaryDataSource());
        factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        factoryBean.setPackagesToScan("pkg.entities");
        return factoryBean;
    }

    @Bean
    public PlatformTransactionManager secondaryTransactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(secondaryEntityManagerFactoryBean().getObject());
        return transactionManager;
    }
}
Run Code Online (Sandbox Code Playgroud)

pkg/repositories/PrimaryRepository.java

package pkg.repositories;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import pkg.entities.SomeEntity;

import javax.persistence.EntityManager;

@Repository
@Transactional
public class PrimaryRepository {
    private final EntityManager entityManager;

    public PrimaryRepository(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public SomeEntity find(Integer id) {
        return entityManager.find(SomeEntity.class, id);
    }
}
Run Code Online (Sandbox Code Playgroud)

pkg/repositories/SecondaryRepository.java

package pkg.repositories;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import pkg.entities.SomeEntity;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Repository
@Transactional("secondaryTransactionManager")
public class SecondaryRepository {
    @PersistenceContext(unitName = "secondary")
    private final EntityManager entityManager;

    public SecondaryRepository(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public SomeEntity find(Integer id) {
        return entityManager.find(SomeEntity.class, id);
    }
}
Run Code Online (Sandbox Code Playgroud)

构建.gradle

plugins {
    id 'org.springframework.boot' version '1.5.7.RELEASE'
}

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile "com.h2database:h2:1.4.193"
    compile "org.hibernate:hibernate-core:5.2.10.Final"
    compile ("org.springframework.boot:spring-boot-starter-data-jpa:1.5.2.RELEASE") {
        exclude module: 'tomcat-jdbc'
    }
}
Run Code Online (Sandbox Code Playgroud)

运行这个应用程序我收到下一个错误:

Description:

Parameter 0 of constructor in pkg.repositories.PrimaryRepository required a single bean, but 2 were found:
    - org.springframework.orm.jpa.SharedEntityManagerCreator#0: defined by method 'createSharedEntityManager' in null
    - org.springframework.orm.jpa.SharedEntityManagerCreator#1: defined by method 'createSharedEntityManager' in null
Run Code Online (Sandbox Code Playgroud)