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
2.在插件设置中选择从本地导入配置
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
2.IDEA连接数据库
1.点击右上角的数据库标志,然后点击加号,选择要连接的数据库
2.填写数据库信息进行连接
3.创建并使用数据库 sunrays_framework
sql
create database sunrays_framework;
use sunrays_framework;
4.创建示例表
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
3.项目环境搭建
1.创建模块 common-mybatis-plus-starter-demo
2.目录结构
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.启动测试
4.使用EasyCode生成代码
1.选中指定的表,右键生成代码
2.选择Module和Package以及之前导入的模板,点击OK
3.生成的代码
5.测试分页查询
1.不加任何条件查询第一页,页面大小为三的数据
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方法的入参格式化打印
2.统计数量的sql格式化打印
3.查询数据的sql格式化打印
4.controller和service方法的出参格式化打印
4.生成代码详细说明
1.概览
2.ExampleTableController.java
1.功能说明
1.Controller层,跟前端进行交互
2.提供基础的CRUD接口
3.继承了BaseController,提供了Date类型的自动转换,和一些快捷的响应方法
2.使用说明
1.该层是req查vo封,当然,如果图方便直接po查po封也是可以的
2.本层方法首先要进行参数校验,然后再调用注入的service进行业务的处理
3.ExampleTableConverter.java
1.功能说明
1.使用MapStruct实现实体之间的转换
2.使用说明
1.如果要转换ExampleTableReq到ExampleTable,直接编写方法体即可(前提是属性名相同)
2.然后直接使用INSTANCE去调用这个方法即可完成自动转换
4.ExampleTable.java
1.功能说明
1.作为与数据库直接交互的po而存在,每个字段都对应数据库的字段
2.继承了BaseEntity的四个通用字段
2.使用说明
1.在mapper层使用po查,po封
5.ExampleTableReq.java
1.功能说明
1.req是用来封装前端的请求的实体类
2.使用说明
1.在Controller层和Service层作为方法的参数来封装请求(最好是一个请求配一个req)
2.如果需要分页,就继承 PageInfo(默认pageNo = 1 pageSize = 10)
6.ExampleTableVo.java
1.功能说明
1.vo是用来封装后端给前端的响应的
2.使用说明
1.在Controller和Service层作为方法的返回值来封装响应
7.ExampleTableMapper.java
1.功能说明
1.mapper层的接口,定义与数据库交互的接口
2.提供了三个基础接口
2.使用说明
1.直接在这里编写数据访问层的接口即可
8.ExampleTablePlusMapper.java
1.功能说明
1.为了使用MyBatis-Plus框架才生成的接口
2.继承了SunRaysBaseService接口的一些方法
2.使用说明
1.开发中不需要在意!!!
9.ExampleTableService.java
1.功能说明
1.Service实现类用来实现业务逻辑
2.继承了SunRaysBaseServiceImpl的实现好的方法
2.使用说明
1.实现Service层的接口来完成具体的业务逻辑
2.使用super来调用框架自动生成的方法,使用注入的mapper接口来调用自定义的方法(后面会有演示)
10.ExampleTableMapper.xml
1.功能说明
1.用来实现mapper接口编写具体的SQL
2.提供了三个基础的接口实现
2.使用说明
1.就是跟普通的MyBatis一样,直接实现接口编写SQL即可
5.示例:使用框架编写一个需求
1.需求
分页查询id大于x的用户
2.目录结构
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.查询结果
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
}
}