SpringBoot整合Mybatis-Plus多数据源

前言

随着业务的不断扩展和复杂度的增加,我们在开发过程中往往需要访问多个数据库。比如:我们可能需要同时访问主数据库和从数据库,或者访问多个独立的数据库来处理不同的业务逻辑。这时候,我们就需要使用多数据源来实现对多个数据库的操作。

SpringBoot整合Mybatis-plus

在之前的文章SpringBoot整合MyBatis-Plus已经详细介绍过,本文就不在多做介绍了。

进行整合

引入pom依赖

xml 复制代码
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.19</version>
</dependency>

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.3.2</version>
</dependency>

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>4.1.3</version>
</dependency>

yml文件配置

yaml 复制代码
spring:
  application:
    name: springboot-demo

  #配置数据库信息
  datasource:
    dynamic:
      primary: master
      strict: false
      datasource:
        master:
          url: jdbc:mysql://ip:3306/test?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false&useAffectedRows=true&serverTimezone=Asia/Shanghai
          driver-class-name: com.mysql.cj.jdbc.Driver
          username: 账号
          password: 密码
        slave1:
          url: jdbc:mysql://ip:3306/test1?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false&useAffectedRows=true&serverTimezone=Asia/Shanghai
          driver-class-name: com.mysql.cj.jdbc.Driver
          username: 账号
          password: 密码
    type: com.alibaba.druid.pool.DruidDataSource
    

#配置mybatis-plus信息
mybatis-plus:
  configuration:
    #日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    #驼峰形式显示
    map-underscore-to-camel-case: true
  mapper-locations: classpath:mybatis-mapper/*.xml
  global-config:
    db-config:
      #全局逻辑删除的实体字段名
      logic-delete-field: isDeleted
      #逻辑已删除值(默认为1)
      logic-delete-value: 1
      #逻辑未删除值(默认为0)
      logic-not-delete-value: 0

创建两个数据库及创建表

主数据库test

user表结构

从数据库test1

class_info表结构

创建各自的实体类

kotlin 复制代码
package com.example.springbootdemo.entity;

import com.baomidou.mybatisplus.annotation.*;
import com.example.springbootdemo.enums.GenderEnum;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * <p>
 *  用户实体类
 * </p>
 *
 * @author yurenwei
 * @since 2023/9/7
 */
@ApiModel(value = "用户参数", description = "用户参数")
@Data
@Accessors(chain = true)
@TableName("user")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 主键id
     */
    @ApiModelProperty(value = "主键id")
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private Long id;

    /**
     * 姓名
     */
    @ApiModelProperty(value = "姓名")
    private String userName;

    /**
     * 手机号
     */
    @ApiModelProperty(value = "手机号")
    private String phone;

    /**
     * 性别
     */
    @ApiModelProperty(value = "性别")
    private GenderEnum gender;

    /**
     * 地址
     */
    @ApiModelProperty(value = "地址")
    private String address;

    /**
     * 状态(0、禁用1、启用)
     */
    @ApiModelProperty(value = "状态(0、禁用1、启用)")
    private Boolean status;

    /**
     * 注册时间
     */
    @ApiModelProperty(value = "注册时间")
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime registerTime;

    /**
     * 创建人
     */
    @ApiModelProperty(value = "创建人")
    private Long createBy;

    /**
     * 创建时间
     */
    @ApiModelProperty(value = "创建时间")
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;

    /**
     * 修改人
     */
    @ApiModelProperty(value = "修改人")
    private Long updateBy;

    /**
     * 修改时间
     */
    @ApiModelProperty(value = "修改时间")
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;

    /**
     * 是否删除(0、否1、是)
     */
    @ApiModelProperty(value = "是否删除(0、否1、是)")
    private Boolean isDeleted;
}
kotlin 复制代码
package com.example.springbootdemo.entity;

import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * <p>
 *  班级实体类
 * </p>
 *
 * @author yurenwei
 * @since 2023/9/25
 */
@ApiModel(value = "班级参数", description = "班级参数")
@Data
@Accessors(chain = true)
@TableName("class_info")
public class ClassInfo implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 主键id
     */
    @ApiModelProperty(value = "主键id")
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private Long id;

    /**
     * 班级名称
     */
    @ApiModelProperty(value = "班级名称")
    private String className;

    /**
     * 创建人
     */
    @ApiModelProperty(value = "创建人")
    private Long createBy;

    /**
     * 创建时间
     */
    @ApiModelProperty(value = "创建时间")
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;

    /**
     * 修改人
     */
    @ApiModelProperty(value = "修改人")
    private Long updateBy;

    /**
     * 修改时间
     */
    @ApiModelProperty(value = "修改时间")
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;

    /**
     * 是否删除(0、否1、是)
     */
    @ApiModelProperty(value = "是否删除(0、否1、是)")
    private Boolean isDeleted;

}

创建各自mapper

