目录
[4. 条件构造器 Wrapper](#4. 条件构造器 Wrapper)
[4.1 QueryWrapper](#4.1 QueryWrapper)
[4.2 UpdateWrapper](#4.2 UpdateWrapper)
[基于 SQL 更新](#基于 SQL 更新)
[4.3 LambdaQueryWrapper](#4.3 LambdaQueryWrapper)
[4.4 LambdaUpdateWrapper](#4.4 LambdaUpdateWrapper)
[5. 自定义 SQL](#5. 自定义 SQL)
[5.1 注解方式](#5.1 注解方式)
[5.2 XML 方式](#5.2 XML 方式)
[配置 mapper 路径](#配置 mapper 路径)
[5.3 自定义更新 SQL](#5.3 自定义更新 SQL)
4. 条件构造器 Wrapper
简单 CRUD 无法满足复杂查询。MyBatis-Plus 提供了强大的条件构造器 Wrapper,支持链式调用构建查询条件,减少手写 SQL,并降低 SQL 注入风险。
主要 Wrapper:
-
AbstractWrapper:抽象基类,提供通用方法和属性。 -
QueryWrapper:构造查询条件,扩展了 **select**方法,可指定查询字段。 -
UpdateWrapper:构造更新条件,可在更新数据时指定条件。 -
LambdaQueryWrapper:基于 Lambda表达式的查询条件构造器,避免硬编码字段名。 -
LambdaUpdateWrapper:基于 Lambda 表达式的更新条件构造器。
4.1 QueryWrapper
**QueryWrapper**不仅用于查询,也可用于修改、删除等场景构建条件。
查询
目标 SQL:
java
SELECT id, username, password, age
FROM user_info
WHERE age = 18 AND username LIKE '%min%';
测试代码:
java
@Test
void testQueryWrapper() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>()
.select("id", "username", "password", "age")
.eq("age", 18)
.like("username", "min");
List<UserInfo> userInfos = userInfoMapper.selectList(queryWrapper);
userInfos.forEach(System.out::println);
}
注意:
默认情况下,MyBatis-Plus 会根据 @TableField 生成别名。当指定了 QueryWrapper 的 select 字段后,查询结果可能没有别名,导致映射不上。
解决办法:
-
自己写自定义 SQL。
-
实体类名和字段名保持一致。
-
不指定
QueryWrapper的 **select**字段。 -
使用
LambdaQueryWrapper。
更新(Update)
目标 SQL:
java
UPDATE user_info SET delete_flag = ? WHERE age < 20;
测试代码:
java
@Test
void testUpdateByQueryWrapper() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>()
.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:
java
DELETE FROM user_info WHERE age = 18;
测试代码:
java
@Test
void testDeleteByQueryWrapper() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>()
.eq("age", 18);
userInfoMapper.delete(queryWrapper);
}
4.2 UpdateWrapper
对于更新,可以直接使用 UpdateWrapper,在不创建实体对象的情况下设置更新字段和条件。
基础更新
目标 SQL:
java
UPDATE user_info
SET delete_flag = 0, age = 5
WHERE id IN (1, 2, 3);
测试代码:
java
@Test
void testUpdateByUpdateWrapper() {
UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>()
.set("delete_flag", 0)
.set("age", 5)
.in("id", List.of(1, 2, 3));
userInfoMapper.update(updateWrapper);
}
基于 SQL 更新
目标 SQL:
java
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(updateWrapper);
}
4.3 LambdaQueryWrapper
QueryWrapper 和 **UpdateWrapper**需要写死字段名。如果字段名变更,可能引发事故。MyBatis-Plus 提供了基于 Lambda 表达式的条件构造器,避免硬编码字段名,提高可读性和可维护性。
java
@Test
void testLambdaQueryWrapper() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda()
.select(UserInfo::getUsername, UserInfo::getPassword, UserInfo::getAge)
.eq(UserInfo::getUserId, 1);
userInfoMapper.selectList(queryWrapper).forEach(System.out::println);
}
如果主键属性名为 id ,则使用 UserInfo::getId。
4.4 LambdaUpdateWrapper
LambdaUpdateWrapper 用法与 LambdaQueryWrapper 类似:
java
@Test
void testLambdUpdateByUpdateWrapper() {
UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<>();
updateWrapper.lambda()
.set(UserInfo::getDeleteFlag, 0)
.set(UserInfo::getAge, 5)
.in(UserInfo::getUserId, List.of(1, 2, 3));
userInfoMapper.update(updateWrapper);
}
5. 自定义 SQL
实际开发中,MyBatis-Plus 提供的操作不一定能满足所有需求。MyBatis-Plus 支持自定义 SQL,可以结合 Wrapper 构造查询条件,再通过 Mapper 编写 SQL。
使用该功能时,MyBatis-Plus 版本不低于 3.0.7。
5.1 注解方式
目标 SQL:
java
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);
}
注意事项:
-
参数命名:传递 Wrapper 对象作为参数时,参数名必须为
ew,或者使用@Param(Constants.WRAPPER)明确指定。 -
使用
${ew.customSqlSegment}:在 SQL 中引用 Wrapper 生成的 SQL 片段。 -
不支持基于 entity 的 where 语句:自定义 SQL 时,Wrapper 不会基于实体类自动生成 where 子句,需要手动编写完整 SQL。
5.2 XML 方式
MyBatis-Plus 在 MyBatis 基础上只做增强,因此也支持 XML 方式。
配置 mapper 路径
java
mybatis-plus:
mapper-locations: "classpath*:/mapper/**.xml"
定义方法:
java
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
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">
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);
}
5.3 自定义更新 SQL
目标 SQL:
java
UPDATE user_info
SET age = age + 10
WHERE id IN (1, 2, 3);
Mapper:
java
@Update("UPDATE user_info SET age = age + #{addAge} ${ew.customSqlSegment}")
void updateUserByCustom(@Param("addAge") int addAge,
@Param("ew") Wrapper<UserInfo> wrapper);
测试代码:
java
@Test
void updateUserByCustom() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>()
.in("id", List.of(1, 2, 3));
userInfoMapper.updateUserByCustom(10, queryWrapper);
}
附:常用条件方法速查
| 方法 | 含义 |
|---|---|
eq |
等于 |
ne |
不等于 |
gt |
大于 |
ge |
大于等于 |
lt |
小于 |
le |
小于等于 |
like |
模糊查询 |
in |
IN 查询 |
set |
设置更新字段 |
setSql |
使用 SQL 片段更新 |
select |
指定查询字段 |
