SpringBoot多数据源JPA

时间:2017-03-29 07:11:42

标签: jpa spring-boot spring-data-jpa

我有以下代码

实体

 @Entity
    public class Employee {

        @Id
        @GeneratedValue
        long id;

        @Column(name="first_name")
        String firstName;

        @Column(name="last_name")
        String lastName;

        @Column(name="salary")
        int salary;

        @ManyToOne
        @JoinColumn(name="address")
        Address address;

    ..... setter & getter

    }

回购

public interface EmpRepository extends JpaRepository<Employee, Long>{}

服务

@Service
public class EmpService {

    @Autowired
    private EmpRepository empRepo;

    @Autowired @Qualifier("primaryEntityManagerFactory") EntityManager em;

    public List<Employee> findAll(){
        return empRepo.findAll();
    }

}

控制器

@RestController
@RequestMapping(value = "/demo")
public class DemoController {

    @Autowired
    private EmpService empService;


    @RequestMapping("/abcd")
    public List<Employee> findAll(){
        return empService.findAll();
    }

}

数据源配置(主要)

@Configuration
@EnableJpaRepositories(basePackages="com.example",
entityManagerFactoryRef = "primaryEntityManagerFactory")
public class DataSourceConfiguration {

    @Bean(name="primaryDataSource")
    @Primary
    @ConfigurationProperties(prefix = "datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public JpaTransactionManager transactionManager() {
        JpaTransactionManager tm = new JpaTransactionManager();
        tm.setEntityManagerFactory(primaryEntityManagerFactory().getObject());
        return tm;
    }

    @Bean(name="primaryEntityManagerFactory")
    @Primary
    LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory() {

        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        factoryBean.setDataSource(primaryDataSource());
        factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        factoryBean.setPackagesToScan(DataSourceConfiguration.class.getPackage().getName());

        return factoryBean;
    }

}

辅助数据源配置

 @Configuration
@EnableJpaRepositories(basePackages="com.example",
entityManagerFactoryRef = "secondaryEntityManagerFactory")
public class DS2Configuration {

    @Bean(name="secondaryDataSource")
    @ConfigurationProperties(prefix = "datasource.secondary")

    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public JpaTransactionManager transactionManager() {
        JpaTransactionManager tm = new JpaTransactionManager();
        tm.setEntityManagerFactory(secondaryEntityManagerFactory().getObject());
        return tm;
    }

    @Bean(name="secondaryEntityManagerFactory")
    LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory() {

        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        factoryBean.setDataSource(secondaryDataSource());
        factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        factoryBean.setPackagesToScan(DataSourceConfiguration.class.getPackage().getName());

        return factoryBean;
    }

}

application.properties

spring.jpa.show-sql = true
spring.jpa.properties.hibernate.show_sql=true
spring.jooq.sql-dialect=MYSQL
logging.level.org.springframework.data=DEBUG

# Primary DataSource configuration
datasource.primary.url=jdbc:mysql://127.0.0.1:3306/jpa
datasource.primary.username=root
datasource.primary.password=root

# Secondary DataSource configuration
datasource.secondary.url=jdbc:mysql://127.0.0.1:3306/jpa2
datasource.secondary.username=root
datasource.secondary.password=root

# Disable Spring DataSource auto-initialization
spring.datasource.initialize=false

server.port=8081

当我实际从EmpService运行函数findAll()时,即使我将secondary entitymanagefactory指定为

,它总是使用主数据源
@Autowired
    @Qualifier("secondaryEntityManagerFactory")
    EntityManager em;

如何解决这个问题? 附: - 请不要为此分享博客链接。

3 个答案:

答案 0 :(得分:2)

您需要将Repository类放在两个不同的目录中。并改变

@EnableJpaRepositories(basePackages="com.example".....)  

在您配置数据源的两个位置都行。那应该解决你的问题 代码运行但始终使用主数据源

此致

答案 1 :(得分:0)

这是因为有多个类型javax.persistence.EntityManagerFactory的bean来帮助spring boot决定选择哪个bean

使用 bean 注释

注释@primary

@primary official documentation

答案 2 :(得分:0)

您需要在此方法上添加@Primary:primaryEntityManagerFactory()

顺便说一句,我认为primaryTransactionManager()和等效的辅助方法是多余的,工厂bean方法返回相同的东西。

您还需要为每个entityManager定义一个transactionManager,例如

@Bean
@Primary
public JpaTransactionManager transactionManager() {
    JpaTransactionManager tm = new JpaTransactionManager();
    tm.setEntityManagerFactory(yourPrimaryEntityManagerInjected);
    return tm;
}