4.Mybatis Plus
Mybatis Plus 学习
第一章 Hello Mybatis Plus
STEP1: 数据库建表
use study_mybatis_plus;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`
(
id BIGINT NOT NULL COMMENT '主键ID 自增' AUTO_INCREMENT,
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
INSERT INTO `user` (id, name, age, email)
VALUES (1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
SETP2: Maven依赖
<!--3.整合Mybatis Plus-->
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!--JDBC启动器依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--Mybatis Plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.9</version>
</dependency>
<!--Lombok:快速get/set-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
STEP3: 配置数据库和日志
# 数据源配置
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/study_mybatis_plus?serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
# 日志
logging:
level:
com.mts: debug
STEP4: 实体类
package com.mts.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
// getter+setter+to_string
// 无参
// 全参
// 对应数据库表的名称
public class User {
// 标记自增
private Integer id;
private String name;
private Integer age;
private String email;
}
STEP5: DAO/Mapper层改造
- & 解释: 持久化层的接口①直接继承
BaseMapper<Object>具体有哪些方法?
package com.mts.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mts.entity.User;
public interface UserMapper extends BaseMapper<User> {
// ^^^^^^^^^^只需要继承即可,如果有复杂的增删改查再写
}
SETP6: Service层改造
- & 解释: 接口①直接继承
IService<Object>
package com.mts.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.mts.entity.User;
import org.springframework.stereotype.Service;
public interface UserService extends IService<User> {
}
- & 解释: 实现类 ①继承
ServiceImpl<XXXMapper, Object>②实现 服务层接口 具体有哪写方法
package com.mts.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mts.entity.User;
import com.mts.mapper.UserMapper;
import com.mts.service.UserService;
import org.springframework.stereotype.Service;
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
// 如果有复杂的 业务逻辑再写...
}
STEP7: 测试
package com.mts.test;
import com.mts.entity.User;
import com.mts.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
public class Test01 {
private UserService userService;
public void test() {
// 查询所有
List<User> list = userService.list();
list.forEach(System.out::println);
}
}
第二章 基本使用
第一节 @TableName
- 作用: 解决实体和数据库表名字不一致的问题
第二节 @TableField
- ①解决实体中字段和数据库字段不一致的问题
- ②
exit=false解决实体有, 但数据库中没有的字段 - ③
select = false默认select是查询所有, 标注了的不会查询, 全是null
第三节 @TableId
- 作用:
@TableId(type=IdType.AUTD)插入时默认是UUID生成自增的ID, 加了主键才会自增
第四节 逻辑删除@TableLogic
- 实现方式一: 全局配置(但保证所有表的逻辑删字段都为一个名字)
# 逻辑删
mybatis-plus:
global-config:
db-config:
logic-delete-field: deleted
logic-delete-value: 1 # 删除的标记是1
logic-not-delete-value: 0 #
- 实现方式二:
@TableLogic注解: 在需要的字段上面标记即可
第五节 乐观锁🔒@Version
STEP1: 添加乐观锁拦截器
- 回顾: 有
@Configuration注解的都是配置类;@Bean是注入一个对象, 这里注入的是一个MybatisPlusInterceptor类的对象
package com.mts.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author 明廷盛
* @Date 2024/12/8 22:53
* @Description ToDo(一句话描述类的作用)
*/
public class MybatisPlusConfig {
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); //配置乐观锁 拦截器
return interceptor;
}
}
STEP2: 控制版本号的字段上加@Version
- ! 控制版本号的字段名字随意
package com.mts.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author 明廷盛
* @Date 2024/12/8 21:50
* @Description ToDo(一句话描述类的作用)
*/
public class User {
private Integer id;
private String name;
private Integer age;
private String email;
private Integer deleted;
private Integer balance;
// 乐观锁
private Integer version;
}
第六节 分页
STEP1: Maven依赖
- ! 提示: 于 v3.5.9 起,PaginationInnerInterceptor 已分离出来。如需使用,则需单独引入 mybatis-plus-jsqlparser 依赖 , 具体请查看 安装 一章。
<!--分页插件-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-jsqlparser-4.9</artifactId>
<version>3.5.9</version>
</dependency>
STEP2: 编写拦截器
package com.mts.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author 明廷盛
* @Date 2024/12/8 22:53
* @Description ToDo(一句话描述类的作用)
*/
public class MybatisPlusConfig {
public MybatisPlusInterceptor mybatisPlusInterceptorPagination() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// ^^^^^^^^^^^^^^^^^分页的拦截器
// ^^^^指定数据库为MYSQL
return interceptor;
}
}
STEP3: 实现分页
// 分页
public void test04() {
// 分页STEP1:创建IPage对象(实现类为Page和PageDTO), 并指定当前页数/和每页页数
IPage<User> page = new Page<>(1, 2);
// ^^^^^页数索引从1开始
// 分页STEP2:调用userMapper的selectPage方法, 传入上述IPage实例化的对象
userMapper.selectPage(page, null);
// 分页STEP3:调用page.getRecords() 获取结果 返回值类型:`List`
List<User> records = page.getRecords(); // 当页结果
System.out.println("总共有几条数据(去除逻辑删的): "+page.getTotal());
System.out.println("总共有几页: "+page.getPages());
System.out.println("当前在第几页: "+page.getCurrent());
System.out.println("每页几条数据: "+page.getSize());
// 输出
records.forEach(System.out::println);
}
第七节 条件构造器
官网: 条件构造器] 用到什么查什么, 这里只是给出一些需求的例子
2.7.1 QueryWrapper示例
- ! 注意: 支持链式编程
public void test02() {
// 需求: 查询①name以J开头 ②age>=20 ③id降序
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.like("name", "J"); // name以J开头
userQueryWrapper.ge("age", 20); // age>=20
userQueryWrapper.orderByDesc("id"); // id降序
// 查询时携带参数
List<User> result = userService.list(userQueryWrapper);
result.forEach(System.out::println);
}
2.7.2 LambdaQueryWrapper示例
- 语法: 方法引用
User::getId是指向User类中的getId方法的引用 - 对比QueryWrapper的好处: ①避免了硬编码字段名 ②避免手瓢写错
public void test3() {
// 需求: 查询①name以J开头 ②age>=20 ③id降序
LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
userQueryWrapper.like(User::getName, "J"); // name以J开头
userQueryWrapper.ge(User::getAge, 20); // age>=20
userQueryWrapper.orderByDesc(User::getId); // id降序
// 查询时携带参数
List<User> result = userService.list(userQueryWrapper);
result.forEach(System.out::println);
}
第三章 代码生成器
题外话: Mybatis的那个代码生成器, 堪比折磨, 4种模式, 配置麻烦的要死; 相比之下MP就简单太多了
SETP1: Mavne依赖
<!--MP 代码生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.9</version>
</dependency>
<!--Freemarker 模板引擎-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
SETP2: 编写代码生成器
package com.mts.auto_generator;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.sql.Types;
import java.util.Collections;
/**
* @Author 明廷盛
* @Date 2024/12/9 10:52
* @Description 9处需要修改
*/
public class GeneratorTest {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://localhost:3306/study_mybatis_plus?serverTimezone=UTC", "root", "root") //TODO 修改数据库连接
.globalConfig(builder -> {
builder.author("baomidou") // TODO 设置作者
//.enableSwagger() // TODO swagger 模式(别开,不好用)
.outputDir("D:\\文档\\CodeBeach\\毕设SE\\back_v1\\src\\main\\java"); // TODO 当前项目的Java目录
})
.dataSourceConfig(builder ->
builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
int typeCode = metaInfo.getJdbcType().TYPE_CODE;
if (typeCode == Types.SMALLINT) {
// 自定义类型转换
return DbColumnType.INTEGER;
}
return typeRegistry.getColumnType(metaInfo);
})
)
.packageConfig(builder ->
builder.parent("com.mts") // TODO 启动类所在的位置(设置父包名)
.moduleName("g2") // TODO 生成的东西会放在com.mts.g1包下(设置父包模块名)
.pathInfo(Collections.singletonMap(OutputFile.xml, "D:\\文档\\CodeBeach\\毕设SE\\back_v1\\src\\main\\resources\\g2\\mapper")) // TODO 设置mapperXml生成路径
)
.strategyConfig(builder ->
builder.addInclude("dept", "user") // TODO 设置需要生成的表名
//.addTablePrefix("t_", "c_") //TODO 上一行tb_dept ,这行过滤"tb" 那生成的实体名字为Dept, 如果不写就是TbDept(设置过滤表前缀)
)
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}
- Title: 4.Mybatis Plus
- Author: 明廷盛
- Created at : 2026-02-02 05:32:25
- Updated at : 2025-02-17 16:22:00
- Link: https://blog.20040424.xyz/2026/02/02/😼Java全栈工程师/第四部分 中间件/4.Mybatis Plus/
- License: All Rights Reserved © 明廷盛