Skip to content

common-mybatis-plus-starter

1.功能介绍

1.对MyBatisPlus的分页插件进行扩展

  • 使其具备更加丰富的信息
  • 结合函数式编程以及泛型的封装,实现一行调用分页。

2.对 MyBatis-Plus 框架进行二次封装

  • 隐藏 QueryWrapper 等复杂实现细节,保留动态生成 CRUD 特性。
  • 结合 EasyCode 自定义模板优化代码生成,实现无感封装,统一数据访问规范,大幅提升开发效率和规范性,打造高可用、高扩展性、低入门成本的企业级数据访问层解决方案。

3.定义 MyBatis 拦截器

  • 对 SQL 进行格式话输出,提高 SQL 可读性,便于排查问题。

2.配置示例

1.开启 SQL 美化 配置是否启用 SQL 美化功能,使 SQL 更加可读。

yaml
sun-rays:
  mybatis-plus:
    sql-beauty-enabled: true # 是否开启 SQL 美化(默认 true)

2.配置数据源 配置数据库连接信息,使用 Spring 的数据源配置项。

yaml
spring:
  datasource:
    username: ${MYSQL_USERNAME} # 用户名
    password: ${MYSQL_PASSWORD} # 密码
    url: jdbc:mysql://${MYSQL_IP}:${MYSQL_PORT}/${MYSQL_DATABASE}?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false # 数据库连接 URL

3.配置 EasyCode 的宏定义

properties
# 定义配置宏
# 指定逻辑删除字段名(驼峰命名)
set($logicDeleteField = "isDeleted")

# 指定逻辑删除字段名(下划线命名)
set($logicDeleteFieldUnder = "is_deleted")

# 定义全局逻辑删除字段的删除值和未删除值
set($deleteColumnValue = 1)
set($notDeletedColumnValue = 0)

# 配置排除的字段列表(驼峰命名)
set($excludedFields = ["createBy", "createTime", "updateBy", "updateTime"])

4.配置 common-mybatis-plus-starter 模块的 BaseEntity 与通用字段一致

5.最佳实践(无需任何配置)

通用字段为:
  • create_by
  • create_time
  • update_by
  • update_time
  • is_deleted

3.案例演示

1.EasyCode插件配置

1.下载 EasyCodeConfig.json

点击下载 EasyCodeConfig.json

2.在插件设置中选择从本地导入配置

CleanShot 2025-01-19 at 14.38.51@2x

3.在设置的Global Config中创建sunrays-framework.vm并粘贴配置
properties
# 定义配置宏

    # 指定逻辑删除字段名(驼峰命名)
    set($logicDeleteField = "isDeleted")
    # 指定逻辑删除字段名(下划线命名)
    set($logicDeleteFieldUnder = "is_deleted")
    
    #定义全局逻辑删除字段的删除值和未删除值
    set($deleteColumnValue = 1)
    set($notDeletedColumnValue = 0)

    # 配置排除的字段列表(驼峰命名)
    set($excludedFields = ["createBy", "createTime", "updateBy", "updateTime"])
    # 最佳实践(必要字段):create_by,create_time,update_by,update_time,is_deleted

CleanShot 2025-01-19 at 14.40.10@2x

2.IDEA连接数据库

1.点击右上角的数据库标志,然后点击加号,选择要连接的数据库

CleanShot 2025-01-19 at 14.47.49@2x

2.填写数据库信息进行连接

CleanShot 2025-01-19 at 14.50.06@2x

3.创建并使用数据库 sunrays_framework

CleanShot 2025-01-19 at 14.53.54@2x

CleanShot 2025-01-19 at 14.54.04@2x

sql
create database sunrays_framework;
use sunrays_framework;
4.创建示例表

CleanShot 2025-01-19 at 14.55.42@2x

