【SringBoot項目中MyBatis-Plus多數據源應用實踐】

文章目錄

前言

一、Mybatis-Plus是什么?

二、多數據源是什么?

三、使用步驟

1. 新建一個SpringBoot項目

2. 引入必要的MyBatis架包

3. 新建兩個數據庫及兩張表

3.3.1 新建數據庫:DB_A,并創建一張數據表alarm_kind,以及一些測試數據。

3.3.2 同樣再建一個數據庫DB_B,并創建一張數據表test,以及一些測試數據。

4. 修改配置文件application.yml

5. 編碼

5.1 entity 實體類

5.2 mapper接口

5.3 service服務接口

5.4 service服務實現

6. 測試及驗證?

總結




前言

在日常大型項目中經常會遇到分庫分表的數據庫設計,咱們普通的SpringBoot 單體項目通過默認配置及注解可以很容易實現對單個數據庫的操作管理,但遇到需要多個數據庫操作可能會比較麻煩,因此咱們今天主要介紹如何使用MyBatis-Plus提供的一個多數據源動態加載組件簡單輕松實現在單個項目中實現對多個數據庫的操作管理。

關鍵詞:SpringBoot 、MyBatis、MyBatis-Plus、多數據源

一、Mybatis-Plus是什么?

Mybatis-Plus是一個Mybatis(opens new window)的增強工具,在Mybatis的基礎上只做增強不做改變,為簡化開發。

二、多數據源是什么?

多數據源是指在分布式環境或集群環境下,為不同的數據庫(如MySQL、Oracle、SQLServer等)配置數據源,以便在項目中能夠隨意切換以獲取數據。這種配置方式允許應用程序根據需要連接到不同的數據庫,以實現特定的業務需求,如數據隔離、水平擴展、讀寫分離等。

三、使用步驟

1. 新建一個SpringBoot項目

可以通過Ide工具向導建立,這里不詳細描述了。

2. 引入必要的MyBatis架包

在項目的pom.xml加入如何內容

  <!-- mysql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.18</version></dependency><!-- 連接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.24</version></dependency><!-- mybatis plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mybatisplus-spring-boot-starter.version}</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus</artifactId><version>>3.4.2</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.4.1</version></dependency><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.3</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.5.0</version></dependency>

3. 新建兩個數據庫及兩張表

3.3.1 新建數據庫:DB_A,并創建一張數據表alarm_kind,以及一些測試數據。

CREATE DATABASE IF NOT EXISTS `DB_A` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
USE `DB_A`;DROP TABLE IF EXISTS `alarm_kind`;
CREATE TABLE IF NOT EXISTS `alarm_kind` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',`type_no` varchar(255) DEFAULT NULL COMMENT '類型編號',`type_name` varchar(255) DEFAULT NULL COMMENT '類型名稱',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COMMENT='報警類型字典表';DELETE FROM `alarm_kind`;
INSERT INTO `alarm_kind` (`id`, `type_no`, `type_name`) VALUES(1, 'Powon', '市電'),(2, 'Baton', 'UPS電源'),(3, 'Move', '位移'),(4, 'Alarm', '震動'),(5, 'Cut', '切割檢測'),(6, 'Smoke', '煙霧'),(7, 'LBJ', '聲光'),(8, 'HW', '紅外'),(9, 'Box4_NoPutTimeOut', '四號柜款箱未放入');

3.3.2 同樣再建一個數據庫DB_B,并創建一張數據表test,以及一些測試數據。

CREATE DATABASE IF NOT EXISTS `DB_B` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
USE `DB_B`;DROP TABLE IF EXISTS `test`;
CREATE TABLE IF NOT EXISTS `alarm_kind` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',`type_no` varchar(255) DEFAULT NULL COMMENT '類型編號',`type_name` varchar(255) DEFAULT NULL COMMENT '類型名稱',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COMMENT='報警類型字典表';DELETE FROM `test`;
INSERT INTO `test` (`id`, `type_no`, `type_name`) VALUES(1, 'Powon', '測試1'),(2, 'Baton', '測試2'),(3, 'Move', '測試3');

4. 修改配置文件application.yml

