4.Mybatis Plus

明廷盛 嘻嘻😁

Mybatis Plus 学习

Mybatis Plus官网

第一章 Hello Mybatis Plus

STEP1: 数据库建表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');

SETP2: Maven依赖

title
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!--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: 配置数据库和日志

1
2
3
4
5
6
7
8
9
10
11
12
# 数据源配置
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: 实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.mts.entity;

import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data // getter+setter+to_string
@NoArgsConstructor // 无参
@AllArgsConstructor// 全参
@TableName("user") // 对应数据库表的名称
public class User {
@TableId(type = IdType.AUTO) // 标记自增
private Integer id;
private String name;
private Integer age;
private String email;
}

STEP5: DAO/Mapper层改造

1
2
3
4
5
6
7
8
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>
1
2
3
4
5
6
7
8
9
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> ②实现 服务层接口 具体有哪写方法
1
2
3
4
5
6
7
8
9
10
11
12
13
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;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
// 如果有复杂的 业务逻辑再写...
}

STEP7: 测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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;

@SpringBootTest
public class Test01 {
@Autowired
private UserService userService;

@Test
public void test() {
// 查询所有
List<User> list = userService.list();
list.forEach(System.out::println);
}
}

第二章 基本使用

第一节 @TableName

  • 作用: 解决实体和数据库表名字不一致的问题

第二节 @TableField

  1. ①解决实体中字段和数据库字段不一致的问题
  2. exit=false解决实体有, 但数据库中没有的字段
  3. select = false默认select是查询所有, 标注了的不会查询, 全是null

第三节 @TableId

  • 作用: @TableId(type=IdType.AUTD)插入时默认是UUID生成自增的ID, 加了主键才会自增

第四节 逻辑删除@TableLogic

  • 实现方式一: 全局配置(但保证所有表的逻辑删字段都为一个名字)
1
2
3
4
5
6
7
# 逻辑删
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类的对象
ins
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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(一句话描述类的作用)
*/

@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); //配置乐观锁 拦截器
return interceptor;
}

}

STEP2: 控制版本号的字段上加@Version

  • ! 控制版本号的字段名字随意
ins
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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(一句话描述类的作用)
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("user")
public class User {
private Integer id;
private String name;
private Integer age;
private String email;
private Integer deleted;
private Integer balance;

@Version // 乐观锁
private Integer version;

}

第六节 分页

STEP1: Maven依赖

  • ! 提示: 于 v3.5.9 起,PaginationInnerInterceptor 已分离出来。如需使用,则需单独引入 mybatis-plus-jsqlparser 依赖 , 具体请查看 安装 一章。
title
1
2
3
4
5
6
<!--分页插件-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-jsqlparser-4.9</artifactId>
<version>3.5.9</version>
</dependency>

STEP2: 编写拦截器

ins
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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(一句话描述类的作用)
*/

@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptorPagination() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// ^^^^^^^^^^^^^^^^^分页的拦截器
// ^^^^指定数据库为MYSQL
return interceptor;
}

}

STEP3: 实现分页

ins
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 分页
@Test
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示例

  • ! 注意: 支持链式编程
1
2
3
4
5
6
7
8
9
10
11
12
@Test
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的好处: ①避免了硬编码字段名 ②避免手瓢写错
1
2
3
4
5
6
7
8
9
10
11
12
@Test
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依赖

title
1
2
3
4
5
6
7
8
9
10
11
<!--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: 编写代码生成器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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 : 2025-02-15 21:56:34
  • Updated at : 2025-02-17 16:22:00
  • Link: https://blog.20040424.xyz/2025/02/15/😼Java全栈工程师/第四部分 中间件/4.Mybatis Plus/
  • License: All Rights Reserved © 明廷盛