1.MyBatis-Plus 介绍
MyBatis-Plus 是MyBatis 的增强工具 , 在MyBatis 的基础上增强不做改变 , 为简化开发而生 , 提高效率而生 ; 省去大量重复的 XML/注解 SQL
特点 :
- 自动生成单表查询
- 强大的条件构造器
- 支持 Lambda , 分页 , 逻辑删除 , 自动填充
- 兼容所有 Mybatis 写法
MyBatis-Plus 官网条件构造器
快速上手
1.项目准备
1.1 SQL 准备
sql
DROP DATABASE IF EXISTS mybatis_test2;
CREATE DATABASE mybatis_test2 DEFAULT CHARACTER SET utf8mb4;
USE mybatis_test2;
DROP TABLE IF EXISTS user_info;
CREATE TABLE `user_info` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(127) NOT NULL,
`password` VARCHAR(127) NOT NULL,
`age` TINYINT(4) NOT NULL,
`gender` TINYINT(4) DEFAULT 0 COMMENT '1-男 2-女 0-默认',
`phone` VARCHAR(15) DEFAULT NULL,
`delete_flag` TINYINT(4) DEFAULT 0 COMMENT '0-正常,1-删除',
`create_time` DATETIME DEFAULT now(),
`update_time` DATETIME DEFAULT now(),
PRIMARY KEY (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;
INSERT INTO user_info(username, password, age, gender, phone)
VALUES
('admin','admin',18,1,'18612340001'),
('zhangsan','zhangsan',18,1,'18612340002'),
('lisi','lisi',18,1,'18612340003'),
('wangwu','wangwu',18,1,'18612340004');
2.2 pom 文件
XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.boop</groupId>
<artifactId>Mybatis-Plus</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Mybatis-Plus</name>
<description>Mybatis-Plus</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>4.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
这四个依赖

MyBatis-Plus 依赖
XML
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.5</version>
</dependency>
注意引入MyBatis-Plus 时 , Spring 的版本不能过高 , 否则会产生冲突
1.3 配置数据库相关文件
html
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/mybatis_test2?characterEncoding=utf8&useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印SQL
mapper-locations: classpath*:/mapper/**.xml
配置数据库 , 打印日志 , 匹配 Mapper.xml 的路径
1.4 创建实体类
java
@Data
public class UserInfo {
private Integer id;
private String username;
private String password;
private Integer age;
private Integer gender;
private String phone;
private Integer deleteFlag;
private Date createTime;
private Date updateTime;
}
1.5 编写 Mapper 接口
java
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
}
不需要写任何的方法
只需要继承 BaseMapper 接口 , 它已经实现了单表查询的 CRUD , 无需再编写单表 CRUD 代码

2. 测试代码
java
package com.boop.mybatisplus.mapper;
import com.boop.mybatisplus.model.UserInfo;
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 // 必须有
class MyBatisPlusTest {
@Autowired
private UserInfoMapper userInfoMapper;
// 1. 新增
@Test
void testInsert() {
UserInfo user = new UserInfo();
user.setUsername("bite");
user.setPassword("123456");
user.setAge(11);
user.setGender(0);
user.setPhone("18610001234");
userInfoMapper.insert(user);
}
// 2. 根据ID查询
@Test
void testSelectById() {
UserInfo user = userInfoMapper.selectById(1);
System.out.println(user);
}
// 3. 批量ID查询
@Test
void testSelectBatchIds() {
List<UserInfo> users = userInfoMapper.selectBatchIds(List.of(1,2,3,4));
users.forEach(System.out::println);
}
// 4. 根据ID更新
@Test
void testUpdateById() {
UserInfo user = new UserInfo();
user.setId(1);
user.setPassword("4444444");
userInfoMapper.updateById(user);
}
// 5. 根据ID删除
@Test
void testDeleteById() {
userInfoMapper.deleteById(5);
}
}
@SpringBootTest 必须要有 , 否则报空指针

users.forEach(System.out::println)=
users.forEach(user -> System.out.println(user))=
for (UserInfo user : users) { System.out.println(user); }
3.Mybatis-Plus 复杂操作
3.1 常见注解
MyBatis-Plus会根据这个实体类来推断表的信息.
默认情况下:
- 表名:实体类的驼峰表示法转换成蛇形表示法,以下划线分割,作为表名。例如 UserInfo 转为 user_info
- 字段:根据实体类的属性名转换为蛇形表示法作为字段名。例如 deleteFlag 转为 delete_flag
- 主键:默认为 id
当命名不规范时,Mybatis-Plus 提供了能够表示表信息的注解
数据库字段

① @TableName

命名不规范此类名对应的是 userinfo 表名 ; 正确的是 user_info

用注解 @TableName("user_info") 可以标识实体类对应的表名
java
@Data
@TableName("user_info")
public class Userinfo {
private Integer id;
private String username;
private String password;
private Integer age;
private Integer gender;
private String phone;
private Integer deleteflag;
private Date createTime;
private Date updateTime;
}
运行程序, 结果正常
java
@Test
void testInsert() {
Userinfo user = new Userinfo();
user.setUsername("bite");
user.setPassword("123456");
user.setAge(11);
user.setGender(0);
user.setPhone("18610001234");
user.setDeleteflag(1);
userInfoMapper.insert(user);
}
② @TableField

命名不规范此属性对应的字段为 deleteflag ; 正确的是 delete_flage

用@TableField("delete_flag") , 表示属性名对应的字段名
注意 : 演示时注意 Getter(),Setter()方法也要跟着变
java
@Data
@TableName("user_info")
public class Userinfo {
private Integer id;
private String username;
private String password;
private Integer age;
private Integer gender;
private String phone;
@TableField("delete_flag")
private Integer deleteflag;
private Date createTime;
private Date updateTime;
}
测试代码
java
@Test
void testInsert() {
Userinfo user = new Userinfo();
user.setUsername("bite");
user.setPassword("123456");
user.setAge(11);
user.setGender(0);
user.setPhone("18610001234");
user.setDeleteflag(1);
userInfoMapper.insert(user);
}
③ @TableId

命名不规范
java
@Data
@TableName("user_info")
public class Userinfo {
@TableId(value = "id", type = IdType.AUTO)
private Integer userid;
private String username;
private String password;
private Integer age;
private Integer gender;
private String phone;
@TableField("delete_flag")
private Integer deleteflag;
private Date createTime;
private Date updateTime;
}
@TableId(value ="id", type =IdType.AUTO) , 属性名和字段名不一致 , 需要在 注解中表明对应的字段名 (选择性加入自增主键)
如果属性名和字段名一致 , 则直接加@TableId 注解即可
3.2 条件构造器

|-------------------------|--------------------|-----------------------------------------------------------|
| 类名 | 核心用途 | 特点 |
| AbstractWrapper | 所有条件构造器的抽象父类 | 封装了所有通用条件方法(eq、ne、gt、lt、like、in等),是其他 4 个类的基础 |
| QueryWrapper | 构建查询条件(SELECT语句) | 支持链式调用,可指定查询字段、过滤条件、排序、分组等 |
| UpdateWrapper | 构建更新条件(UPDATE语句) | 可同时指定更新字段和更新条件,无需额外创建实体对象 |
| LambdaQueryWrapper | 基于 Lambda 的查询构造器 | 通过 实体类::getter引用字段,避免硬编码字段名,降低写错字段名的风险 |
| LambdaUpdateWrapper | 基于 Lambda 的更新构造器 | 通过 实体类::setter或 实体类::getter引用字段,避免编码,类型安全 |
① 通用条件方法(所有 Wrapper 通用)
|--------------------------|----------------------------|-------------------------|
| 方法 | 作用 | 对应 SQL |
| eq("name", "张三") | equal 等于 | name = '张三' |
| ne("age", 18) | not equal 不等于 | age <> 18 |
| gt("age", 18) | greater than 大于 | age > 18 |
| lt("age", 18) | less than 小于 | age < 18 |
| ge("age", 18) | greater than or equal 大于等于 | age >= 18 |
| le("age", 18) | less than or equal 小于等于 | age <= 18 |
| like("name", "张") | like 模糊查询 | name LIKE '%张%' |
| in("id", 1,2,3) | IN 查询 | id IN (1,2,3) |
| between("age", 18, 30) | 区间查询 | age BETWEEN 18 AND 30 |
| orderByDesc("age") | 降序排序 | ORDER BY age DESC |
| orderByAsc("age") | 升序排序 | ORDER BY age ASC |
② QueryWrapper 和 LambdaQueryWrapper 示例
java
//
@Test
void testQueryWrapper(){
//使用QueryWrapper
QueryWrapper<Userinfo> userinfoQueryWrapper = new QueryWrapper<Userinfo>()
.select("id", "username", "age")
.eq("age", 18)
.like("username", "张");
List<Userinfo> userinfos1 = userInfoMapper.selectList(userinfoQueryWrapper);
userinfos1.forEach(System.out::println);
//使用LambdaQueryWrapper (防止字段名硬编码,字段名不会写错)
LambdaQueryWrapper<Userinfo> userinfoLambdaQueryWrapper = new LambdaQueryWrapper<Userinfo>()
.select(Userinfo::getUserid,Userinfo::getUsername,Userinfo::getAge)
.gt(Userinfo::getAge,18)
.like(Userinfo::getUsername,"张");
List<Userinfo> userinfos2 = userInfoMapper.selectList(userinfoLambdaQueryWrapper);
userinfos2.forEach(System.out::println);
}
对应 SQL
sql
SELECT userid,username,age
FROM userinfo
WHERE age = 18
AND username
LIKE '%张%'
sql
SELECT userid,username,age
FROM userinfo
WHERE age > 18
AND username
LIKE '%张%'
注意 :

在变量声明时写了泛型 <Userinfo>,但 new QueryWrapper<>() 时,Java 类型推断没有正确识别泛型类型,而是推断成了 Object,导致前后类型不匹配
③ UpdateWrapper 和 LambdaUpdateWrapper 示例
java
// 7. UpdateWrapper 和 LambdaUpdateWrapper 示例
@Test
void testUpdateWrapper(){
//使用UpdateWrapper
UpdateWrapper<Userinfo> updateWrapper = new UpdateWrapper<Userinfo>();
updateWrapper.set("username","张三").set("update_time", LocalDateTime.now())
.eq("age",18);
// 第一个参数 null:表示不通过实体类传值,只使用 UpdateWrapper 里的 set 值
// 第二个参数 updateWrapper:更新的字段 + 条件
int count1 = userInfoMapper.update(null,updateWrapper);
//使用LambdaUpdateWrapper
LambdaUpdateWrapper<Userinfo> userinfoLambdaUpdateWrapper = new LambdaUpdateWrapper<Userinfo>()
.set(Userinfo::getUsername,"张三")
.set(Userinfo::getUpdateTime,LocalDateTime.now())
.eq(Userinfo::getAge,18);
int count2 = userInfoMapper.update(null,updateWrapper);
}
对应 SQL
sql
SELECT id, username, age
FROM userinfo
WHERE age = 18
AND username
LIKE '%张%'
总结 :
LambdaUpdateWrapper 和 LambdaQueryWrapper 是基于 Lambda 表达式的条件构造器 , 通过 Lambda 表达式来应用实体类的属性 , 从而避免因为命名不规范或字段名不匹配产生的硬编码问题 , 提高了代码的可读性
④ 自定义 SQL(此处演示的为注解+Wrapper)
MyBatis-Plus 提供了自定义 SQL 的功能 , 可以利用 Wrapper 构造查询条件 , 再结合 Wrapper 编写 SQL
注意 :

编写 Mapper
java
@Mapper
public interface UserInfoMapper extends BaseMapper<Userinfo> {
@Select("select id,username,password,age from user_info ${ew.customSqlSegment}")
List<Userinfo> queryUserByCustom(@Param(Constants.WRAPPER)Wrapper<Userinfo> wrapper);
}
编写测试代码
java
// 8.自定义Mybatis-Plus 的SQL
@Test
void queryUserByCustom(){
QueryWrapper<Userinfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username","admin");
userInfoMapper.queryUserByCustom(queryWrapper).forEach(System.out::println);
}
最终 SQL : select id,username,password,age FROM user_info WHERE username = 'admin'
原理 :
必须继承 BaseMapper 通用 CRUD
需要自己写 select....from....部分 , 实现自定义字段 , 多表联查等需求
必须通过{ew.customSqlSegment} 让 Mapper 自动拼接 Wrapper 里的 where 条件 ; 支持所有条件方法 ; **注意是{}**
必须用@Param(Constants.WRAPPER) 作用 : 告诉 Mybatis , 这个是 Wrapper 对象 , 在 SQL 中用${ew.xxx}来引用 (如果不写注解 , 则找不到引用对象)
注意 :不要引错包名 , 正确包名 : import com.baomidou.mybatisplus.core.conditions.Wrapper
${ew.xxx}必须写在 from 表名之后
以下均为示例片段 , 没有做准备
支持多表联查(需要配置多表环境)
java
@Select("SELECT u.*, d.dept_name "
+ "FROM user_info u "
+ "LEFT JOIN dept d ON u.dept_id = d.id "
+ "${ew.customSqlSegment}")
List<UserVO> selectUserWithDept(@Param(Constants.WRAPPER)Wrapper<UserInfo> wrapper);
支持 Lambda
java
@Test
void testLambdaQuery(){
LambdaQueryWrapper<UserInfo> wrapper = newLambdaQueryWrapper<>();
wrapper.eq(UserInfo::getUsername,"admin")
.ge(UserInfo::getAge,18);
userInfoMapper.queryUserByCustom(wrapper).forEach(System.out::println);}
支持 Mapper.xml+Wrapper
https://www.yuque.com/u29274559/wwxtlt/hkx9urdliqy551tv
vb
`<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mappernamespace="com.bite.mybatis.plus.mapper.UserInfoMapper">
<selectid="queryUserByCustom2">
select id,username,password,age FROM user_info ${ew.customSqlSegment}
</select>
</mapper>`