server:port: 8085  #服務端口配置
spring:application:name: ms-basedatasource:dynamic:primary: baseA #默認加載的數據庫是DB_Astrict: falsedatasource:baseA:driver-class-name: com.mysql.cj.jdbc.Driver #數據源配置url: jdbc:mysql://127.0.0.1:13306/DB_A?serverTimezone=GMT%2B8&useSSL=falseusername: rootpassword: data@123456!type: com.alibaba.druid.pool.DruidDataSource  #連接池配置max-idle: 10  #No operations allowed after connection closed錯誤原因及解決max-wait: 10000min-idle: 5initial-size: 5validation-query: SELECT 1test-on-borrow: falsetest-while-idle: truetime-between-eviction-runs-millis: 18800baseB:driver-class-name: com.mysql.cj.jdbc.Driver #數據源配置url: jdbc:mysql:///127.0.0.1:13306/DB_B?serverTimezone=GMT%2B8&useSSL=falseusername: rootpassword: data@123456!type: com.alibaba.druid.pool.DruidDataSource  #連接池配置max-idle: 10  #No operations allowed after connection closed錯誤原因及解決max-wait: 10000min-idle: 5initial-size: 5validation-query: SELECT 1test-on-borrow: falsetest-while-idle: truetime-between-eviction-runs-millis: 18800

5. 編碼

5.1 entity 實體類

AlarmKind.java

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;/*** <p>* 報警類型字典表* </p>** @since 2022-05-24*/
@Data
@EqualsAndHashCode(callSuper = false)
public class AlarmKind implements Serializable {private static final long serialVersionUID = 1L;/*** 主鍵ID*/@TableId(value = "id", type = IdType.AUTO)private Long id;/*** 類型編號*/private String typeNo;/*** 類型名稱*/private String typeName;
}

?Test.java

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;/*** <p>* 測試表* </p>**/
@Data
@EqualsAndHashCode(callSuper = false)
public class Test implements Serializable {private static final long serialVersionUID = 1L;/*** 主鍵ID*/@TableId(value = "id", type = IdType.AUTO)private Long id;/*** 類型編號*/private String typeNo;/*** 類型名稱*/private String typeName;
}

5.2 mapper接口

?AlarmKIndMapper.java


import com.xxxx.rest.entity.AlarmKind;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;/*** <p>* 報警類型字典表 Mapper 接口* </p>**/
public interface AlarmKindMapper extends BaseMapper<AlarmKind> {List<AlarmKind> getAll();
}

?TestMapper.java


import com.xxxx.rest.entity.Test;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;/*** <p>* 測試表 Mapper 接口* </p>**/
public interface TestMapper extends BaseMapper<Test> {List<Test> getAll();
}

5.3 service服務接口

IAlarmKIndService.java

import com.xxx.rest.entity.AlarmKind;
import com.baomidou.mybatisplus.extension.service.IService;import com.xianban.rest.model.msbase.vo.platform.BaseLineVO;import java.util.List;/*** <p>* 報警類型表 服務類* </p>**/
public interface IAlarmKindService extends IService<AlarmKind> {List<AlarmKind> getAll();
}

ITestService.java

import com.xxx.rest.entity.Test;
import com.baomidou.mybatisplus.extension.service.IService;import com.xianban.rest.model.msbase.vo.platform.BaseLineVO;import java.util.List;/*** <p>*測試表 服務類* </p>**/
public interface ITestService extends IService<Test> {List<Test> getAll();
}

5.4 service服務實現

AlarmKindServiceImpl.java

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xxxx.rest.entity.AlarmKind;
import com.xxxx.rest.mapper.AlarmKindMapper;
import com.xxxx.rest.service.IAlarmKindService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;/*** <p>* 報警類型表 服務實現類* </p>**/
@Service
@DS("baseA") //這個注解是指定操作哪個數據源,如果沒有這個注解則代表操作配置文件中的主數據源
public class AlarmKindServiceImpl extends ServiceImpl<AlarmKindMapper, AlarmKind> implements IAlarmKindService {@Resourceprivate AlarmKindMapper mapper;@Overridepublic List<AlarmKind> getAll() {QueryWrapper<AlarmKind> wrapper=new QueryWrapper();return mapper.selectList(wwapper);}
}

TestServiceImpl.java

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xxxx.rest.entity.Test;
import com.xxxx.rest.mapper.TestMapper;
import com.xxxx.rest.service.ITestService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;/*** <p>* 測試表 服務實現類* </p>**/
@Service
@DS("baseB") //這個注解是指定操作哪個數據源,如果沒有這個注解則代表操作配置文件中的主數據源
public class TestServiceImpl extends ServiceImpl<TestMapper, Test> implements ITestService {@Resourceprivate TestMapper mapper;@Overridepublic List<Test> getAll() {QueryWrapper<Test> wrapper=new QueryWrapper();return mapper.selectList(wwapper);}
}


? ??

6. 測試及驗證?

編寫測試Controller

