文章目錄
前言
一、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("配置文件中定義的數據源名稱"),代碼改動可以說非常小。