spring boot 2 多數據源詳細配置

場景 : 配置兩個數據源,主數據源是mysql , 次數據源是impala [1] , 兩個個數據源都使用spring-data-jpa 。

一、環境

  1. 基礎組件版本
maven: 3.5.3
spring-boot: 2.0.1
spring-data: 2.0.5
jdk: 8
  1. 先把項目結構分成三部分,方便理解, 我們要做的就是用不同的持久層使用不同的數據源
src
├─持久層
│  ├─domain
│  └─repository
│  
├─服務層
│  └─service
│
└─控制層
    └─controller
  1. 如果使用多數據源,結構主要結構看起來如下,服務層控制層不變
src
├─mysql持久層
│  ├─domain
│  └─repository
│  
├─impala持久層
│  ├─domain
│  └─repository
│  
├─服務層
│  └─service
│
└─控制層
    └─controller

二、配置多數據源

  1. 增加yaml配置
  • mysql配置
spring:
    datasource:
        driverClassName: com.mysql.jdbc.Driver
        url: jdbc:mysql://100.100.100:3306/db_mysql?useUnicode=true&characterEncoding=utf-8&useSSL=false&zeroDateTimeBehavior=convertToNull&useNewIO=true&autoReconnectForPools=true
        username: user
        password: pwd
  • impala配置 (impala:是自定義的,這個結構可以全部自定義)
impala:
    datasource:
        url: jdbc:hive2://finance-06:21050/db_impala;auth=noSasl;
        username: user
        password: pwd
  1. 分隔持久層,就是建兩個不同的包,持久層分開放。
  • defaultDataSource存放的是mysql的實體類和DAO , impalaDataSource放impala的DAO和實體類
    image.png
  1. 配置datasource
  • 新建DefaultDBConfig類,配置mysql的dataSourceentityManagerFactorytransactionManager
package com.demo.conf;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;


@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactory", 
        transactionManagerRef = "transactionManager", 
        // 【1】這里寫的是DAO層的路徑 ,如果你的DAO放在 com.xx.DAO下面,則這里寫成 com.xx.DAO
        basePackages = {"com.demo.defaultDataSource.repository"}  
)
public class DefaultDBConfig {

    @Autowired
    private JpaProperties jpaProperties;

    @Primary
    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "spring.datasource") // 【2】datasource配置的前綴,對應上面 【mysql的yaml配置】
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Primary
    @Bean(name = "entityManagerFactory") 
    public LocalContainerEntityManagerFactoryBean
    entityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("dataSource") DataSource dataSource
    ) {
        return builder
                .dataSource(dataSource)
                .packages("com.demo.defaultDataSource.domain") // 【3】這里是實體類的包路徑
                .persistenceUnit("defaultUnit") // 這里寫成唯一的就可以了,具體我也不太明白 ,希望有人告知
                  // 【4】
                .properties(jpaProperties.getHibernateProperties(new HibernateSettings())) 
                .build();
    }

    @Primary
    @Bean(name = "transactionManager") 
    public PlatformTransactionManager transactionManager(
            @Qualifier("entityManagerFactory") EntityManagerFactory
                    entityManagerFactory
    ) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

注意上面標的【1】【2】【3】【4】這四個地方,
【1】:設置DAO所在的包路徑
【2】:datasource的yaml配置前綴,默認數據原最好保持為spring.datasource
【3】:這里是實體類的包路徑,里面是 @Entity 注解的實體,對應數據庫的表。
【4】:因為這里自己生成數據源,沒有spring-boot的自動配置了,所以要通過 JpaProperties 獲取默認配置并放進去,這里算是小重點
注意:這里配置的為默認數據源,記得加上@Primary

  • image.png

    注意 : 圖片中相同顏色和數字標注的地方要保持統一

圖片是以前的老圖,沒有加@Primary,在實際代碼中記得加上


  • 新建ImpalaDBConfig類,配置impala的dataSource、entityManagerFactory和transactionManager
package com.bbd.finance.xuanwu.web.conf;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
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.core.env.Environment;
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;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "impalaEntityManagerFactory" ,
        transactionManagerRef = "impalaTransactionManager" ,
        basePackages = {"com.demo.impalaDataSource.dao"} // 【1】
)
public class ImpalaDBConfig {
    @Autowired
    private JpaProperties jpaProperties ;
    
   
    @Bean(name = "impalaDataSource")
    @ConfigurationProperties(prefix = "impala.datasource") // 【2】
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }
    

    @Bean(name = "impalaEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean
    entityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("impalaDataSource") DataSource dataSource , Environment environment
    ) {
        
        LocalContainerEntityManagerFactoryBean impala = builder
                .dataSource(dataSource)
                .packages("com.demo.impalaDataSource.domain") // 【3】
                .persistenceUnit("impala")
                // 【4】
                .properties(jpaProperties.getHibernateProperties(new HibernateSettings())) 
                .build();
        return impala ;
    }
    

    @Bean(name = "impalaTransactionManager")
    public PlatformTransactionManager transactionManager(
            @Qualifier("impalaEntityManagerFactory") EntityManagerFactory
                    entityManagerFactory
    ) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}
  1. 要注意的地方和上面 mysql的一樣。【2】標注的impala.datasource是自定義的前綴,可以自己定義,這里寫成對應的就可以獲取到配置 .
  2. 配置完上面的就ok了,在spring-boot中,controller和service層都不用做什么修改(我的項目中全部用的 JPA)

可能會出現的問題
  1. 實體類中命名解析無效,比如實體類中的 userName , 沒有自動映射成數據中的 user_name , 因為自己構建的數據源沒有加載到 命名策略 , 此時請檢查上面代碼標注的第【4】點 , 可以在【4】標注的地方斷點,看有沒有加載 org.hibernate.boot.model.naming.SpringPhysicalNamingStrategy
    image.png
1. 如果要實現mysql和oracle的多數據源,配置方法類似,把impala的配置改成oracle的就ok
2. 多數據源中默認數據源要加上@Primary , (entityManagerFactory , transactionManager ,dataSource )

2018-11-30 更新 : 圖片部分就不做更新了哈

    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "spring.datasource") // 【2】datasource配置的前綴,對應上面 【mysql的yaml配置】
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

請把▲上面部分的代碼換成▼下面的,這樣可以解決報錯 jdbcUrl is required with driverClassName。原因是spring-boot 1.x 數據源使用的是spring.datasource.url , 而spring-boot 2.x 使用的是spring.datasource.jdbcUrl , 代碼修改成下面的樣子,可以自動兼容 。官方文檔- 79.2 Configure Two DataSources

    @Bean(name = "dataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource(@Autowired @Qualifier("defaultDataSourceProperties") DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder().build();
    }

    @Bean(name="defaultDataSourceProperties")
    @ConfigurationProperties("spring.datasource")
    public DataSourceProperties dataSourceProperties() {
        return new DataSourceProperties();
    }

參考:


  1. Impala是Cloudera公司主導開發的新型查詢系統,它提供SQL語義,能查詢存儲在Hadoop的HDFS和HBase中的PB級大數據 ?

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容