SpringBoot從入門到精通教程(三十二)- MybatisPlus框架動態數據源用法(支持多個DB,動態切換數據源)

需求背景

SpringBoot用法:MybatisPlus框架動態數據源用法(支持多個DB,動態切換數據源)

簡介

dynamic-datasource-spring-boot-starter 是一個基於springboot的快速集成多數據源的啓動器

優勢

網上關於動態數據源的切換的文檔有很多,核心只有兩種:

  1. 構建多套環境,優勢是方便控制也容易集成一些簡單的分佈式事務,缺點是非動態同時代碼量較多,配置難度大。
  2. 基於spring提供原生的 AbstractRoutingDataSource ,參考一些文檔自己實現切換。

如果你的數據源較少,場景不復雜,選擇以上任意一種都可以

如果你需要更多特性,請嘗試本動態數據源:

  1. 數據源分組,適用於多種場景 純粹多庫 讀寫分離 一主多從 混合模式。
  2. 簡單集成Druid數據源監控多數據源,簡單集成Mybatis-Plus簡化單表,簡單集成P6sy格式化sql,簡單集成Jndi數據源。
  3. 簡化Druid和HikariCp配置,提供全局參數配置。
  4. 提供自定義數據源來源(默認使用yml或properties配置)。
  5. 項目啓動後能動態增減數據源。
  6. 使用spel動態參數解析數據源,如從session,header和參數中獲取數據源。(多租戶架構神器)
  7. 多層數據源嵌套切換。(一個業務ServiceA調用ServiceB,ServiceB調用ServiceC,每個Service都是不同的數據源)
  8. 使用正則匹配或spel表達式來切換數據源(實驗性功能)。

劣勢

  1. 不能使用多數據源事務(同一個數據源下能使用事務),網上其他方案也都不能提供。
  2. 如果你需要使用到分佈式事務,那麼你的架構應該到了微服務化的時候了。
  3. 如果你只是幾個數據庫,但是有強烈的需求分佈式事務,建議還是使用傳統方式自己構建多套環境集成atomic這類,網上百度很多。

約定

  1. 本框架只做 切換數據源 這件核心的事情,並不限制你的具體操作,切換了數據源可以做任何CRUD。
  2. 配置文件所有以下劃線 _ 分割的數據源 首部 即爲組的名稱,相同組名稱的數據源會放在一個組下。
  3. 切換數據源即可是組名,也可是具體數據源名稱,切換時默認採用負載均衡機制切換。
  4. 默認的數據源名稱爲 master ,你可以通過spring.datasource.dynamic.primary修改。
  5. 方法上的註解優先於類上註解。

建議

強烈建議在 主從模式 下遵循普遍的規則,以便他人能更輕易理解你的代碼:

1. 主數據庫 建議 只執行 INSERT UPDATE DELETE 操作

2. 從數據庫 建議 只執行 SELECT 操作

準備內容

1. 準備兩個Mysql實例

