# 多数据源组件
# 概述
随着业务量的扩大,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源,此组件是一个能够快速集成多数据源功能的组件。
# 配置
# 引入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
# 配置项说明
spring:
datasource:
dynamic:
primary: master #设置默认的数据源或者数据源组,默认值即为master
strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
datasource:
master:
url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
slave1:
url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
slave2:
url:jdbc:oracle:thin:@114.242.xxx.xxxx:8521/XE
username: HOS_APP_2_DEV
password: xxxxxx
driver-class-name: oracle.jdbc.driver.OracleDriver
该组件可以支持不同的数据库,如mysql、oracle、人大金仓等,使用时直接配置相应的数据库地址(url)、驱动名(driver-class-name)即可。
# 使用 @DS 切换数据源
@DS 可以注解在方法上或类上,同时存在就近原则 方法上注解 优先于 类上注解。
注解 | 结果 |
---|---|
没有@DS | 默认数据源 |
@DS("dsName") | dsName可以为组名也可以为具体某个库的名称 |
@Service
public class OrganizationServiceImpl implements OrganizationService {
@Autowired
OrganizationMapper organizationMapper;
@DS(DataSourceConstant.SLAVE1)
@Override
public List<Organization> selectALL() {
return organizationMapper.selectList();
}
}
# 约定
- 多数据源组件只做 切换数据源 这件核心的事情,并不限制你的具体操作,切换了数据源可以做任何CRUD。
- 配置文件所有以下划线 _ 分割的数据源 首部 即为组的名称,相同组名称的数据源会放在一个组下。
- 切换数据源可以是组名,也可以是具体数据源名称。组名则切换时采用负载均衡算法切换。
- 默认的数据源名称为 master ,你可以通过 spring.datasource.dynamic.primary 修改。
- 方法上的注解优先于类上注解。
- DS支持继承抽象类上的DS,暂不支持继承接口上的DS。
# 示例
# 引入依赖
在需要多数据源的工程中引入下面的依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
# 修改配置文件中数据源配置
spring:
datasource:
dynamic:
primary: master #设置默认的数据源或者数据源组,默认值即为master
strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
datasource:
master:
url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
slave1:
url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
# 在测试库中执行以下SQL
在master库及slave库中分别新建表
CREATE TABLE `staff` (
`id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键',
`name` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '姓名',
`gender` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '性别',
`age` int(2) NULL DEFAULT NULL COMMENT '年龄',
`email` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '邮箱',
`phone` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '手机号',
`org_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '部门id',
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '描述',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`tenant_id` bigint(20) NULL DEFAULT NULL COMMENT '租户id',
`is_deleted` int(1) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '员工信息表' ROW_FORMAT = Dynamic;
在master中执行以下SQL
INSERT INTO staff
(id, name, gender, age, email, phone, org_id, description, create_time, update_time, tenant_id, is_deleted)
VALUES('1', '张工', '男', 25, 'zhangsan@mediway.com', '1321111111111', NULL, NULL, '2023-05-18 18:23:51', '2023-05-19 08:56:39', NULL, NULL);
在salve中执行以下SQL
INSERT INTOstaff
(id, name, gender, age, email, phone, org_id, description, create_time, update_time, tenant_id, is_deleted)
VALUES('2', '李工', '女', 22, 'ligong@mediway.com', '132222222222', NULL, NULL, '2023-05-18 18:25:56', '2023-05-19 08:56:21', NULL, NULL);
# 编写测试代码
# DataSourceConstant.java
数据源常量类
package com.mediway.oa.user.constant;
public class DataSourceConstant {
public static final String MASTER = "master";
public static final String SLAVE1 = "slave1";
}
# Staff.java
staff表对应的实体类
package com.mediway.oa.user.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.mediway.hos.database.model.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
* 员工信息表
* </p>
*
* @author 代码生成器
* @since 2022-02-19
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@ApiModel(value="Staff对象", description="员工信息表")
@TableName(value = "staff", autoResultMap = true)
public class Staff extends BaseEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "性别")
@TableField("gender")
private String gender;
@ApiModelProperty(value = "年龄")
@TableField("age")
private Integer age;
@ApiModelProperty(value = "邮箱")
@TableField("email")
private String email;
@ApiModelProperty(value = "手机号")
private String phone;
@ApiModelProperty(value = "部门id")
@TableField("org_id")
private String orgId;
@ApiModelProperty(value = "描述")
@TableField("description")
private String description;
@ApiModelProperty(value = "租户id")
@TableField("tenant_id")
private String tenantId;
@TableField("is_deleted")
private Integer isDeleted;
}
# StaffMapper.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.mediway.oa.user.mapper.StaffMapper">
<select id="selectListStaff" resultType="com.mediway.oa.user.model.entity.Staff">
select
id,name,age,gender,email,phone
from staff
</select>
</mapper>
# StaffMapper.java
package com.mediway.oa.user.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mediway.oa.user.model.entity.Staff;
import java.util.List;
public interface StaffMapper extends BaseMapper<Staff> {
List<Staff> selectListStaff();
}
# StaffService.java
package com.mediway.oa.user.service;
import com.mediway.oa.user.model.entity.Staff;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Author 开发平台
* @Date Mon Sep 27 11:34:47 CST 2021
* @description
*/
@Service
public interface StaffService{
List<Staff> selectALL1();
List<Staff> selectALL2();
}
# StaffServiceImpl.java
在需要使用分库的service方法或类上加@DS
注解
package com.mediway.oa.user.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.mediway.oa.user.constant.DataSourceConstant;
import com.mediway.oa.user.mapper.StaffMapper;
import com.mediway.oa.user.model.entity.Staff;
import com.mediway.oa.user.service.StaffService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Author 开发平台
* @Date Mon Sep 27 11:34:47 CST 2021
* @description
*/
@Service
public class StaffServiceImpl implements StaffService {
@Autowired
StaffMapper staffMapper;
@Override
public List<Staff> selectALL1() {
return staffMapper.selectListStaff();
}
@DS(DataSourceConstant.SLAVE1)
@Override
public List<Staff> selectALL2() {
return staffMapper.selectListStaff();
}
}
# StaffController
package com.mediway.oa.user.controller;
import com.mediway.hos.base.model.BaseResponse;
import com.mediway.oa.user.model.entity.Staff;
import com.mediway.oa.user.service.StaffService;
import io.swagger.annotations.Api;
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 java.util.List;
@Api(tags = "员工信息")
@RestController
@RequestMapping("/user/staff")
public class StaffController {
@Autowired
private StaffService staffService;
@PostMapping("/selectALL1")
public BaseResponse<List<Staff>> selectALL1() {
return BaseResponse.success(staffService.selectALL1());
}
@PostMapping("/selectALL2")
public BaseResponse<List<Staff>> selectALL2() {
return BaseResponse.success(staffService.selectALL2());
}
}
# 演示效果
访问http://localhost:8080/api//user/staff/selectALL1
访问http://localhost:8080/api//user/staff/selectALL2