【MyBatis-Plus】深入解析 MP:UpdateWrapper、LambdaQueryWrapper 、LambdaUpdateWrapper 构造动态 SQL 和自定义 SQL 的方法及规范

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


条件构造器


UpdateWrapper


对于更新,我们也可以直接使用 UpdateWrapper,在不创建实体对象的情况下,直接设置更新字段和条件。


set( )


刚刚煮啵讲解了条件构造器 QueryWrapper,那怎么使用 UpdateWrapper构造更新语句呢?

image-20250413173618216

两种更新方式的对比说明

以下是简化后的对比表格,突出核心区别:

对比维度QueryWrapper 更新方式UpdateWrapper 更新方式(推荐)
更新值设置通过实体对象设置通过wrapper.set()方法直接设置
条件构建需单独创建QueryWrapper直接在同个Wrapper中构建条件和设置值
参数传递需传递实体对象 + QueryWrapper仅需传递UpdateWrapper(实体对象传null)
代码简洁性需要维护两个对象一站式完成设置和条件构建
推荐场景需要复用已有实体对象时简单字段更新或动态条件更新

核心区别:UpdateWrapper通过内置的set()方法实现了条件构造和值更新的统一处理,避免了实体对象的创建。


基础更新:完成下述 SQL 查询。

UPDATE user_info SET delete_flag=0, age=5 WHERE id IN (1,2,3)

测试代码:

    @Test
    void testUpdateByUpdateWrapper(){
        UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("delete_flag", 0).set("age",25)
                .in("id", List.of(1,2,3));
        userInfoMapper.update(updateWrapper);
    }

image-20250413181451589


setSql( )


基于 SQL 更新:完成下述 SQL 查询。

UPDATE user_info SET age = age+10 WHERE id IN (1,2,3)

对于条件不是一个固定值,而是一个语句,就不能使用 set(),而是使用 setSql()

	@Test
    void testUpdateByUpdateWrapper(){
        UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.setSql("age = age + 10")
                .in("id", List.of(1,2,3));
        userInfoMapper.update(updateWrapper);
    }

LambdaQueryWrapper


QueryWrapperUpdateWrapper 存在一个问题,就是需要写死字段名;如果字段名发生变更,可能会因为测试不到位酿成事故

MyBatis-Plus 提供了一种基于 Lambda 表达式的条件构造器,它通过 Lambda 表达式引用实体类的属性,从而避免了硬编码字段名,也提高了代码的可读性可维护性

  • LambdaQueryWrapper
  • LambdaUpdateWrapper

分别对应上述的 QueryWrapperUpdateWrapper


接下来我们看下具体使用:

SELECT id, username, password, age 
FROM user_info 
WHERE age = 18 AND username 
LIKE "%min%"

下列分别是QueryWrapperLambdaQueryWrapper的 SQL 代码实现:

image-20250413184454470


image-20250413184350715


通过日志,也可以看出来拼接的 SQL 是否正确:

image-20250413185253843


LambdaUpdateWrapper


LambdaUpdateWrapper 用法和 LambdaQueryWrapper 相似。

    @Test
    void testLamdaUpdateByUpdateWrapper(){
        UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                .set(UserInfo::getDeleteFlag, 0)
                .set(UserInfo::getAge, 5)
                .in(UserInfo::getId, List.of(1,2,3));
        userInfoMapper.update(updateWrapper);
    }

MyBatis-Plus Wrapper类对比表格


以下是整理后的 MyBatis-Plus Wrapper 类对比表格:

Wrapper 类名继承关系主要用途核心特点适用场景
AbstractWrapper所有 Wrapper 的基类提供通用的条件构造方法包含 eq(), ne(), gt(), lt() 等通用条件方法,支持链式调用作为其他 Wrapper 的父类使用
QueryWrapper继承 AbstractWrapper构造查询条件新增 select() 方法可指定查询字段,支持 SQL 函数操作需要动态构建查询条件的场景
UpdateWrapper继承 AbstractWrapper构造更新条件支持 set() 方法直接指定更新字段和值,可结合条件更新部分数据需要条件更新的场景
LambdaQueryWrapper继承 AbstractWrapperLambda 表达式风格的查询构造器通过 Lambda 方法引用(如 User::getName)避免字段名硬编码,编译期类型检查需要类型安全且避免硬编码的场景
LambdaUpdateWrapper继承 AbstractWrapperLambda 表达式风格的更新构造器结合 Lambda 表达式set() 方法,在避免字段名硬编码的同时构建更新条件需要类型安全的条件更新场景

补充说明:

  1. 所有 Wrapper 都支持链式调用(如 .eq().gt().orderBy()
  2. Lambda 系 Wrapper 需基于实体类(如 new LambdaQueryWrapper<User>()
  3. 官网链接:条件构造器 | MyBatis-Plus

接下来通过代码来看下如何使用。


自定义 SQL


在实际的开发中,MyBatis-Plus 提供的操作不能满足我们的实际需求,MyBatis-Plus 也提供了自定义 SQL 的功能,我们可以利用 Wrapper 构造查询条件,再结合 Mapper 编写 SQL。

条件构造器 | MyBatis-Plus

image-20250413213353254


代码示例 1


完成下述 SQL 查询。

select id,username,password,age FRoM user_info WHERE username = "admin"

Mapper:

导入正确的 wrapper 包:

image-20250413213926302


${} 虽然会有 SQL 注入的问题,但是 MyBatis-Plus 已经考虑到了这个问题并且解决了,所以这里我们可以正常使用 ${ew.customSqlSegment}

image-20250413214337144


package com.bit.mybatis.plus.mapper;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.bit.mybatis.plus.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {

    @Select("select id,username,password,age from user_info ${ew.customSqlSegment}")
    List<UserInfo> selectUserInfoByCondition(@Param(Constants.WRAPPER) Wrapper<UserInfo> queryWrapper);
}


测试代码:

    @Test
    void selectUserInfoByCondition() {
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lt("age",20);
        userInfoMapper.selectUserInfoByCondition(queryWrapper).forEach(System.out::println);
    }

image-20250413214917059


image-20250413215054397


观察打印日志:

image-20250413215459683


代码示例 2


完成下述 SQL 查询。

UPDATE user_info SET age = age+10 WHERE id IN (1,2,3)

Mapper:

image-20250413215804674


image-20250413215937675


image-20250413220033831


测试代码:

image-20250413220308500


观察打印日志:

image-20250413220422937


代码示例 3


MyBatis-Plus 在 MyBatis 的基础上只做增强不做改变,所以也支持 XML 的实现方式。上述功能也可以使用 XML 的方式完成:

配置 mapper 路径

mybatis-plus:
  mapper-locations: "classpath*:/mapper/**.xml" # Mapper.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.bit.mybatis.plus.mapper.UserInfoMapper">


</mapper>

在这里插入图片描述


在这里插入图片描述


编写 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.bit.mybatis.plus.mapper.UserInfoMapper">


    <select id="queryUserByCustom" resultType="com.bit.mybatis.plus.model.UserInfo">
        select id,username,password,age FROM user_info ${ew.customSqlSegment}
    </select>
</mapper>

测试

在这里插入图片描述


查看打印日志

在这里插入图片描述


总结


  • MyBatis-Plus 是 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,可以用更少的代码实现数据库表的 CRUD,让我们的开发变得更加简单。
  • MyBatis-Plus 支持自定义 SQL,版本不低于 3.0.7,传递 Wrapper 对象作为参数时,参数名必须为 ew,在 SQL 语句中,使用 ${ew.customSqlSegment} 来引用 Wrapper 对象生成的 SQL 片段。

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值