2. 數據庫初始化init.sql腳本內容(或Docker安裝MySQL數據庫

db1-init.sql

-- for db1

drop table users;

CREATE TABLE `users` (
  `username` varchar(50) NOT NULL COMMENT '用戶名',
  `password` varchar(500) NOT NULL COMMENT '密碼',
  `enabled` tinyint(1) NOT NULL COMMENT '是否啓用',
  PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `users` (`username`, `password`, `enabled`)
VALUES
	('master', '123456', 1);

db2-init.sql

-- for db2

drop table users;

CREATE TABLE `users` (
  `username` varchar(50) NOT NULL COMMENT '用戶名',
  `password` varchar(500) NOT NULL COMMENT '密碼',
  `enabled` tinyint(1) NOT NULL COMMENT '是否啓用',
  PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `users` (`username`, `password`, `enabled`)
VALUES
	('slave', '654321', 1);

代碼演示

1. 項目目錄結構

2. pom.xml依賴組件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<parent>
		<groupId>com.md</groupId>
		<artifactId>spring-boot2-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version>
		<relativePath>../pom.xml</relativePath>
	</parent>

	<artifactId>spring-boot2-mybatis-plus-multi-datasource</artifactId>
	<packaging>jar</packaging>

	<name>spring-boot2-mybatis-plus-multi-datasource</name>
	<description>Spring Boot, MVC, Rest API for App</description>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.8</java.version>
		<swagger.version>2.9.2</swagger.version>
		<mybatisplus.version>3.2.0</mybatisplus.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<!-- 構建成可運行的Web項目 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>net.sf.json-lib</groupId>
			<artifactId>json-lib-ext-spring</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
		</dependency>
		<!-- swagger集成 -->
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger2</artifactId>
		</dependency>
		<!-- 默認swagger-ui -->
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger-ui</artifactId>
		</dependency>
		<!-- 更易用第三方swagger-ui組件 -->
		<dependency>
			<groupId>com.github.xiaoymin</groupId>
			<artifactId>swagger-bootstrap-ui</artifactId>
		</dependency>
		<!-- mybatis-plus集成 -->
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-generator</artifactId>
			<version>${mybatisplus.version}</version>
		</dependency>
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>${mybatisplus.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-freemarker</artifactId>
		</dependency>
		<!-- 集成動態數據源 -->
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
			<version>2.5.4</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

3. application.yml配置文件

spring:
   datasource:
      dynamic:
         primary: master #設置默認的數據源或者數據源組,默認值即爲master
         #如果你只是單數據源,則只需要註釋掉slave相關配置就好了,這裏爲了方便演示master與slave保持相同
         datasource:
            master:
               driverClassName: com.mysql.jdbc.Driver
               url: jdbc:mysql://localhost:33061/testdb?useUnicode=true&autoReconnect=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
               username: root
               password: 123456
            slave_1:
               driverClassName: com.mysql.jdbc.Driver
               url: jdbc:mysql://localhost:33062/testdb?useUnicode=true&autoReconnect=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
               username: root
               password: 123456
server:
   port: 9090

4. 自動代碼生成器類

CodeGenerator.java(如不熟悉mybatis-plus框架,可以先閱讀文章:入門Mybatis-Plus快速開發框架用法

通過此類,生成users表相應的dao,service,controller類,mapper文件等

5. UsersMapper

定義一個方法,使用@DS註解

  1. 使用 @DS 切換數據源
  2. @DS 可以註解在方法上和類上,同時存在方法註解優先於類上註解。
  3. 註解在service實現或mapper接口方法上,但強烈不建議同時在service和mapper註解。
package com.md.demo.dao;

import com.md.demo.entity.vo.Users;

import java.util.List;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * <p>
 * Mapper 接口
 * </p>
 *
 * @author Minbo
 * @since 2020-03-27
 */
//@DS("slave_1")
public interface UsersMapper extends BaseMapper<Users> {

	// 使用@DS註解,可以切換數據源。如果沒有配置@DS,則使用默認數據源(使用配置文件中的primary源)
	// @DS 可以註解在方法上和類上,同時存在方法註解優先於類上註解
	// 註解在service實現或mapper接口方法上,但強烈不建議同時在service和mapper註解

//	@DS("slave_1")
//	@DS("master")
	public List<Users> listDbInfo();
}

UsersMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.md.demo.dao.UsersMapper">

	<select id="listDbInfo" resultType="com.md.demo.entity.vo.Users">
		select * from users
	</select>

</mapper>

6. 服務類

IUsersService:

package com.md.demo.service;

import com.md.demo.entity.vo.Users;

import java.util.List;

import com.baomidou.mybatisplus.extension.service.IService;

/**
 * <p>
 * 服務類
 * </p>
 *
 * @author Minbo
 * @since 2020-03-27
 */
public interface IUsersService extends IService<Users> {

	public List<Users> listDbInfo();
}

服務實現類

package com.md.demo.service.impl;

import java.util.List;

import org.springframework.stereotype.Service;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.md.demo.dao.UsersMapper;
import com.md.demo.entity.vo.Users;
import com.md.demo.service.IUsersService;

/**
 * <p>
 * 服務實現類
 * </p>
 *
 * @author Minbo
 * @since 2020-03-27
 */
@Service
//@DS("slave_1")
public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users> implements IUsersService {

	@Override
//	@DS("master")
	public List<Users> listDbInfo() {
		return this.baseMapper.listDbInfo();
	}

}

7. 前端控制器

UsersController

package com.md.demo.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.md.demo.entity.vo.Users;
import com.md.demo.service.IUsersService;
import com.md.demo.util.JsonResult;
import com.md.demo.util.ResultCode;

import io.swagger.annotations.ApiOperation;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author Minbo
 * @since 2020-03-27
 */
@RestController
@RequestMapping("/demo/users")
public class UsersController {

	@Autowired
	private IUsersService usersService;

	@ApiOperation(value = "獲得用戶列表信息", httpMethod = "POST")
	@PostMapping("/listDbInfo")
	public JsonResult listDbInfo() {
		List<Users> dataList = this.usersService.listDbInfo();
		if (dataList == null || dataList.size() == 0) {
			return new JsonResult(ResultCode.SUCCESS_FAIL);
		}
		return new JsonResult(ResultCode.SUCCESS, dataList);
	}
}

8. 啓動類

Application:

package com.md.demo;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;

/**
 * 程序主入口
 * 
 * @author Minbo
 *
 */
@SpringBootApplication
@EnableSwaggerBootstrapUI
@MapperScan("com.md.demo.dao")
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

	/**
	 * 開啓過濾器功能
	 * 
	 * @return
	 */
	private CorsConfiguration buildConfig() {
		CorsConfiguration corsConfiguration = new CorsConfiguration();
		corsConfiguration.addAllowedOrigin("*");
		corsConfiguration.addAllowedHeader("*");
		corsConfiguration.addAllowedMethod("*");
		return corsConfiguration;
	}

	/**
	 * 跨域過濾器
	 * 
	 * @return
	 */
	@Bean
	public CorsFilter corsFilter() {
		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		source.registerCorsConfiguration("/**", buildConfig());
		return new CorsFilter(source);
	}
}

啓動成功輸出日誌:

就表示集成成功了

接口測試

1. 啓動項目,訪問地址:http://localhost:9090/doc.html

如果,service和mapper文件中,@DS都不啓用,則默認使用主庫

以mapper文件舉例(service同理):

package com.md.demo.dao;

import com.md.demo.entity.vo.Users;

import java.util.List;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * <p>
 * Mapper 接口
 * </p>
 *
 * @author Minbo
 * @since 2020-03-27
 */
//@DS("slave_1")
public interface UsersMapper extends BaseMapper<Users> {

	// 使用@DS註解,可以切換數據源。如果沒有配置@DS,則使用默認數據源(使用配置文件中的primary源)
	// @DS 可以註解在方法上和類上,同時存在方法註解優先於類上註解
	// 註解在service實現或mapper接口方法上,但強烈不建議同時在service和mapper註解

//	@DS("slave_1")
//	@DS("master")
	public List<Users> listDbInfo();
}

2. 如果啓用@DS("slave_1"),再次測試結果如下

package com.md.demo.dao;

import com.md.demo.entity.vo.Users;

import java.util.List;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * <p>
 * Mapper 接口
 * </p>
 *
 * @author Minbo
 * @since 2020-03-27
 */
//@DS("slave_1")
public interface UsersMapper extends BaseMapper<Users> {

	// 使用@DS註解,可以切換數據源。如果沒有配置@DS,則使用默認數據源(使用配置文件中的primary源)
	// @DS 可以註解在方法上和類上,同時存在方法註解優先於類上註解
	// 註解在service實現或mapper接口方法上,但強烈不建議同時在service和mapper註解

	@DS("slave_1")
//	@DS("master")
	public List<Users> listDbInfo();
}

完整源碼下載

我的Github源碼地址:

https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-mybatis-plus-multi-datasource

官方資料

dynamic-datasource動態數據源配置用法

同類資料

Mysql多數據源配置和Hikari用法集成詳解

該系列教程

SpringBoot從入門到精通教程

我的專欄

 

 

至此,全部介紹就結束了

 

 

-------------------------------

-------------------------------

 

我的CSDN主頁

關於我(個人域名)

我的開源項目集Github

 

期望和大家一起學習,一起成長,共勉,O(∩_∩)O謝謝

歡迎交流問題,可加個人QQ 469580884,

或者,加我的羣號 751925591,一起探討交流問題

不講虛的,只做實幹家

Talk is cheap,show me the code

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章