@RestController
@RequestMapping("/test")
@CrossOrigin
@Api(tags = "手動測試接口管理")
public class TestController {@Resourceprivate IAlarmKindService alarmKindService;@Resourceprivate ITestService testService;//查詢報警類型數據@GetMapping("/getAlarmKindList")public ResponseEntity<Object> getAlarmKindList(){
return getRespOk(alarmKindService.getAll());
}
//查詢測試表數據@GetMapping("/getTestList")public ResponseEntity<Object> getTestList(){
return getRespOk(testService.getAll());
}protected ResponseEntity<Object> getRespOk(Object resData) {return new ResponseEntity<>(resData, HttpStatus.OK); }}
啟動項目

在瀏覽器訪問
1.報警類型信息接口地址:http://localhost:8085/test/getAlarmKindList,如果返回結果說明正確

2.測試信息接口地址:http://localhost:8085/test/getTestList,如果返回結果說明正確

總結

通過以上內容分析,其實關鍵就引入架包、修改配置文件、服務的實現類中增加@DS("配置文件中定義的數據源名稱"),代碼改動可以說非常小。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/21750.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/21750.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/21750.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

云端數據提取:安全、高效地利用無限資源

在當今的大數據時代&#xff0c;企業和組織越來越依賴于云平臺存儲和處理海量數據。然而&#xff0c;隨著數據的指數級增長&#xff0c;數據的安全性和高效的數據處理成為了企業最為關心的議題之一。本文將探討云端數據安全的重要性&#xff0c;并提出一套既高效又安全的數據提…

淺測 長亭雷池 WAF “動態防護”

本文首發于 Anyeの小站 前言 雷池 WAF 社區版的更新速度是真快啊&#xff0c;幾乎一周一個小版本&#xff0c;倆月一個大版本&#xff0c;攻城獅們真的狠啊&#xff0c;沒法測了。 廢話不多說&#xff0c;前兩天看到了 這篇文章&#xff0c;對雷池的“動態防護”功能挺感興趣…

Android應用的基本構造及威脅(apk)

目錄 APK文件是什么 apk文件解壓后的目錄結構 apk文件的存儲位置

去掉el-table表頭右側類名是gutter,width=17px的空白區域(包括表頭樣式及表格奇偶行樣式和表格自動滾動)

代碼如下&#xff1a; <el-table:data"tableData"ref"scroll_Table":header-cell-style"getRowClass":cell-style"styleBack"height"350px"style"width: 100%"><el-table-column prop"id" l…

Scrum團隊在迭代中如何處理計劃外的工作

認為 Scrum 團隊不做計劃其實是一個誤區&#xff0c;實際上很多 Scrum 團隊在沖刺計劃會議以及在細化工作項時均會進行詳細規劃。此外&#xff0c;他們還會創建一個路線圖&#xff0c;以便顯示他們在多個沖刺中的計劃。 Scrum 團隊需要經常進行計劃&#xff0c;以便在不斷變化…

linux學習:進程

目錄 例子1 獲取當前進程的進程標識符 例子2 創建一個新的子進程 例子3 展示了父進程和子進程的進程標識符 例子4 區分父進程和子進程 例子5 區分父進程和子進程的行為 例子6 比較進程標識符來區分父進程和子進程 例子7 子進程如何修改一個變量&…

混合動力電動汽車介紹(二)

接續前一章內容&#xff0c;本篇文章介紹混合動力汽車串聯、并聯和混聯的系統組成和工作原理。 一、串聯混合動力電動汽車的系統組成和工作原理 上圖為串聯混合動力電動汽車的結構簡圖。汽車由電動機-發電機驅動行駛&#xff0c;電機控制器的動力來自油箱-發動機-發電機-發電機…

Python 爬蟲零基礎:探索網絡數據的神秘世界

Python 爬蟲零基礎&#xff1a;探索網絡數據的神秘世界 在數字化時代&#xff0c;網絡數據如同無盡的寶藏&#xff0c;等待著我們去發掘。Python爬蟲&#xff0c;作為獲取這些數據的重要工具&#xff0c;正逐漸走進越來越多人的視野。對于零基礎的學習者來說&#xff0c;如何入…

基于Spring Boot框架的分頁查詢和文件上傳

分頁查詢 分析 要想從數據庫中進行分頁查詢&#xff0c;我們要使用LIMIT關鍵字&#xff0c;格式為&#xff1a;limit 開始索引 每頁顯示的條數 假設一頁想展示10條數據 查詢第1頁數據的SQL語句是&#xff1a; select * from emp limit 0,10; 查詢第2頁數據的SQL語句是&…

【Pytest官方文檔翻譯及學習】2.2 如何在測試中編寫和報告斷言