sql
CREATE TABLE example_table
(
    id             INT PRIMARY KEY COMMENT '主键ID',
    user_name      VARCHAR(255) NULL COMMENT '用户名称',
    user_email     VARCHAR(255) NULL COMMENT '用户邮箱',
    phone_number   VARCHAR(20)  DEFAULT NULL COMMENT '联系电话',
    home_address   VARCHAR(255) DEFAULT NULL COMMENT '家庭住址',
    account_status TINYINT(1)   DEFAULT 0 COMMENT '账户状态(0-禁用,1-启用)',
    create_by      VARCHAR(50)  DEFAULT NULL COMMENT '创建人',
    create_time    DATETIME COMMENT '创建时间',
    update_by      VARCHAR(50)  DEFAULT NULL COMMENT '更新人',
    update_time    DATETIME COMMENT '更新时间',
    is_deleted     TINYINT(1)   DEFAULT 0 COMMENT '逻辑删除标记(0-未删除,1-已删除)'
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COMMENT ='示例表';

INSERT INTO example_table (id, user_name, user_email, phone_number, home_address, account_status, create_by)
VALUES (1, '张三', 'zhangsan@example.com', '13800138000', '北京市朝阳区', 1, 'admin'),
       (2, '李四', 'lisi@example.com', '13800138001', '上海市浦东新区', 1, 'admin'),
       (3, '王五', 'wangwu@example.com', '13800138002', '广州市天河区', 0, 'admin'),
       (4, '赵六', 'zhaoliu@example.com', '13800138003', '深圳市福田区', 1, 'admin'),
       (5, '孙七', 'sunqi@example.com', '13800138004', '成都市武侯区', 0, 'admin'),
       (6, '周八', 'zhouba@example.com', '13800138005', '杭州市西湖区', 1, 'admin'),
       (7, '吴九', 'wujia@example.com', '13800138006', '重庆市渝中区', 0, 'admin'),
       (8, '郑十', 'zhengshi@example.com', '13800138007', '南京市鼓楼区', 1, 'admin'),
       (9, '冯十一', 'fengshiyi@example.com', '13800138008', '武汉市武昌区', 1, 'admin'),
       (10, '褚十二', 'chushier@example.com', '13800138009', '长沙市岳麓区', 0, 'admin');
5.让IDEA连接刚才创建的数据库sunrays_framework

CleanShot 2025-01-19 at 15.11.53@2x

CleanShot 2025-01-19 at 15.12.17@2x

3.项目环境搭建

1.创建模块 common-mybatis-plus-starter-demo

CleanShot 2025-01-19 at 14.59.01@2x

2.目录结构

CleanShot 2025-01-19 at 15.07.33@2x

3.pom.xml
xml
    <dependencies>
        <!-- common-mybatis-plus-starter -->
        <dependency>
            <groupId>cn.sunxiansheng</groupId>
            <artifactId>common-mybatis-plus-starter</artifactId>
        </dependency>
        <!-- common-log4j2-starter 是必须引入的!!! -->
        <dependency>
            <groupId>cn.sunxiansheng</groupId>
            <artifactId>common-log4j2-starter</artifactId>
        </dependency>
        <!-- EasyCode 生成的代码依赖Web模块-->
        <dependency>
            <groupId>cn.sunxiansheng</groupId>
            <artifactId>common-web-starter</artifactId>
        </dependency>

        <!-- env模块确保数据安全,可以不引入 -->
        <dependency>
            <groupId>cn.sunxiansheng</groupId>
            <artifactId>common-env-starter</artifactId>
        </dependency>
    </dependencies>
4.application.yml 配置日志根目录、.env文件的绝对路径、数据源
yaml
sun-rays:
  log4j2:
    home: /Users/sunxiansheng/IdeaProjects/sunrays-framework/sunrays-common-demo/common-mybatis-plus-starter-demo/logs # 日志根目录(默认./logs)
  env:
    path: /Users/sunxiansheng/IdeaProjects/sunrays-framework/sunrays-common-demo/common-mybatis-plus-starter-demo # .env文件的绝对路径
spring:
  datasource:
    username: ${MYSQL_USERNAME} # 用户名
    password: ${MYSQL_PASSWORD} # 密码
    url: jdbc:mysql://${MYSQL_IP}:${MYSQL_PORT}/${MYSQL_DATABASE}?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false # url
5..env文件配置数据库信息
properties
MYSQL_USERNAME=用户名
MYSQL_PASSWORD=密码
MYSQL_IP=ip
MYSQL_PORT=端口
MYSQL_DATABASE=数据库名字
6.MyBatisPlusController.java 测试Controller
java
package cn.sunxiansheng.mybatis.plus.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Description: MyBatisPlusController
 *
 * @Author sun
 * @Create 2025/1/19 15:01
 * @Version 1.0
 */
@RestController
public class MyBatisPlusController {

    /**
     * A test endpoint.
     *
     * @return A sample response.
     */
    @RequestMapping("/test")
    public String test() {
        return "This is a test response from MyBatisPlusController";
    }
}
7.MyBatisPlusApplication.java 启动类
java
package cn.sunxiansheng.mybatis.plus;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Description: MyBatisPlusApplication
 *
 * @Author sun
 * @Create 2025/1/19 15:00
 * @Version 1.0
 */
@SpringBootApplication
public class MyBatisPlusApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyBatisPlusApplication.class, args);
    }
}
8.启动测试

