搞定SpringBoot多資料來源(1):多套源策略
目錄
- 1. 引言
- 2. 執行環境
- 3. 多套資料來源
- 3.1 搭建 Spring Boot 工程
- 3.1.1 初始化 Spring Boot 工程
- 3.1.2 新增 MyBatis Plus 依賴
- 3.1.3 新增包結構
- 3.2 多套資料來源
- 3.2.1 獨立資料庫連線資訊
- 3.2.2 多套資料來源配置
- 3.2.3 多套實體
- 3.2.4 多套Mapper操作
- 3.2.5 多套 mapper xml 檔案
- 3.3 多資料來源使用
- 3.1 搭建 Spring Boot 工程
- 4. 優缺點
- 4.1 優點
- 4.2 缺點
- 5. 總結
- 參考資料
- 往期文章
tags: multi-datasource java springboot
一句話概括:Spring Boot開發中連線多個數據庫進行讀寫操作,使用多套資料來源是最直接、簡單的方式。
1. 引言
在開發過程中,避免不了需要同時操作多個數據庫的情況,通常的應用場景如下 :
- 資料庫高效能場景:主從,包括一主一從,一主多從等,在主庫進行增刪改操作,在從庫進行讀操作。
- 資料庫高可用場景:主備,包括一往一備,多主多備等,在資料庫無法訪問時可以切換。
- 同構或異構資料的業務處理:需要處理的資料儲存在不同的資料庫中,包括同構(如都是 MySQL ),異構(如一個MySQL ,另外是 PG 或者 Oracle )。
使用 Spring Boot 該如何處理多個數據庫的讀寫,一般有以下幾種策略:
- 多套資料來源:即針對一個數據庫建立一套資料處理邏輯,每套資料庫都包括資料來源配置、會話工廠( sessionFactory )、連線、SQL 操作、實體。各套資料庫相互獨立。
- 動態資料來源:確定數量的多個數據源共用一個會話工廠,根據條件動態選取資料來源進行連線、SQL 操作。
- 引數化變更資料來源:根據引數新增資料來源,並進行資料來源切換,資料來源數量不確定。通常用於對多個數據庫的管理工作。
本系列文章“搞定SpringBoot多資料來源”將針對以上幾個策略進行描述,本文是第一篇:“多套資料來源”,主要以主從場景為例項,結合程式碼,對多套資料來源的實現進行描述,內容包括搭建 Spring Boot + MyBatis Plus 工程、多資料來源配置、多資料來源處理與使用邏輯。
本文所涉及到的示例程式碼:https://github.com/mianshenglee/my-example/tree/master/multi-datasource
,讀者可結合一起看。
2. 執行環境
- JAVA 執行環境:
JDK1.8
- Spring Boot:
2.2.2.RELEASE
- MyBatis Plus:
3.3.0
- 開發IDE:
IDEA
- 構建工具Maven:
3.3.9
- MySQL :
5.6.26
- Lombok:
1.18.10
3. 多套資料來源
多套資料來源,顧名思義每一個數據庫有一套獨立的操作。從下往上,資料庫、會話工廠、DAO操作,服務層都是獨立的一套,如下所示:
本示例中,以一主一從兩個資料庫,兩資料庫的分別有一個表 test_user
,表結構一致,為便於說明,兩個表中的資料是不一樣的。兩個表結構可在示例程式碼中的 sql
目錄中獲取。
3.1 搭建 Spring Boot 工程
3.1.1 初始化 Spring Boot 工程
使用 spring.io構建初始 Spring Boot 工程,選用以下幾個構件:
- Lombok: 用於簡化操作
- Spring Configuration Processor:配置檔案處理器
- Spring Web: 用於構建web服務
- MySQL Driver: 資料庫驅動
3.1.2 新增 MyBatis Plus 依賴
MyBatis Plus 是對 MyBatis 增強,簡化 DAO 操作,提高資料庫操作效率。依賴如下:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.0</version>
</dependency>
3.1.3 新增包結構
主要新增以下幾個包:
├─config ---------------------------------- // 資料來源配置
├─controller ------------------------------ // web服務
├─entity ---------------------------------- // 實體類
│ ├─master
│ └─slave
├─mapper ---------------------------------- // dao操作類
│ ├─master
│ └─slave
└─vo -------------------------------------- // 檢視返回物件
注:
- 由於示例簡單,省略service層
- 實體類及mapper均根據主從進行劃分
3.2 多套資料來源
3.2.1 獨立資料庫連線資訊
Spring Boot 的預設配置檔案是 application.properties
,由於有兩個資料庫配置,獨立配置資料庫是好的實踐,因此新增配置檔案 jbdc.properties
,新增以下自定義的主從資料庫配置:
# master
spring.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.master.jdbc-url=jdbc:mysql://localhost:3306/mytest?useSSL=false&serverTimezone=GMT%2B8&characterEncoding=UTF-8
spring.datasource.master.username=root
spring.datasource.master.password=111111
# slave
spring.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.slave.jdbc-url=jdbc:mysql://localhost:3306/my_test1?useSSL=false&serverTimezone=GMT%2B8&characterEncoding=UTF-8
spring.datasource.slave.username=root
spring.datasource.slave.password=111111
3.2.2 多套資料來源配置
有了資料來源連線資訊,需要把資料來源注入到 Spring 中。由於每個資料庫使用獨立的一套資料庫連線,資料庫連線使用的 SqlSession
進行會話連線,SqlSession
是由SqlSessionFactory
生成。因此,需要分別配置SqlSessionFactory
。以下操作均在 config
目錄 下:
(1)新增 DataSourceConfig
配置檔案,注入主從資料來源
@Configuration
@PropertySource("classpath:config/jdbc.properties")
public class DatasourceConfig {
@Bean("master")
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource masterDataSource(){
return DataSourceBuilder.create().build();
}
@Bean("slave")
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DataSource slaveDataSource(){
return DataSourceBuilder.create().build();
}
}
- 註解
PropertySource
指定配置資訊檔案- 註解
ConfigurationProperties
指定主從配置字首- 分別指定主從資料來源的 bean 名稱為
master
,slave
(2)新增 MasterMybatisConfig
配置檔案,注入 Master 的SqlSessionFactory
@Configuration
@MapperScan(basePackages = "me.mason.demo.basicmultidatasource.mapper.master", sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterMybatisConfig {
/**
* 注意,此處需要使用MybatisSqlSessionFactoryBean,不是SqlSessionFactoryBean,
* 否則,使用mybatis-plus的內建函式時就會報invalid bound statement (not found)異常
*/
@Bean("masterSqlSessionFactory")
public SqlSessionFactory masterSqlSessionFactory(@Qualifier("master") DataSource dataSource) throws Exception {
// 設定資料來源
MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
mybatisSqlSessionFactoryBean.setDataSource(dataSource);
//mapper的xml檔案位置
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
String locationPattern = "classpath*:/mapper/master/*.xml";
mybatisSqlSessionFactoryBean.setMapperLocations(resolver.getResources(locationPattern));
//對應資料庫的entity位置
String typeAliasesPackage = "me.mason.demo.basicmultidatasource.entity.master";
mybatisSqlSessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage);
return mybatisSqlSessionFactoryBean.getObject();
}
}
- 註解
MapperScan
指定那些包下的mapper
使用本資料來源,並指定使用哪個SqlSessionFactory
,注意,此處的sqlSessionFactoryRef
即本配置中的注入的SqlSessionFactory
。- 設定指定的資料來源,此處是名為
master
的資料來源,使用Qualifier
指定。- MyBatis Plus 對應的 Mapper 若有自定義的 mapper.xml, 則使用
setMapperLocations
指定。- 若需要對實體進行別名處理,則使用
setTypeAliasesPackage
指定。
(3)新增 SlaveMybatisConfig
配置檔案,注入Slave 的 SqlSessionFactory
與(2)一致,把 master 改為 slave即可。
3.2.3 多套實體
在 MyBatis 配置中,實體設定 typeAliases
可以簡化 xml 的配置,前面提到,使用 typeAliasesPackage
設定實體路徑,在 entity
包下分別設定 master
和 slave
包,存放兩個庫對應的表實體,使用 Lombok 簡化實體操作。如下:
@Data
@TableName("test_user")
public class MasterTestUser implements Serializable {
private static final long serialVersionUID = 1L;
/** id */
private Long id;
/** 姓名 */
private String name;
...
}
3.2.4 多套Mapper操作
在 mapper
包下,分別新增 master
和 slave
包,存放兩個庫對應的 Mapper ,由於 MyBatis Plus 本身已包含基本的 CRUD 操作,所以很多時候可以不用 xml 檔案配置。若需要自定義操作,需要結合 xml檔案,與此同時需要指定對應的 xml 檔案所在目錄。如下:
@Repository
public interface MasterTestUserMapper extends BaseMapper<MasterTestUser> {
/**
* 自定義查詢
* @param wrapper 條件構造器
*/
List<MasterTestUser> selectAll(@Param(Constants.WRAPPER)Wrapper<MasterTestUser> wrapper);
}
slave對應的Mapper與此類似
3.2.5 多套 mapper xml 檔案
MyBatis Plus 的預設mapper xml 檔案路徑為 classpath*:/mapper/**/*.xml
,即 resources/mapper
下,同樣設定 master
及 slave
目錄,分別存放對應的mapper xml 檔案。以下是 master 的自定義操作:
<mapper namespace="me.mason.demo.basicmultidatasource.mapper.master.MasterTestUserMapper">
<select id="selectAll" resultType="masterTestUser">
select * from test_user
<if test="ew!=null">
${ew.customSqlSegment}
</if>
</select>
</mapper>
3.3 多資料來源使用
經過上面的多套資料來源配置,可知道,若需要操作哪個資料庫,直接使用對應的 mapper 進行 CRUD 操作即可。如下為 Controller 中分別查詢兩個庫,獲取到的資料合在一起返回:
@RestController
@RequestMapping("/user")
public class TestUserController {
@Autowired
private MasterTestUserMapper masterTestUserMapper;
@Autowired
private SlaveTestUserMapper slaveTestUserMapper;
/**
* 查詢全部
*/
@GetMapping("/listall")
public Object listAll() {
//master庫,自定義介面查詢
QueryWrapper<MasterTestUser> queryWrapper = new QueryWrapper<>();
List<MasterTestUser> resultData = masterTestUserMapper.selectAll(queryWrapper.isNotNull("name"));
//slave庫,mp內建介面
List<SlaveTestUser> resultDataSlave = slaveTestUserMapper.selectList(null);
//返回
Map<String, Object> result = new HashMap<>();
result.put("master" , resultData);
result.put("slave" , resultDataSlave);
return ResponseResult.success(result);
}
}
- 使用Autowired註解注入對應的mapper
- 使用對應資料庫的 mapper 進行業務操作
- 根據業務在資料庫中執行相應的操作,如主只做增刪改操作、從只讀操作
至此,多資料來源的實現已完成,當前示例是兩個同構的資料庫,當然,若是異構的資料庫,或者多於兩個的資料庫,處理方式是一樣的,只不過是把資料來源增加一套而已。
4. 優缺點
由上述說明,我們可以總結一下使用多套資料來源的方法進行多資料庫操作,它的優缺點是什麼。
4.1 優點
- 簡單、直接:一個庫對應一套處理方式,很好理解。
- 符合開閉原則( OCP ):開發的設計模式告訴我們,對擴充套件開放,對修改關閉,新增多一個數據庫,原來的那一套不需要改動,只新增即可。
4.2 缺點
- 資源浪費:針對每一個數據源寫一套操作,連線資料庫的資源也是獨立的,分別佔用同樣多的資源。
SqlSessionFactory
是一個工廠,建議是使用單例,完全可以重用,不需要建立多個,只需要更改資料來源即可,跟多執行緒,使用執行緒池減少資源消耗是同一道理。 - 程式碼冗餘:在前面的多資料來源配置中可以看出,其實 master 和 slave 的很多操作是一樣的,只是改個名稱而已,因此會造成程式碼冗餘。
- 缺乏靈活:所有需要使用的地方都需要引入對應的mapper,對於很多操作,只是選擇資料來源的不一樣,程式碼邏輯是一致的。另外,對於一主多從的情況,若需要對多個從庫進行負載均衡,相對比較麻煩。
正因為有上述的缺點,所以還有改進的空間。於是就有了動態資料來源,至於動態資料來源如何實現,下回分解。
5. 總結
本文對多個數據庫的操作進行了初步探討,並對使用多套源的策略進行講解,結合主從程式碼示例,搭建了 Spring Boot + MyBatis Plus 工程,配置多資料來源及使用 Mapper 進行多資料來源操作,最後對多套資料來源的優缺點進行總結。希望小夥伴們可以對多資料來源操作有個初步印象。
本文有配套的示例程式碼,有興趣的可以跑一下示例來感受一下。
參考資料
- Spring主從資料庫的配置和動態資料來源切換原理:
https://www.liaoxuefeng.com/article/1182502273240832
- 多資料來源與動態資料來源的權衡:
https://juejin.im/post/5b790a866fb9a019ea01f38c
- 談談Spring Boot 資料來源載入及其多資料來源簡單實現:
https://juejin.im/post/5cb0023d5188250df17d4ffc
- Spring Boot 和 MyBatis 實現多資料來源、動態資料來源切換:
https://juejin.im/post/5a927d23f265da4e7e10d740
往期文章
- java開發必學知識:動態代理
- 2019 讀過的好書推薦
- springboot+apache前後端分離部署https
- springboot+logback 日誌輸出企業實踐(下)
- springboot+logback 日誌輸出企業實踐(上)
我的公眾號(搜尋Mason技術記錄
),獲取更多技術記錄:
相關推薦
搞定SpringBoot多資料來源(1):多套源策略
目錄 1. 引言 2. 執行環境 3. 多套資料來源 3.1 搭建 Spring Boot 工程 3.1.1 初始化 Spring Boot 工程 3.1.2 新增 MyBat
搞定SpringBoot多資料來源(3):引數化變更源
目錄 1. 引言 2. 引數化變更源說明 2.1 解決思路 2.2 流程說明 3. 實現引數化變更源 3.1 改造動態資料來源 3.1.1 動
springBoot(18):多賬號輪詢發送郵件
spring boot 多賬號 一、添加依賴<!-- mail --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-b
附1:多線程並發方案的不足——響應式Spring的道法術器
響應式編程本系列文章索引《響應式Spring的道法術器》本篇內容是響應式流的附錄。 (以下接響應式流的1.2.1.1節,關於“CPU眼中的時間”的內容。請不要單獨看這一篇內容,否則有些內容可能讓你摸不著頭腦 0..0) 多線程的方式有其不完美之處,而且有些難以駕馭—— 一、耗時的上下文切換 CPU先生不太樂
mybatis多資料來源錯誤:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
使用Spring Boot2.0整合mybatis多資料來源遇到如下錯誤 錯誤資訊: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.boot.mapper.one.Sc
caioj1472: 字尾自動機1:多個串的LCS
子串母串跑合並答案 一個點的fail的dep是比任意一條根到這個點路徑長度要小的。 那麼改就可以直接來了。 #include<cstdio> #include<iostream> #include<cstring> #include<cstdlib&
六天搞懂“深度學習”之三:多層神經網路
為了克服單層神經網路只能解決線性可分問題的侷限性,神經網路進化為多層結構。然而,花費了將近30年的時間,才將隱藏層新增到單層神經網路中。很難理解為什麼花費了這麼長時間,其中的主要問題是學習規則。 單層神經網路中的增量規則對於多層神經網路的訓練是無效的,這是因為訓練中在隱藏層產生的誤差並沒
nginx反向代理cas server之1:多個cas server負載均衡配置以及ssl配置
系統環境採用centOS7 由於cas server不支援session持久化方式的共享,所以請用其他方式代替,例如:組播複製。 nginx反向代理完整配置(兩個網站例項) user nobody nobody; worker_processes 2; #error
Hibernate 學習心得1: 多對多關係中,中間表無法插入資料。
Hibernate 學習心得之一 多對多關係中,中間表無法插入資料。最近學習 spring4+hibernate4,學習中遇到了很多坑。在這裡我來說說我遇到的坑,這裡就不介紹如何spring如何整合hibernate。目前學習過程中,我遇到的兩個問題1.為何在hibernat
springBoot 動態資料來源以及Mybatis多資料來源
原文地址:https://blog.csdn.net/tengxing007/article/details/78424645前言在開發過程中可能需要用到多個數據源,比如一個專案(MySQL)就是和(SQL Server)混合使用,就需要使用多資料來源;如果業務場景比較復炸,
多線程:多線程設計模式(三):Master-Worker模式
fonts strong stat bre not 多線程 too () 部分 Master-Worker模式是常用的並行模式之一,它的核心思想是,系統有兩個進程協作工作:Master進程,負責接收和分配任務;Worker進程,負責處理子任務。當Worker進程將子任務處理
分散式鎖, 註解形式, 搞定SpringBoot定時任務@Scheduled 在叢集下的優化
SpringBoot提供了 Schedule模組完美支援定時任務的執行 在實際開發中由於專案部署在分散式或叢集伺服器上 會導致定時任務多次觸發 因此,使用redis分佈鎖機制可以有效避免多次執行定時任務 核心方法是org.springframework.data.redis
Java多執行緒:多執行緒基礎
多執行緒基礎 多執行緒實現-Thread和Runnable 通常使用如下程式碼啟動一個新的執行緒: private void startNewThread1() { new Thread() { @Override pub
MySQL多表3:多表查詢操作
轉載:https://blog.csdn.net/Anarkh_Lee/article/details/79856935 1.交叉連線查詢(基本不會使用——得到的是兩個表的乘積) 語法:select * from A,B; 2.內連線查詢
我的畢設終於搞定了!題為:利用Python開發一款遊戲!
現在來看一下實現的過程。 外形 俄羅斯方塊整個介面分為兩部分,一部分是左邊的遊戲區域,另一部分是右邊的顯示區域,顯示得分、速度、下一個方塊樣式等。這裡就不放截圖了,看上圖就可以。 遊戲區域跟貪吃蛇一樣,是由一個個小方格組成的,為了看得直觀,
10分鐘輕鬆搞定SpringBoot整合RabbitMQ教程
第一步:在專案pom.xml檔案中,新增pring-boot-starter-amqp 依賴<dependency> <groupId>org.springframework.boot</groupId> <artifac
十分鐘搞定SpringBoot 和Redis 實戰整合
這裡,對於springboot和redis 不做介紹,大家可以自己去查詢資料~~~~~~~~~~~ windows下本地安裝 redis 安裝 話不多說,來就是開搞! 專案框架 具體實現程式碼 pom檔案 <?xml version="1.0" en
一週搞定MPU6050Linux驅動(1)
第一日 準備工作: 1、硬體平臺 firefly-rk3288開發板,MPU6500六軸陀螺儀模組 2、參考 開幹: 1、搭建開發環境 首先,搭建firefly-rk3288開發板的核心編譯平臺、原始碼樹等。意思就是需要在ubuntu系統中下載firefly-rk32
一個figure存在多個legend:多行多列圖例
問題:如何在Matlab中,將圖例繪製成多行多列的? 查詢資料過程中發現, 1)有的方法要求多個plot中橫座標具有相同的長度 2)高版本中,部分函式報錯(應該可以改正) 本文根據需要找到一個可靠的解決方法,現整理如下: 優點:每個plot互相獨立;程式碼量
多執行緒 : 多執行緒共享區域性變數的方法
1. 操作相同時,寫一個 Runnable 實現類,內部設定成員變數,run 方法修改該變數,將該Runnable傳給不同Thread使用; 2. 操作不同時,在Thread呼叫類例項化一個數據實例,傳遞給不同Runnable處理,再把不同的Runnable傳給不同Thre