Spring Boot Jpa 多数据源

前言

随着业务量发展,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源,如:user一个库,business一个库。那么接下来我们就要考虑怎么去在spring boot中实现多个数据源的配置。

源码下载

实现

  • 建表

    首先是建表语句,我们要建立两个数据库,并各库内新建一张表

    user表​

    mysql> use `user`;
    mysql> select * from `user`;
    +----+-------+----------+
    | id | name  | password |
    +----+-------+----------+
    |  1 | 用户A | ******   |
    +----+-------+----------+
    1 row in set
    

    business表

    mysql> use `business`;
    mysql> select * from `business`;
    +----+-------+-------------+
    | id | name  | description |
    +----+-------+-------------+
    |  1 | 业务A | 业务A描述   |
    +----+-------+-------------+
    1 row in set
    

    接下来我们通过代码实现对两个库内的多张表进行查询。

  • 配置

    首先,创建一个Spring配置类,定义两个DataSource用来读取application.yml中的不同配置。本文中,我们user做为主数据源,主数据源配置为spring.datasource.user开头的配置,business数据源配置为spring.datasource.business开头的配置。

    @Configuration
    public class DataSourceConfig {
        @Primary
        @Bean(name = "userDataSource")
        @Qualifier("userDataSource")
        @ConfigurationProperties(prefix = "spring.datasource.user")
        public DataSource userDataSource() {
            return DataSourceBuilder.create().build();
        }
    
        @Bean(name = "businessDataSource")
        @Qualifier("businessDataSource")
        @ConfigurationProperties(prefix = "spring.datasource.business")
        public DataSource businessDataSource() {
            return DataSourceBuilder.create().build();
        }
    }
    

    对应的配置文件application.yml如下:

    spring:
      datasource:
        user:
          driver-class-name: com.mysql.jdbc.Driver
          jdbc-url: jdbc:mysql://localhost:3306/user
          username: root
          password: 123456
        business:
          driver-class-name: com.mysql.jdbc.Driver
          jdbc-url: jdbc:mysql://localhost:3306/business
          username: root
          password: 123456
    

    接下来我们对各数据源进行jpa的配置

    主数据源User

    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
            entityManagerFactoryRef = "entityManagerFactoryUser",
            transactionManagerRef = "transactionManagerUser",
            //设置Repository所在位置
            basePackages = {"com.ppc.spring.example.jpamultidatasource.repository.user"})
    public class UserConfig {
    
        @Autowired
        @Qualifier("userDataSource")
        private DataSource userDataSource;
        @Autowired
        private JpaProperties jpaProperties;
        @Autowired
        private HibernateProperties hibernateProperties;
    
        @Primary
        @Bean(name = "entityManagerUser")
        public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
            return entityManagerFactoryUser(builder).getObject().createEntityManager();
        }
    
        @Primary
        @Bean(name = "entityManagerFactoryUser")
        public LocalContainerEntityManagerFactoryBean entityManagerFactoryUser(EntityManagerFactoryBuilder builder) {
            return builder
                    .dataSource(userDataSource)
                    //设置entity所在位置
                    .packages("com.ppc.spring.example.jpamultidatasource.entity.user")
                    .persistenceUnit("userPersistenceUnit")
                    .properties(getVendorProperties())
                    .build();
        }
    
        private Map<String, Object> getVendorProperties() {
            return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
        }
    
        @Primary
        @Bean(name = "transactionManagerUser")
        public PlatformTransactionManager transactionManagerUser(EntityManagerFactoryBuilder builder) {
            return new JpaTransactionManager(entityManagerFactoryUser(builder).getObject());
        }
    
    }
    

    其他数据源business

    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
            entityManagerFactoryRef = "entityManagerFactoryBusiness",
            transactionManagerRef = "transactionManagerBusiness",
            //设置repository所在位置
            basePackages = {"com.ppc.spring.example.jpamultidatasource.repository.business"})
    public class BusinessConfig {
    
        @Autowired
        @Qualifier("businessDataSource")
        private DataSource businessDataSource;
        @Autowired
        private JpaProperties jpaProperties;
        @Autowired
        private HibernateProperties hibernateProperties;
    
        @Bean(name = "entityManagerBusiness")
        public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
            return entityManagerFactoryBusiness(builder).getObject().createEntityManager();
        }
    
        @Bean(name = "entityManagerFactoryBusiness")
        public LocalContainerEntityManagerFactoryBean entityManagerFactoryBusiness(EntityManagerFactoryBuilder builder) {
            return builder
                    .dataSource(businessDataSource)
                    .properties(getVendorProperties())
                    //设置实体类所在位置
                    .packages("com.ppc.spring.example.jpamultidatasource.entity.business")
                    .persistenceUnit("businessPersistenceUnit")
                    .build();
        }
    
        private Map<String, Object> getVendorProperties() {
            return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
        }
    
        @Bean(name = "transactionManagerBusiness")
        PlatformTransactionManager transactionManagerBusiness(EntityManagerFactoryBuilder builder) {
            return new JpaTransactionManager(entityManagerFactoryBusiness(builder).getObject());
        }
    }
    

    配置中需要注意以下几点:

    • repository、entity的所在位置,要和实际保存的位置一致。

    • 主数据源的一些配置需要添加@Primary作为spring默认的首选项,其他数据源无需添加该注解。

    • 通过查看相关源码我们看到Spring Boot中JpaProperties的代码一直在调整,这里我们将properties相关代码单独提取出作为一个单独的方法getVendorProperties展示版本间的区别。其中:

      • Spring Boot 1.5.x

        private Map<String, String> getVendorProperties() {
          return jpaProperties.getHibernateProperties(userDataSource);
        }
        
      • Spring Boot 2.0.x

        private Map<String, Object> getVendorProperties() {
          return jpaProperties.getHibernateProperties(new HibernateSettings());
        }
        
      • Spring Boot 2.1.0参见上文代码,引进了HibernateProperties。同时,在Spring Boot 2.1.0中默认的mysql-connector-java版本为8.0.13,连接低版本mysql配置上比较繁琐,建议在配置文件中手动指定相应版本,如本文中指定5.1.46这个版本。

        runtimeOnly('mysql:mysql-connector-java:5.1.46')
        
  • 查询

    完成了所有的配置,接下来我们就可以开始写个简单代码验证我们配置了

    @RestController
    @SpringBootApplication
    public class JpaMultiDatasourceApplication {
        @Autowired
        UserRepository userRepository;
        @Autowired
        BusinessRepository businessRepository;
    
        public static void main(String[] args) {
            SpringApplication.run(JpaMultiDatasourceApplication.class, args);
        }
    
        @GetMapping("/user/{id}")
        public User getUser(@PathVariable Long id) {
            return userRepository.findById(id).orElse(null);
        }
    
        @GetMapping("/business/{id}")
        public Business getBusiness(@PathVariable Long id) {
            return businessRepository.findById(id).orElse(null);
        }
    }
    

    我们对外暴露了两个接口,分别访问user表business表确认可以正常获取数据。查询结果如下:

    请求:http://localhost:8080/user/1
    结果:{"id":1,"name":"用户A","password":"******"}
    
    请求:http://localhost:8080/business/1
    结果:{"id":1,"name":"业务A","description":"业务A描述"}
    

    就此,我们双数据源的配置和验证工作就完成了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值