Spring boot 2.3 + Spring Data JPA配置多数据源

项目近期有个需求,要同时连接两个数据库,并且不同环境,数据库种类还不同,我们有两个数据库,其中一个测试环境是oracle,生产环境又是postgre,另一个一直是postgre,调查了网上能搜到很多资料,基本上写法都一致,比如https://blog.csdn.net/itguangit/article/details/78747969,但用在sb 2.3上会发现两个问题,一个是EntityManagerFactoryBuilder在启动时无法自动注入,虽然理论上sb会自动创建其实例,另一个是2.3中jpaProperties已经没有getHibernateProperties这个方法了,花了两天时间,发现一个外国人写的帖子方法是适用于2.3这个版本的,发布时间是去年,比较新,原帖见https://springframework.guru/how-to-configure-multiple-data-sources-in-a-spring-boot-application/ ,但也不是没有问题,需要再改造一下才能完全适应项目开发,下面是改造后的大致的代码

  • application.yml
    spring:
      datasource:
        first:
          url: jdbc:postgresql://localhost:5432/sample
          driverClassName: org.postgresql.Driver
          username: postgres
          password: 111
        second:
          url: jdbc:oracle:thin:@//192.168.1.100:1521/orclpdb
          driverClassName: oracle.jdbc.OracleDriver
          username: webdba
          password: 111
      jpa:
        hibernate:
          ddl-auto: none
        show-sql: true

     

  • 数据源1的配置文件,postgre db
    需要注意的是,这里的每个方法都要使用Primary的注解,只有一个配置文件需要如此 ,这个是sb规定,否则启动时会报错,貌似任意一个都可以指定成这样的,不要被字面意思迷惑
    package com.xxx.config;
    
    import com.zaxxer.hikari.HikariDataSource;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
    import org.springframework.orm.jpa.JpaTransactionManager;
    import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.sql.DataSource;
    
    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(basePackages = "com.xxx.repo.first", //当前数据源对应的repository的包名,每个数据源应该有独立的包
            entityManagerFactoryRef = "firstEntityManagerFactory",
            transactionManagerRef= "firstTransactionManager"
    )
    public class FirstJpaConfig {
        @Bean
        @Primary
        @ConfigurationProperties("spring.datasource.first")
        public DataSourceProperties firstDataSourceProperties() {
            return new DataSourceProperties();
        }
    
        @Bean
        @Primary
        @ConfigurationProperties("spring.datasource.first.configuration")
        public DataSource firstDataSource() {
            return firstDataSourceProperties().initializeDataSourceBuilder()
                    .type(HikariDataSource.class).build();
        }
    
        @Primary
        @Bean(name = "firstEntityManagerFactory")
        public LocalContainerEntityManagerFactoryBean firstEntityManagerFactory(EntityManagerFactoryBuilder builder) {
            return builder
                    .dataSource(firstDataSource())
                    .packages("com.xxx.entity.first") //当前数据源对应的实体的包名,每个数据源应该有独立的包
                    .build();
        }
    
        @Primary
        @Bean
        public PlatformTransactionManager firstTransactionManager(
                final @Qualifier("firstEntityManagerFactory") LocalContainerEntityManagerFactoryBean firstEntityManagerFactory) {
            return new JpaTransactionManager(firstEntityManagerFactory.getObject());
        }
    
        @Primary
        @Bean(name = "firstEntityManager")
    	//这个不是必须,但如果你想在service中注入一个EntityManager用于执行动态jql,这个就是必要的,否则,sb会不知道选择哪个EntityManager实例使用,每个数据源对应一个实例
        public EntityManager entityManager(@Qualifier("firstEntityManagerFactory") EntityManagerFactory factory) {
            return factory.createEntityManager();
        }
    }
    
    

     

  • 数据源2的配置文件,oracle db,和第一个高度类似,不解释了
    package com.xxx.config;
    
    import com.zaxxer.hikari.HikariDataSource;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
    import org.springframework.orm.jpa.JpaTransactionManager;
    import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.sql.DataSource;
    
    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(basePackages = "com.xxx.repo.second",
            entityManagerFactoryRef = "secondEntityManagerFactory",
            transactionManagerRef= "secondTransactionManager"
    )
    public class SecondJpaConfig {
        @Bean
        @ConfigurationProperties("spring.datasource.second")
        public DataSourceProperties secondDataSourceProperties() {
            return new DataSourceProperties();
        }
    
        @Bean
        @ConfigurationProperties("spring.datasource.second.configuration")
        public DataSource secondDataSource() {
            return secondDataSourceProperties().initializeDataSourceBuilder()
                    .type(HikariDataSource.class).build();
        }
    
        @Bean(name = "secondEntityManagerFactory")
        public LocalContainerEntityManagerFactoryBean secondEntityManagerFactory(EntityManagerFactoryBuilder builder) {
            return builder
                    .dataSource(secondDataSource())
                    .packages("com.xxx.entity.second")
                    .build();
        }
    
        @Bean
        public PlatformTransactionManager secondTransactionManager(
                final @Qualifier("secondEntityManagerFactory") LocalContainerEntityManagerFactoryBean secondEntityManagerFactory) {
            return new JpaTransactionManager(secondEntityManagerFactory.getObject());
        }
    
        @Bean(name = "secondEntityManager")
        public EntityManager entityManager(@Qualifier("secondEntityManagerFactory") EntityManagerFactory factory) {
            return factory.createEntityManager();
        }
    }
    
    

     

原帖中使用的数据源实现类是dbcp,听说目前性能最好的是Hikari数据源,我就替换了一下,测试运行良好。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值