CleanShot 2025-01-29 at 18.10.24@2x

CleanShot 2025-01-19 at 15.15.09@2x

CleanShot 2025-01-19 at 15.15.17@2x

4.使用EasyCode生成代码

1.选中指定的表,右键生成代码

CleanShot 2025-01-19 at 15.17.06@2x

2.选择Module和Package以及之前导入的模板,点击OK

CleanShot 2025-01-19 at 15.18.54@2x

3.生成的代码

CleanShot 2025-01-19 at 15.21.51@2x

5.测试分页查询

1.不加任何条件查询第一页,页面大小为三的数据

CleanShot 2025-01-29 at 10.47.16@2x

2.响应结果
json
{
  "success": true,
  "code": 200,
  "message": "操作成功",
  "data": {
    "current": 1,
    "size": 3,
    "total": 10,
    "records": [
      {
        "id": 1,
        "userName": "张三",
        "userEmail": "zhangsan@example.com",
        "phoneNumber": "13800138000",
        "homeAddress": "北京市朝阳区",
        "accountStatus": 1,
        "isDeleted": 0
      },
      {
        "id": 2,
        "userName": "李四",
        "userEmail": "lisi@example.com",
        "phoneNumber": "13800138001",
        "homeAddress": "上海市浦东新区",
        "accountStatus": 1,
        "isDeleted": 0
      },
      {
        "id": 3,
        "userName": "王五",
        "userEmail": "wangwu@example.com",
        "phoneNumber": "13800138002",
        "homeAddress": "广州市天河区",
        "accountStatus": 0,
        "isDeleted": 0
      }
    ],
    "orders": [
    ],
    "start": 1,
    "end": 3,
    "totalPages": 4,
    "hasNextPage": true,
    "hasPreviousPage": false,
    "pages": 4
  }
}

6.全链路日志展示

1.controller和service方法的入参格式化打印

CleanShot 2025-01-29 at 18.13.32@2x

2.统计数量的sql格式化打印

CleanShot 2025-01-29 at 18.13.46@2x

3.查询数据的sql格式化打印

CleanShot 2025-01-29 at 18.13.54@2x

4.controller和service方法的出参格式化打印

CleanShot 2025-01-29 at 18.14.08@2x

CleanShot 2025-01-29 at 18.14.15@2x

4.生成代码详细说明

1.概览

CleanShot 2025-01-29 at 10.52.57@2x

2.ExampleTableController.java

1.功能说明
1.Controller层,跟前端进行交互
2.提供基础的CRUD接口

CleanShot 2025-01-29 at 11.00.22@2x

3.继承了BaseController,提供了Date类型的自动转换,和一些快捷的响应方法

CleanShot 2025-01-29 at 11.02.14@2x

