MyBatis-Plus 实战指南:从基础 CRUD 到条件构造器与自定义 SQL(二)

目录

​编辑

[4. 条件构造器 Wrapper](#4. 条件构造器 Wrapper)

[4.1 QueryWrapper](#4.1 QueryWrapper)

查询

更新(Update)

删除

[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 字段后,查询结果可能没有别名,导致映射不上。

解决办法:

  1. 自己写自定义 SQL。

  2. 实体类名和字段名保持一致。

  3. 不指定 QueryWrapper 的 **select**字段。

  4. 使用 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 指定查询字段
相关推荐
凤凰院凶涛QAQ几秒前
《MySQL内核拆解:从SQL到InnoDB》(四) : 联合查询 & 视图
数据库·sql·mysql
码农小河668 分钟前
基于SSM+JSP的高校专业信息管理系统【附源码+数据库】
java·开发语言·数据库
张小姐的猫12 分钟前
【MySQL】访问 & 数据流动原理
android·数据库·mysql·adb·1024程序员节
这个DBA有点耶4 小时前
信创场景下数据同步软件怎么选?对比开源CDC与原生闭环工具的结构性差异
数据库·mysql·架构
多客:duokelijie5 小时前
代练订单系统选型思路:跨品类游戏接入、订单分层管理、自动结算逻辑拆解!
数据库·mysql·微信小程序·前端框架·uni-app·php·持续部署
PingCAP5 小时前
平凯星辰上榜!2026 年胡润全球独角兽企业
数据库
PingCAP5 小时前
轨道交通 AFC 系统升级,平凯 Loop 把跨部门协同变成可追溯闭环
数据库
java_logo6 小时前
Docker 部署 CloudBeaver:轻松搭建网页数据库管理平台
数据库·docker·容器·数据库管理·dbeaver·轩辕镜像·cloudbeaver
李白客7 小时前
AI 数据库落地 NL2SQL:准确率卡在四成,问题在表注释不在模型
数据库