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 指定查询字段
相关推荐
小小AK1 小时前
销售订单从 CRM 推到 ERP:一条策略的完整同步实战
数据库
木雷坞1 小时前
Docker Compose部署Docmost:数据库、附件持久化与首次协作
数据库·docker·容器
VidDown1 小时前
上线三个月后的第一次事故:一个 Django 服务的日志、监控与故障复盘
数据库·python·django·wpf·音视频·视频编解码
小蒜学长1 小时前
基于Springboot+Vue的高校教师教学业绩综合管理系统的设计与开发(代码+数据库+LW)
java·数据库·spring boot·后端·教学业绩管理·三级权限
达梦数据1 小时前
DMDDB如何兼容 MongoDB
数据库·mongodb
蓝胖的四次元口袋1 小时前
Redis知识梳理(5)
数据库·redis·缓存
用户302822530681 小时前
你的 API 只返回 30 条,为什么数据库还是被打满了?
数据库·后端·架构
用户713874229001 小时前
一文读懂 AWS IAM:从工牌、钥匙到统一登录
数据库