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多数据源结束了。

相关推荐
ai小鬼头6 小时前
Ollama+OpenWeb最新版0.42+0.3.35一键安装教程,轻松搞定AI模型部署
后端·架构·github
萧曵 丶6 小时前
Rust 所有权系统:深入浅出指南
开发语言·后端·rust
老任与码7 小时前
Spring AI Alibaba(1)——基本使用
java·人工智能·后端·springaialibaba
华子w9089258597 小时前
基于 SpringBoot+VueJS 的农产品研究报告管理系统设计与实现
vue.js·spring boot·后端
星辰离彬8 小时前
Java 与 MySQL 性能优化:Java应用中MySQL慢SQL诊断与优化实战
java·后端·sql·mysql·性能优化
GetcharZp9 小时前
彻底告别数据焦虑!这款开源神器 RustDesk,让你自建一个比向日葵、ToDesk 更安全的远程桌面
后端·rust
jack_yin10 小时前
Telegram DeepSeek Bot 管理平台 发布啦!
后端
小码编匠10 小时前
C# 上位机开发怎么学?给自动化工程师的建议
后端·c#·.net
库森学长10 小时前
面试官:发生OOM后,JVM还能运行吗?
jvm·后端·面试
转转技术团队10 小时前
二奢仓店的静默打印代理实现
java·后端