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());
    }
}
  • 配置中需要注意以下几点:
  • 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')
  • repository、entity的所在位置,要和实际保存的位置一致。
  •  
  • 主数据源的一些配置需要添加@Primary作为spring默认的首选项,其他数据源无需添加该注解。
  •  
  • 通过查看相关源码我们看到Spring Boot中JpaProperties的代码一直在调整,这里我们将properties相关代码单独提取出作为一个单独的方法getVendorProperties展示版本间的区别。其中:
  • 查询
  • 完成了所有的配置,接下来我们就可以开始写个简单代码验证我们配置了
@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
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值