CleanShot 2025-01-29 at 11.02.21@2x

2.使用说明
1.该层是req查vo封,当然,如果图方便直接po查po封也是可以的

2.本层方法首先要进行参数校验,然后再调用注入的service进行业务的处理

CleanShot 2025-01-29 at 11.05.15@2x

CleanShot 2025-01-29 at 11.06.13@2x

3.ExampleTableConverter.java

1.功能说明
1.使用MapStruct实现实体之间的转换
2.使用说明
1.如果要转换ExampleTableReq到ExampleTable,直接编写方法体即可(前提是属性名相同)

CleanShot 2025-01-29 at 11.10.53@2x

2.然后直接使用INSTANCE去调用这个方法即可完成自动转换

CleanShot 2025-01-29 at 11.12.27@2x

4.ExampleTable.java

1.功能说明
1.作为与数据库直接交互的po而存在,每个字段都对应数据库的字段

CleanShot 2025-01-29 at 11.19.14@2x

2.继承了BaseEntity的四个通用字段

CleanShot 2025-01-29 at 11.14.48@2x

2.使用说明
1.在mapper层使用po查,po封

CleanShot 2025-01-29 at 11.21.41@2x

5.ExampleTableReq.java

1.功能说明
1.req是用来封装前端的请求的实体类
2.使用说明
1.在Controller层和Service层作为方法的参数来封装请求(最好是一个请求配一个req)

CleanShot 2025-01-29 at 11.25.23@2x

CleanShot 2025-01-29 at 11.28.58@2x

2.如果需要分页,就继承 PageInfo(默认pageNo = 1 pageSize = 10)

CleanShot 2025-01-29 at 11.26.22@2x

CleanShot 2025-01-29 at 11.29.51@2x

6.ExampleTableVo.java

1.功能说明
1.vo是用来封装后端给前端的响应的
2.使用说明
1.在Controller和Service层作为方法的返回值来封装响应

7.ExampleTableMapper.java

1.功能说明
1.mapper层的接口,定义与数据库交互的接口
2.提供了三个基础接口

CleanShot 2025-01-29 at 12.39.53@2x

2.使用说明
1.直接在这里编写数据访问层的接口即可

8.ExampleTablePlusMapper.java

1.功能说明
1.为了使用MyBatis-Plus框架才生成的接口
2.继承了SunRaysBaseService接口的一些方法

CleanShot 2025-01-29 at 12.46.25@2x

2.使用说明
1.开发中不需要在意!!!

9.ExampleTableService.java

1.功能说明
1.Service实现类用来实现业务逻辑
2.继承了SunRaysBaseServiceImpl的实现好的方法

CleanShot 2025-01-29 at 12.46.47@2x

2.使用说明
1.实现Service层的接口来完成具体的业务逻辑
2.使用super来调用框架自动生成的方法,使用注入的mapper接口来调用自定义的方法(后面会有演示)

10.ExampleTableMapper.xml

1.功能说明
1.用来实现mapper接口编写具体的SQL
2.提供了三个基础的接口实现
2.使用说明
1.就是跟普通的MyBatis一样,直接实现接口编写SQL即可

CleanShot 2025-01-29 at 12.52.46@2x

5.示例:使用框架编写一个需求

1.需求

分页查询id大于x的用户

2.目录结构

CleanShot 2025-01-29 at 13.21.29@2x

3.ExampleTableController.java 新增一个req和一个方法

java
    /**
     * queryPageById的请求实体类,由于需要分页,就继承了PageInfo
     */
    @Data
    public static class QueryPageByIdReq extends PageInfo {
        /**
         * id大于x
         */
        private Integer x;
    }

    /**
     * 分页查询id大于x的数据
     *
     * @param queryPageByIdReq queryPageById的请求实体类
     * @return 返回分页查询的结果
     */
    @GetMapping("/queryPageById")
    public PlusPageResult<ExampleTableVo> queryPageById(@RequestBody QueryPageByIdReq queryPageByIdReq) {
        return exampleTableService.queryPageById(queryPageByIdReq);
    }

