条件构造器
UpdateWrapper
对于更新,我们也可以直接使用 UpdateWrapper
,在不创建实体对象的情况下,直接设置更新字段和条件。
set( )
刚刚煮啵讲解了条件构造器 QueryWrapper
,那怎么使用 UpdateWrapper
构造更新语句呢?
两种更新方式的对比说明:
以下是简化后的对比表格,突出核心区别:
对比维度 | 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);
}
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
QueryWrapper
和 UpdateWrapper
存在一个问题,就是需要写死字段名
;如果字段名发生变更,可能会因为测试不到位酿成事故
。
MyBatis-Plus 提供了一种基于 Lambda 表达式
的条件构造器,它通过 Lambda 表达式
来引用实体类的属性
,从而避免了硬编码字段名
,也提高了代码的可读性
和可维护性
。
LambdaQueryWrapper
LambdaUpdateWrapper
分别对应上述的 QueryWrapper
和 UpdateWrapper
。
接下来我们看下具体使用:
SELECT id, username, password, age
FROM user_info
WHERE age = 18 AND username
LIKE "%min%"
下列分别是QueryWrapper
和LambdaQueryWrapper
的 SQL 代码实现:
通过日志,也可以看出来拼接的 SQL 是否正确:
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 | 继承 AbstractWrapper | Lambda 表达式风格的查询构造器 | 通过 Lambda 方法引用 (如 User::getName)避免字段名硬编码,编译期类型检查 | 需要类型安全且避免硬编码的场景 |
LambdaUpdateWrapper | 继承 AbstractWrapper | Lambda 表达式风格的更新构造器 | 结合 Lambda 表达式 和 set() 方法 ,在避免字段名硬编码的同时构建更新条件 | 需要类型安全的条件更新场景 |
补充说明:
- 所有 Wrapper 都支持链式调用(如
.eq().gt().orderBy()
) - Lambda 系 Wrapper 需基于实体类(如
new LambdaQueryWrapper<User>()
) - 官网链接:条件构造器 | MyBatis-Plus
接下来通过代码来看下如何使用。
自定义 SQL
在实际的开发中,MyBatis-Plus 提供的操作不能满足我们的实际需求,MyBatis-Plus 也提供了自定义 SQL 的功能,我们可以利用 Wrapper 构造查询条件,再结合 Mapper 编写 SQL。
代码示例 1
完成下述 SQL 查询。
select id,username,password,age FRoM user_info WHERE username = "admin"
Mapper:
导入正确的 wrapper 包:
${}
虽然会有 SQL 注入
的问题,但是 MyBatis-Plus 已经考虑到了这个问题并且解决了,所以这里我们可以正常使用 ${ew.customSqlSegment}
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);
}
观察打印日志:
代码示例 2
完成下述 SQL 查询。
UPDATE user_info SET age = age+10 WHERE id IN (1,2,3)
Mapper:
测试代码:
观察打印日志:
代码示例 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 片段。