java 复制代码
package com.example.springbootdemo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.springbootdemo.entity.User;
import org.springframework.stereotype.Repository;

/**
 * <p>
 *  用户mapper
 * </p>
 *
 * @author yurenwei
 * @since 2023/9/7
 */
@Repository
public interface UserMapper extends BaseMapper<User> {
}
java 复制代码
package com.example.springbootdemo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.springbootdemo.entity.ClassInfo;
import org.springframework.stereotype.Repository;

/**
 * <p>
 *  班级mapper
 * </p>
 *
 * @author yurenwei
 * @since 2023/9/25
 */
@Repository
public interface ClassInfoMapper extends BaseMapper<ClassInfo> {
}

创建各自接口

java 复制代码
package com.example.springbootdemo.mybatisplus;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.springbootdemo.entity.User;

/**
 * <p>
 *  用户接口
 * </p>
 *
 * @author yurenwei
 * @since 2023/9/7
 */
public interface IUserService extends IService<User> {
}
java 复制代码
package com.example.springbootdemo.mybatisplus;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.springbootdemo.entity.ClassInfo;

/**
 * <p>
 *  班级接口机
 * </p>
 *
 * @author yurenwei
 * @since 2023/9/25
 */
public interface IClassInfoService extends IService<ClassInfo> {
}

创建各自接口实现类

scala 复制代码
package com.example.springbootdemo.mybatisplus.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.springbootdemo.entity.User;
import com.example.springbootdemo.mapper.UserMapper;
import com.example.springbootdemo.mybatisplus.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * <p>
 *  用户接口实现类
 * </p>
 *
 * @author yurenwei
 * @since 2023/9/7
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}
scala 复制代码
package com.example.springbootdemo.mybatisplus.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.springbootdemo.entity.ClassInfo;
import com.example.springbootdemo.mapper.ClassInfoMapper;
import com.example.springbootdemo.mybatisplus.IClassInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * <p>
 *  班级接口实现类
 * </p>
 *
 * @author yurenwei
 * @since 2023/9/25
 */
@Slf4j
@Service
public class ClassInfoServiceImpl extends ServiceImpl<ClassInfoMapper, ClassInfo> implements IClassInfoService {
}

怎么区分主从数据库呢

user表是在我们的主数据库master里,class_info表是在我们从数据库slave里,那么我们在开发的时候如何区分他们呢?

这就需要我们使用一个注解@DS 来进行区分,我们在各自的接口实现类上添加注解

编写测试类进行测试

java 复制代码
package com.example.springbootdemo;

import cn.hutool.core.util.IdUtil;
import com.example.springbootdemo.entity.ClassInfo;
import com.example.springbootdemo.entity.User;
import com.example.springbootdemo.enums.GenderEnum;
import com.example.springbootdemo.mybatisplus.IClassInfoService;
import com.example.springbootdemo.mybatisplus.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.time.LocalDateTime;

@Slf4j
@SpringBootTest
public class SpringbootDemoApplicationTests {

    @Autowired
    private IUserService iUserService;

    @Autowired
    private IClassInfoService iClassInfoService;


    /**
     * 测试动态数据源
     */
    @Test
    public void testDynamicDatasource(){
        User user = new User()
                .setId(IdUtil.getSnowflakeNextId())
                .setUserName("测试")
                .setPhone("13000000000")
                .setGender(GenderEnum.MALE)
                .setAddress("山东")
                .setStatus(true)
                .setRegisterTime(LocalDateTime.now());
        iUserService.save(user);

        ClassInfo c = new ClassInfo()
                .setId(IdUtil.getSnowflakeNextId())
                .setClassName("三年一班");
        iClassInfoService.save(c);
        log.info("---over---");
    }

}

执行测试类

查看数据库数据

两个数据库的两张表的数据都已经被成功插入。

至此,SpringBoot整合Mybatis-Plus多数据源结束了。

相关推荐
devlei1 小时前
从源码泄露看AI Agent未来:深度对比Claude Code原生实现与OpenClaw开源方案
android·前端·后端
努力的小郑3 小时前
Canal 不难,难的是用好:从接入到治理
后端·mysql·性能优化
Victor3563 小时前
MongoDB(87)如何使用GridFS?
后端
Victor3564 小时前
MongoDB(88)如何进行数据迁移?
后端
小红的布丁4 小时前
单线程 Redis 的高性能之道
redis·后端
GetcharZp4 小时前
Go 语言只能写后端?这款 2D 游戏引擎刷新你的认知!
后端
宁瑶琴5 小时前
COBOL语言的云计算
开发语言·后端·golang
普通网友6 小时前
阿里云国际版服务器,真的是学生党的性价比之选吗?
后端·python·阿里云·flask·云计算
IT_陈寒6 小时前
Vue的这个响应式问题,坑了我整整两小时
前端·人工智能·后端
Soofjan7 小时前
Go 内存回收-GC 源码1-触发与阶段
后端