Spring Boot Jpa多数据源配置

前言

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

实现

  • 建表
  • 首先是建表语句,咱们要创建两个数据库,并各库内新建一张表
  • 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描述"}
  • 就此,咱们双数据源的配置和验证工做就完成了。
相关文章
相关标签/搜索