4.ExampleTableService.java 定义接口

java
    /**
     * 分页查询id大于x的数据
     *
     * @param queryPageByIdReq queryPageById的请求实体类
     * @return 返回分页查询的结果
     */
    PlusPageResult<ExampleTableVo> queryPageById(ExampleTableController.QueryPageByIdReq queryPageByIdReq);

5.ExampleTableServiceImpl.java 实现接口

直接调用SunPlusPageHelper.paginate传入pageNo,pageSize,分页查询后要封装到的实体类(一般就是po),还有一个函数式接口,就是将框架给的一个plusPageResult放到mapper接口的第一个参数即可,不用管为什么,这样就可以自动完成分页,而后面的参数才是自己查询真正需要使用的

java
    @Override
    public PlusPageResult<ExampleTableVo> queryPageById(ExampleTableController.QueryPageByIdReq queryPageByIdReq) {
        // 获取x
        Integer x = queryPageByIdReq.getX();

        // 分页查询
        PlusPageResult<ExampleTable> poPageResult = SunPlusPageHelper.paginate(queryPageByIdReq.getPageNo(), queryPageByIdReq.getPageSize(), ExampleTable.class,
                plusPageResult -> {
                    // 正常执行查询即可,但是方法中的第一个参数一定要是plusPageResult,至于为什么不需要关心
                    return exampleTableMapper.queryPageById(plusPageResult, x);
                });

        // 将po转换为vo并返回
        return ExampleTableConverter.INSTANCE.convertPoPage2VoPage(poPageResult);
    }

6.ExampleTableMapper.java 编写mapper接口

java
    /**
     * 分页查询id大于x的的用户
     *
     * @param plusPageResult
     * @param x
     * @return
     */
    PlusPageResult<ExampleTable> queryPageById(@Param("plusPageResult") PlusPageResult<ExampleTable> plusPageResult, @Param("x") Integer x);

7.ExampleTableMapper.xml 实现mapper接口

直接使用后面的x参数进行查询即可,注意要加上is_deleted = 0,也就是查询未逻辑删除的数据

java
    <!-- 查询id大于x的的用户 -->
    <select id="queryPageById" resultMap="ExampleTableMap">
        select *
        from example_table
        where id > #{x}
        and is_deleted = 0
    </select>

8.查询结果

CleanShot 2025-01-29 at 13.24.50@2x

json
{
  "success": true,
  "code": 200,
  "message": "操作成功",
  "data": {
    "current": 1,
    "size": 2,
    "total": 7,
    "records": [
      {
        "id": 4,
        "userName": "赵六",
        "userEmail": "zhaoliu@example.com",
        "phoneNumber": "13800138003",
        "homeAddress": "深圳市福田区",
        "accountStatus": 1,
        "isDeleted": 0
      },
      {
        "id": 5,
        "userName": "孙七",
        "userEmail": "sunqi@example.com",
        "phoneNumber": "13800138004",
        "homeAddress": "成都市武侯区",
        "accountStatus": 0,
        "isDeleted": 0
      }
    ],
    "orders": [
    ],
    "start": 1,
    "end": 2,
    "totalPages": 4,
    "hasNextPage": true,
    "hasPreviousPage": false,
    "pages": 4
  }
}

9.通过日志梳理查询流程

CleanShot 2025-01-29 at 15.19.18@2x

1.首先是进入了Controller,可以看到携带的参数

CleanShot 2025-01-29 at 15.19.43@2x

2.然后进入Service,查看参数

CleanShot 2025-01-29 at 15.19.54@2x

3.接下来发现有一条SQL,查询了total

CleanShot 2025-01-29 at 15.18.01@2x

4.然后下一条SQL,查询了分页的数据

CleanShot 2025-01-29 at 15.18.23@2x

5.退出Service

CleanShot 2025-01-29 at 15.18.41@2x

6.退出Controller

CleanShot 2025-01-29 at 15.18.52@2x