文章目录
-
- 一、MyBatis-Plus介绍
- [二、MyBatis-Plus 入门使用](#二、MyBatis-Plus 入门使用)
-
- [2.1 依赖引入与配置](#2.1 依赖引入与配置)
- [2.2 入门使用](#2.2 入门使用)
- 三、MyBatis-Plus复杂操作
-
- [3.1 注解配置](#3.1 注解配置)
-
- [3.1.1 @TableName](#3.1.1 @TableName)
- [3.1.2 @TableField](#3.1.2 @TableField)
- [3.1.3 @TableId](#3.1.3 @TableId)
- [3.2 打印日志](#3.2 打印日志)
- [3.3 条件构造器](#3.3 条件构造器)
-
- [3.3.1 QueryWrapper](#3.3.1 QueryWrapper)
- [3.3.2 UpdateWrapper](#3.3.2 UpdateWrapper)
- [3.3.3 LambdaQueryWrapper](#3.3.3 LambdaQueryWrapper)
- [3.3.4 LambdaUpdateWrapper](#3.3.4 LambdaUpdateWrapper)
- [3.4 自定义SQL](#3.4 自定义SQL)

一、MyBatis-Plus介绍
MyBatis-Plus(简称 MP) 是一个 MyBatis 的增强工具, 在 MyBatis 的基础上只做增强不做改变, 为简化开发、提高效率而生。
特性
- 润物无声: 只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。
- 效率至上: 只需简单配置,即可快速进行单表 CRUD 操作,从而节省大量时间。
- 丰富功能: 代码生成、自动分页、逻辑删除、自动填充、拦截器等功能一应俱全。
- 广泛认可: 连续 5 年获得开源中国年度最佳开源项目殊荣,Github 累计 16K Star。
支持数据库
PostgreSQL, MySQL, MariaDB, Oracle, SQL Server, OceanBase, H2, DB2...
(任何能使用 MyBatis 进行增删改查,并且支持标准 SQL 的数据库应该都在 MyBatis-Plus 的支持范围内)
官网地址:Mybatis-Plus 简化开发
二、MyBatis-Plus 入门使用
Mybatis-Plus操作数据库的步骤:
2.1 依赖引入与配置
- 创建springboot工程
- 添加MyBatis-Plus和MySQL依赖, 配置数据库连接信息
Spring Boot2依赖:
xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.7</version>
</dependency>
Spring Boot3依赖:
xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.5</version>
</dependency>
MySQL依赖:
xml
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
配置数据库(application.yml文件):
yaml
# 数据库连接配置
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
配置数据库(application.properties文件):
properties
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=root
2.2 入门使用
-
创建实体类,实体类的属性名与表中的字段名一一对应:
-
编写Mapper接口类
MybatisPlus提供了一个基础的BaseMapper 接口,已经实现了单表的CRUD,自定义的 Mapper只需要继承这个BaseMapper,就无需自己实现单表CRUD了。
BaseMapper包含了很多方法,示例:

Mapper接口代码:
java
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
}
也可以在启动类上添加 @MapperScan ,扫描Mapper文件夹,如下:(二选一即可)

- CRUD单元测试
在创建出来的SpringBoot工程中,在src下的test目录下,创建测试类,可以直接使用这个测试类来进行测试。
编写单元测试,测试基本的CRUD功能:
java
@SpringBootTest
class MybatisPlusDemoApplicationTests {
@Autowired
private UserInfoMapper userInfoMapper;
@Test
public void testSelect() {
System.out.println(("----- selectAll method test ------"));
List<UserInfo> userList = userInfoMapper.selectList(null);
userList.forEach(System.out::println);
}
}
运行结果如下:

三、MyBatis-Plus复杂操作
3.1 注解配置
MyBatis是如何知道,我们要操作的是哪张表,表里有哪些字段呢?
java
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
}
UserInfoMapper 在继承BaseMapper 时, 指定了一个泛型, 这个UserInfo就是与数据库表相对应的实体类。MyBatis-Plus会根据这个实体类来推断表的信息。
默认情况下:
- 表名: 实体类的驼峰表示法转换成蛇形表示法(下划线分割), 作为表名。比如UserInfo -> user_info
- 字段: 根据实体类的属性名转换为蛇形表示法作为字段名。比如deleteFlag -> delete_flag
- 主键: 默认为id
如果实体类和数据库不是按照上述规则定义。MyBatis-Plus也给我们提供了一些注解,用来标识表的信息。
3.1.1 @TableName
该注解用于指定实体类对应的数据库表名。当实体类名与数据库表名不一致,或者实体类名不是数据库表名的驼峰写法时,可以使用这个注解来明确指定表名。
示例:
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;
}
3.1.2 @TableField
该注解用于标记实体类中的非主键字段,它告诉 MyBatis-Plus 如何映射实体类字段到数据库表字段。如果实体类字段名遵循驼峰命名规则,并且与数据库表字段名一致,可以省略这个注解。
示例:
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;
}
3.1.3 @TableId
该注解用于标记实体类中的主键字段。如果你的主键字段名为 id,可以省略这个注解。
示例:
java
@Data
@TableName("user_info")
public class Userinfo {
@TableId("id")
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 指明对应的字段名;属性名和字段一致的情况下, 直接加@TableId 注解就可以。
@TableId 参数介绍:
-
value
类型 :String
默认值 :""
描述:指定数据库表的主键字段名。如果不设置,MyBatis-Plus 将使用实体类中的字段名作为数据库表的主键字段名。 -
type
类型 :Enum
默认值 :IdType.NONE
描述:指定主键的生成策略。
IdType 枚举类型定义
- IdType.AUTO:使用数据库自增 ID 作为主键。
- IdType.NONE:无特定生成策略,如果全局配置中有 IdType 相关的配置,则会跟随全局配置。
- IdType.INPUT:在插入数据前,由用户自行设置主键值。
- IdType.ASSIGN_ID:自动分配 ID,适用于 Long、Integer、String 类型的主键。默认使用雪花算法通过 IdentifierGenerator 的 nextId 实现。
- IdType.ASSIGN_UUID:自动分配 UUID,适用于 String 类型的主键。默认实现为 IdentifierGenerator 的 nextUUID 方法。
详情参考网址:注解配置
3.2 打印日志
Mybatis-Plus配置日志如下(application.yml):
yaml
mybatis-plus:
configuration: # 配置打印 MyBatis日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
3.3 条件构造器
MyBatis-Plus 提供了一套强大的条件构造器(Wrapper), 用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件, 无需编写繁琐的 SQL 语句, 从而提高开发效率并减少 SQL 注入的风险。
以下是主要的 Wrapper 类及其功能:
- AbstractWrapper:这是一个抽象基类, 提供了所有 Wrapper 类共有的方法和属性。详细参考官网介绍: 条件构造器
- QueryWrapper:用于构造查询条件, 在AbstractWrapper的基础上拓展了一个select方法, 允许指定查询字段。
- UpdateWrapper:用于构造更新条件, 可以在更新数据时指定条件。
- LambdaQueryWrapper:基于 Lambda 表达式的查询条件构造器, 它通过 Lambda 表达式来引用实体类的属性,从而避免了硬编码字段名。
- LambdaUpdateWrapper:基于 Lambda 表达式的更新条件构造器, 它允许你使用 Lambda 表达式来指定更新字段和条件,同样避免了硬编码字段名的问题。
3.3.1 QueryWrapper
QueryWrapper并不只用于查询语句, 无论是修改, 删除, 查询, 都可以使用QueryWrapper来构建查询条件。
- 查询
完成SQL:
sql
SELECT id,username,password,age FROM user_info WHERE age = 18 AND username LIKE "%min%"
测试代码:
java
@Test
@Test
void testQueryWrapper(){
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.select("id","username","password","age")
.eq("age",18)
.like("username","min");
List<UserInfo> userInfos = userInfoMapper.selectList(queryWrapper);
userInfos.forEach(System.out::println);
}
- 更新
完成SQL:
sql
UPDATE user_info SET delete_flag=? WHERE age < 20
测试代码:
java
@Test
@Test
void testUpdateByQueryWrapper(){
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.lt("age",20);
UserInfo userInfo = new UserInfo();
userInfo.setDeleteFlag(1);
userInfoMapper.update(userInfo,queryWrapper);
}
条件方法说明:
- lt : "less than" 的缩写,表示小于
- le : "less than or equal to"的缩写, 表示小于等于
- ge : "greater than or equal to" 的缩写, 表示大于等于
- gt : "greater than" 的缩写, 表示大于
- eq : "equals" 的缩写, 表示等于
- ne : "not equals" 的缩写, 表示不等于
- 删除
完成SQL:
sql
DELETE FROM user_info WHERE age = 18
测试代码:
java
@Test
void testDeleteByQueryWrapper(){
QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<UserInfo>()
.eq("age",18);
userInfoMapper.delete(userInfoQueryWrapper);
}
3.3.2 UpdateWrapper
对于更新,也可以直接使用 UpdateWrapper,在不创建实体对象的情况下,直接设置更新字段和条件。
- 基础更新
完成SQL:
sql
UPDATE user_info SET delete_flag=0, age=5 WHERE id IN (1,2,3)
测试代码:
java
@Test
void testUpdateWrapper(){
UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<>();
updateWrapper.set("delete_flag",1).set("age",5).in("id",List.of(2,3,5,8));
userInfoMapper.update(updateWrapper);
}
- 基于SQL更新
完成SQL:
sql
UPDATE user_info SET age = age+10 WHERE id IN (1,2,3)
测试代码:
java
@Test
void testUpdateBySQLUpdateWrapper(){
UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>()
.setSql("age = age+10")
.in("id", List.of(1,2,3));
userInfoMapper.update(null, updateWrapper);
}
3.3.3 LambdaQueryWrapper
QueryWrapper 和 UpdateWrapper存在一个问题, 就是需要写死字段名, 如果字段名发生变更, 可能会因为测试不到位酿成事故。
MyBatis-Plus 提供了一种基于Lambda表达式的条件构造器, 它通过 Lambda 表达式来引用实体类的属性,从而避免了硬编码字段名,也提高了代码的可读性和可维护性。
- LambdaQueryWrapper
- LambdaUpdateWrapper
分别对应上述的QueryWrapper和UpdateWrapper。
java
@Test
void testLambdaQueryWrapper(){
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.lambda()
.select(UserInfo::getUsername, UserInfo::getPassword,UserInfo::getAge)
.eq(UserInfo::getId, 1);
userInfoMapper.selectList(queryWrapper).forEach(System.out::println);
}
3.3.4 LambdaUpdateWrapper
LambdaUpdateWrapper用法和 LambdaQueryWrapper相似:
java
@Test
void testLambdaUpdateByUpdateWrapper(){
UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>();
updateWrapper.lambda()
.set(UserInfo::getDeleteFlag, 0)
.set(UserInfo::getAge, 5)
.in(UserInfo::getId, List.of(1,2,3));
userInfoMapper.update(null, updateWrapper);
}
3.4 自定义SQL
在实际的开发中, MyBatis-Plus提供的操作不能满足所有的实际需求, MyBatis-Plus 也提供了自定义 SQL的功能, 可以利用Wrapper构造查询条件, 再结合Mapper编写SQL。
- 注:为了使用这一功能, mybatis-plus 版本不低于 3.0.7。
代码示例1
完成下述SQL查询:
sql
select id,username,password,age FROM user_info WHERE username = "admin"
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
@Test
void testQueryUserByCustom(){
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>()
.eq("username","admin");
userInfoMapper.queryUserByCustom(queryWrapper).forEach(System.out::println);
}
注意:
- 参数命名:在自定义 SQL 时, 传递 Wrapper 对象作为参数时, 参数名必须为 ew ,或者使用注解 @Param(Constants.WRAPPER) 明确指定参数为 Wrapper 对象。
- 使用
${ew.customSqlSegment}:在 SQL 语句中,使用${ew.customSqlSegment}来引用 Wrapper 对象生成的 SQL 片段。 - 不支持基于 entity 的 where 语句:自定义 SQL 时,Wrapper 对象不会基于实体类自动生成 where 子句,你需要手动编写完整的 SQL 语句。
代码示例2
MyBatis-Plus 在 MyBatis 的基础上只做增强不做改变, 所以也支持XML的实现方式。上述功能也可以使用XML的方式完成。
配置mapper路径(application.yml):
yaml
mybatis-plus:
mapper-locations: "classpath*:/mapper/**.xml" # Mapper.xml
Mapper:
java
List<UserInfo> queryUserByCustom2(@Param(Constants.WRAPPER) Wrapper<UserInfo> wrapper);
编写XML:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bite.mybatis.plus.mapper.UserInfoMapper">
<select id="queryUserByCustom2" resultType="com.bite.mybatis.plus.entity.UserInfo">
select id,username,password,age FROM user_info ${ew.customSqlSegment}
</select>
</mapper>
测试:
java
@Test
void testQueryUserByCustom2(){
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>()
.eq("username","admin");
userInfoMapper.queryUserByCustom2(queryWrapper).forEach(System.out::println);
}