MyBatis-Plus 条件构造器
MyBatis-Plus 的条件构造器(Wrapper)是 MyBatis-Plus 提供的一个非常强大的功能,它允许你以链式调用的方式构建复杂的 SQL 查询条件,而无需手写繁琐的 XML 映射文件或注解。
主要特点
- 链式调用:通过链式调用的方式构建查询条件,代码可读性高,易于维护。
- 灵活:支持各种复杂的查询条件,包括但不限于等于、不等于、大于、小于、模糊查询等。
- 避免 SQL 注入:MyBatis-Plus 的条件构造器内部会处理 SQL 注入的问题,提高应用的安全性。
参数中的Wrapper
就是条件构造的抽象类,其下有很多默认实现,继承关系如图:
QueryWrapper:用于封装查询条件
UpdateWrapper:用于封装更新条件
LambdaQueryWrapper:用于使用Lambda语法封装查询条件
LambdaUpdateWrapper:用于使用Lambda语法封装更新条件
Wrapper
的子类AbstractWrapper
提供了where中包含的所有条件构造方法:
而QueryWrapper在AbstractWrapper的基础上拓展了一个select方法,允许指定查询字段:
而UpdateWrapper在AbstractWrapper的基础上拓展了一个set方法,允许指定SQL中的SET部分:
QueryWrapper
无论是修改、删除、查询,都可以使用QueryWrapper来构建查询条件。接下来看一些例子:
查询:查询出名字中带o
的,存款大于等于1000元的人。代码如下:
原SQL语句
SELECT id,username,info,balance
FROM user
WHERE username LIKE ? AND balance >= ?
@Test
void testQueryWrapper() {
// 1.构建查询条件 where name like "%o%" AND balance >= 1000
QueryWrapper<User> wrapper = new QueryWrapper<User>()
.select("id", "username", "info", "balance")
.like("username", "o")
.ge("balance", 1000);
// 2.查询数据
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
更新:更新用户名为jack的用户的余额为2000,代码如下:
UPDATE user
SET balance = 2000
WHERE (username = "jack")
@Test
void testUpdateByQueryWrapper() {
// 1.构建查询条件 where name = "Jack"
QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username", "Jack");
// 2.更新数据,user中非null字段都会作为set语句
User user = new User();
user.setBalance(2000);
userMapper.update(user, wrapper);
}
UpdateWrapper
基于BaseMapper中的update方法更新时只能直接赋值,对于一些复杂的需求就难以实现。
例如:更新id为1,2,4
的用户的余额,扣200,对应的SQL应该是:
UPDATE user SET balance = balance - 200 WHERE id in (1, 2, 4)
SET的赋值结果是基于字段现有值的,这个时候就要利用UpdateWrapper中的setSql功能了:
@Test
void testUpdateWrapper() {
List<Long> ids = List.of(1L, 2L, 4L);
// 1.生成SQL
UpdateWrapper<User> wrapper = new UpdateWrapper<User>()
.setSql("balance = balance - 200") // SET balance = balance - 200
.in("id", ids); // WHERE id in (1, 2, 4)
// 2.更新,注意第一个参数可以给null,也就是不填更新字段和数据,
// 而是基于UpdateWrapper中的setSQL来更新
userMapper.update(null, wrapper);
}
LambdaQueryWrapper
无论是QueryWrapper还是UpdateWrapper在构造条件的时候都需要写死字段名称,会出现字符串魔法值
。这在编程规范中显然是不推荐的。
在编程中,“字符串魔法值”通常指的是硬编码在代码中的字符串常量,这些常量没有明确的意义或者上下文,可能难以理解和维护。在 MyBatis-Plus (MBP) 中,如果出现了字符串魔法值问题,这通常意味着在构建 SQL 语句时直接使用了硬编码的字符串,而不是使用更清晰的枚举、常量或配置文件。
其中一种办法是基于变量的gettter
方法结合反射技术。因此我们只要将条件对应的字段的getter
方法传递给MybatisPlus,它就能计算出对应的变量名了。而传递方法可以使用JDK8中的方法引用
和Lambda
表达式。 因此MybatisPlus又提供了一套基于Lambda的Wrapper,包含两个:
-
LambdaQueryWrapper
-
LambdaUpdateWrapper
分别对应QueryWrapper和UpdateWrapper
其使用方式如下:
@Test
void testLambdaQueryWrapper() {
// 1.构建条件 WHERE username LIKE "%o%" AND balance >= 1000
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.lambda()
.select(User::getId, User::getUsername, User::getInfo, User::getBalance)
.like(User::getUsername, "o")
.ge(User::getBalance, 1000);
// 2.查询
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
条件构造器的用法:
- QueryWrapper和LambdaQueryWrapper通常用来构建select、delete、update的where条件部分
- UpdateWrapper和LambdaUpdateWrapper通常只有在set语句比较特殊才使用 尽量使用
- LambdaQueryWrapper和LambdaUpdateWrapper,避免硬编码