目錄 2.2 如何在測試中編寫和報告斷言 2.2.1 使用assert語句斷言 2.2.2 關于預期異常的斷言 2.2.3 關于預期警告的斷言 2.2.4 應用上下文相關的比較 2.2.5 為失敗的斷言定義自己的解釋 2.2.6 斷言內省細節 2.2 如何在測試中編寫和報告斷言 2.2.1 使用assert語句斷言 p…

6、架構-服務端緩存

為系統引入緩存之前&#xff0c;第一件事情是確認系統是否真的需要緩 存。從開發角度來說&#xff0c;引入緩存會提 高系統復雜度&#xff0c;因為你要考慮緩存的失效、更新、一致性等問題&#xff1b;從運維角度來說&#xff0c;緩存會掩蓋一些缺 陷&#xff0c;讓問題在更久的…

npm徹底清理緩存

在使用npm過程中&#xff0c;肯定會遇到清緩存的情況&#xff0c;網上的命令一般為 npm cache clear --force有時筆者在清理緩存之后npm install依然失敗&#xff0c;仔細發現&#xff0c;執行該命令之后npm報了一個警告 npm WARN using --force Recommended protections dis…

代碼隨想錄算法訓練營第27天|● 39. 組合總和● 40.組合總和II● 131.分割回文串

組合總和 題目鏈接 39. 組合總和 - 力扣&#xff08;LeetCode&#xff09; 代碼&#xff1a; class Solution {public List<List<Integer>> res new ArrayList<>();public List<Integer> list new ArrayList<>();public int sum 0;/**…

在nginx中配置反向代理

在nginx中配置反向代理&#xff0c;需要使用proxy_pass指令。以下是一個簡單的nginx反向代理配置示例&#xff1a; server {listen 80;server_name example.com;location / {proxy_pass http://backend_server;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote…

LoadRunner 錄制腳本時提示無Internet訪問/加載慢,如何解決?

LoadRunner 錄制腳本時提示無Internet訪問/加載慢&#xff0c;如何解決&#xff1f; 在使用LoadRunner 12.02 進行錄制腳本時提示無Internet訪問&#xff0c;這是如下圖&#xff1a; 翻譯中文如下&#xff1a; 這里&#xff0c;我認為大家應該都已經點過yes了&#xff0c;但是…

python結構化模式匹配switch-case,Python 3.10中引入,Python的模式匹配(pattern matching)語法

增加了采用模式加上相應動作的 match 語句 和 case 語句 的形式的結構化模式匹配。 模式由序列、映射、基本數據類型以及類實例構成。 模式匹配使得程序能夠從復雜的數據類型中提取信息、根據數據結構實現分支&#xff0c;并基于不同的數據形式應用特定的動作。 語法與操作 模…

Linux下配置Pytorch

1.Anaconda 1.1虛擬環境創建 2.Nvidia驅動 3.CUDA驅動安裝 4.Pytorch安裝 具體的步驟如上&#xff1a;可參考另一位博主的博客非常詳細&#xff1a; Linux服務器配置PythonPyTorchCUDA深度學習環境_linux cuda環境配置-CSDN博客https://blog.csdn.net/NSJim/article/detai…

極海APM32F072用Keil5燒錄失敗Error: Flash Download failed -“Cortex-MO+“

在用Keil5燒錄時&#xff0c;出現錯誤彈窗&#xff0c;大概長這樣&#xff1a; 檢查了一圈設置&#xff0c;都搞不好。 先用J-Flash&#xff0c;顯示讀寫保護&#xff08;未截圖&#xff09;&#xff0c;會跳出界面讓選擇是否解除讀寫保護&#xff1a; 1.點擊允許讀操作YES&am…

DNF手游攻略:0氪攻略,轉職技巧與避坑指南!

在DNF手游的冒險旅程中&#xff0c;角色的轉職是一次重要的成長經歷。通過轉職&#xff0c;玩家可以獲得全新的技能和屬性&#xff0c;提升自己在地下城中的戰斗力。本文將為您介紹轉職后的關鍵技巧和日常任務&#xff0c;幫助您更好地適應新的職業身份&#xff0c;成為地下城中…

Python從0到100(二十九):requests模塊處理cookie

1 爬蟲中使用cookie 為了能夠通過爬蟲獲取到登錄后的頁面&#xff0c;或者是解決通過cookie的反扒&#xff0c;需要使用request來處理cookie相關的請求 1.1 爬蟲中使用cookie的利弊 帶上cookie的好處 能夠訪問登錄后的頁面能夠實現部分反反爬 帶上cookie的壞處 一套cookie往往…