简介

MyBatis-Plus (简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

1快速入门

1.1 基本步骤

引入mybatis-plus-boot-starter依赖:

1
2
3
4
5
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>最新版本</version>
</dependency>

定义Mapper接口并继承BaseMapper:

1
2
3
public interface UserMapper extends BaseMapper<User> {

}

1.2 定义Mapper

为了简化单表CRUD,MybatisPlus提供了一个基础的BaseMapper接口,其中已经实现了单表的CRUD:
20250709155511
因此我们自定义的Mapper只要继承了这个BaseMapper,就无需自己实现单表CRUD了。

2 常见注解

MybatisPlus中比较常用的几个注解如下:

  • @TableName: 用于指定表名
  • @Tabled: 用于指定表中的主键字段信息
  • @TableField: 用于指定表中的普通字段信息
1
2
3
4
5
6
7
8
9
@TableName("sys_user")
public class User {
@TableId("id",type=IdType.AUTO)
private Long id;
@TableField("nickname")
private String name;
private Integer age;
private String email;
}

2.1 @TableName

TableName注解除了指定表名以外,还可以指定很多其它属性:
20250709155749

2.2 @TableId

TableId注解支持两个属性:
20250709155858

IdType支持的类型有:
20250709160228

这里比较常见的有三种:

  • AUTO: 利用数据库的id自增长
  • INPUT: 手动生成id
  • ASSIGN_ID: 雪花算法生成Long类型的全局唯一id,这是默认的ID策略

2.3 @TableField

一般情况下我们并不需要给字段添加@TableField注解,一些特殊情况除外:

  • 成员变量名与数据库字段名不一致
  • 成员变量是以isXXX命名,按照JavaBean的规范,MybatisPlus识别字段时会把is去除,这就导致与数据库不符。
  • 成员变量名与数据库一致,但是与数据库的关键字冲突。使用@TableField注解给字段名添加转义字符:``

支持的其它属性如下:
20250709160448

3 常见配置

大多数的配置都有默认值,因此我们都无需配置。但还有一些是没有默认值的,例如:

  • 实体类的别名扫描包
  • 全局id类型
1
2
3
4
5
mybatis-plus:
type-aliases-package: com.itheima.mp.domain.po
global-config:
db-config:
id-type: auto # 全局id类型为自增长

需要注意的是,MyBatisPlus也支持手写SQL的,而mapper文件的读取地址可以自己配置:

1
2
mybatis-plus:
mapper-locations: "classpath*:/mapper/**/*.xml" # Mapper.xml文件地址,当前这个是默认值。

4 核心功能

4.1 条件构造器

除了新增以外,修改、删除、查询的SQL语句都需要指定where条件。因此BaseMapper中提供的相关方法除了以id作为where条件以外,还支持更加复杂的where条件。

20250709162157

参数中的Wrapper就是条件构造的抽象类,其下有很多默认实现,继承关系如图:

20250709162220

Wrapper的子类AbstractWrapper提供了where中包含的所有条件构造方法:

20250709162243

4.1.1 QueryWrapper

QueryWrapper在AbstractWrapper的基础上拓展了一个select方法,允许指定查询字段:

20250709162311

无论是修改、删除、查询,都可以使用QueryWrapper来构建查询条件。接下来看一个例子:

1
2
3
4
5
6
7
8
9
10
11
@Test
void testQueryWrapper() {
// 1.构建查询条件 where name like "%o%" AND balance >= 1000
QueryWrapper<User> wrapper = new QueryWrapper<User>()
.select("id", "username", "info", "balance")
.like("username", "o")
.ge("balance", 1000);
// 2.查询数据
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}

4.1.2 UpdateWrapper

UpdateWrapperAbstractWrapper的基础上拓展了一个set方法,允许指定SQL中的SET部分:
20250709163917

基于BaseMapper中的update方法更新时只能直接赋值,对于一些复杂的需求就难以实现。
例如:更新id为1,2,4的用户的余额,扣200,对应的SQL应该是:

1
UPDATE user SET balance = balance - 200 WHERE id in (1, 2, 4)

SET的赋值结果是基于字段现有值的,这个时候就要利用UpdateWrapper中的setSql功能了:

1
2
3
4
5
6
7
8
9
10
11
@Test
void testUpdateWrapper() {
List<Long> ids = List.of(1L, 2L, 4L);
// 1.生成SQL
UpdateWrapper<User> wrapper = new UpdateWrapper<User>()
.setSql("balance = balance - 200") // SET balance = balance - 200
.in("id", ids); // WHERE id in (1, 2, 4)
// 2.更新,注意第一个参数可以给null,也就是不填更新字段和数据,
// 而是基于UpdateWrapper中的setSQL来更新
userMapper.update(null, wrapper);
}

4.1.3 4.1.3.LambdaQueryWrapper

无论是QueryWrapper还是UpdateWrapper在构造条件的时候都需要写死字段名称,会出现字符串魔法值。这在编程规范中显然是不推荐的。
那怎么样才能不写字段名,又能知道字段名呢?

其中一种办法是基于变量的gettter方法结合反射技术。因此我们只要将条件对应的字段的getter方法传递给MybatisPlus,它就能计算出对应的变量名了。而传递方法可以使用JDK8中的方法引用和Lambda表达式。
因此MybatisPlus又提供了一套基于LambdaWrapper,包含两个:

  • LambdaQueryWrapper
  • LambdaUpdateWrapper
    分别对应QueryWrapperUpdateWrapper其使用方式如下:
1
2
3
4
5
6
7
8
9
10
11
12
@Test
void testLambdaQueryWrapper() {
// 1.构建条件 WHERE username LIKE "%o%" AND balance >= 1000
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.lambda()
.select(User::getId, User::getUsername, User::getInfo, User::getBalance)
.like(User::getUsername, "o")
.ge(User::getBalance, 1000);
// 2.查询
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}

4.2 自定义SQL

MybatisPlus提供了自定义SQL功能,可以让我们利用Wrapper生成查询条件,再结合Mapper.xml编写SQL

1
2
3
4
5
6
7
8
9
@Test
void testCustomWrapper() {
// 1.准备自定义查询条件
List<Long> ids = List.of(1L, 2L, 4L);
QueryWrapper<User> wrapper = new QueryWrapper<User>().in("id", ids);

// 2.调用mapper的自定义方法,直接传递Wrapper
userMapper.deductBalanceByIds(200, wrapper);
}

然后在UserMapper中自定义SQL:

1
2
3
4
5
6
7
8
9
10
11
12
package com.itheima.mp.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.mp.domain.po.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.Param;

public interface UserMapper extends BaseMapper<User> {
@Select("UPDATE user SET balance = balance - #{money} ${ew.customSqlSegment}")
void deductBalanceByIds(@Param("money") int money, @Param("ew") QueryWrapper<User> wrapper);
}

5 Service接口

MybatisPlus不仅提供了BaseMapper,还提供了通用的Service接口及默认实现,封装了一些常用的service模板方法。
通用接口为IService,默认实现为ServiceImpl,其中封装的方法可以分为以下几类:

  • save:新增
  • remove:删除
  • update:更新
  • get:查询单个结果
  • list:查询集合结果
  • count:计数
  • page:分页查询

5.1 CRUD

我们先俩看下基本的CRUD接口。
新增:
20250709164628

  • save是新增单个元素
  • saveBatch是批量新增
  • saveOrUpdate是根据id判断,如果数据存在就更新,不存在则新增
  • saveOrUpdateBatch是批量的新增或修改

删除:
20250709164721

  • removeById:根据id删除
  • removeByIds:根据id批量删除
  • removeByMap:根据Map中的键值对为条件删除
  • remove(Wrapper):根据Wrapper条件删除

Get:
20250709164749

List:

20250709164804