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描述"}
  • 就此,咱們雙數據源的配置和驗證工做就完成了。
相關文章
相關標籤/搜索