一.条件构造器是做什么的?
先看一个需求:
查询用户表中,姓名为"张三",年龄大于等于18岁的用户,并按年龄从小到大排序。
直接写SQL:
sql
SELECT *
FROM user
WHERE name = '张三'
AND age >= 18
ORDER BY age ASC;
使用MyBatis-Plus,可以用java代码描述这些条件:
java
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getName, "张三")
.ge(User::getAge, 18)
.orderByAsc(User::getAge);
List<User> users = userMapper.selectList(wrapper);
对应关系:
|--------------------------|------------------|
| Java写法 | SQL含义 |
| eq(User::getName, "张三") | name = '张三' |
| ge(User::getAge, 18) | age >= 18 |
| orderByAsc(User::getAge) | ORDER BY age ASC |
核心理解:条件构造器负责描述条件,Mapper方法负责执行数据操作。
java
// 只是构造条件,还没有查询数据库
wrapper.eq(User::getName, "张三");
// 调用 Mapper,才真正查询数据库
List<User> users = userMapper.selectList(wrapper);
上面的SQL是为了方便理解;实际执行时,普通条件中的值通常通过参数绑定传入。
二.MyBatis和MyBatis-Plus要分清
- **Spring Boot:**负责应用配置、组件管理等。
- **MyBatis:**持久层框架,支持通过 XML、注解等方式编写 SQL。
- **MyBatis-Plus:**在 MyBatis 的基础上提供增强功能,例如通用 CRUD、条件构造器。
因此,你现在学的 QueryWrapper,准确地说属于 MyBatis-Plus。
通常 Mapper 会这样定义:
java
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
继承 BaseMapper<User> 后,就可以使用它提供的方法:
java
userMapper.selectList(wrapper); // 根据条件查询列表
userMapper.selectCount(wrapper); // 根据条件统计数量
userMapper.delete(wrapper); // 根据条件删除
注意:同一个条件可以用于不同操作,最终做什么取决于你调用的方法。 不要把查询条件构造器误认为只能用于查询。
三.最常见的四种条件构造器
| 类型 | 主要用途 | 字段写法 |
|---|---|---|
QueryWrapper<User> |
查询条件、排序、查询字段等 | "name" |
LambdaQueryWrapper<User> |
查询条件的 Lambda 写法 | User::getName |
UpdateWrapper<User> |
更新条件及更新字段 | "name" |
LambdaUpdateWrapper<User> |
更新条件及字段的 Lambda 写法 | User::getName |
1. QueryWrapper:使用数据库列名
java
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name", "张三")
.ge("age", 18);
这里的 "name" 和 "age" 是数据库列名。
如果实体属性是 userName,数据库列名是 user_name,一般应写:
java
wrapper.eq("user_name", "张三");
2. LambdaQueryWrapper:使用实体的 getter
java
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getName, "张三")
.ge(User::getAge, 18);
User::getName 是方法引用,MyBatis-Plus 会根据实体映射信息解析出对应的数据库列。
它不是"现在调用 getter 获取某个用户的姓名",而是在这里标识要操作哪个属性对应的列。
学习和日常开发时,建议优先使用 LambdaQueryWrapper:字段更容易检查,也方便重构。
四、先掌握这些常用方法
| 方法 | 含义 | SQL 示例 |
|---|---|---|
eq |
等于 | age = 18 |
ne |
不等于 | age <> 18 |
gt |
大于 | age > 18 |
ge |
大于等于 | age >= 18 |
lt |
小于 | age < 18 |
le |
小于等于 | age <= 18 |
like |
包含某段文字 | name LIKE '%张%' |
between |
在某个范围内,包含两端 | age BETWEEN 18 AND 30 |
in |
属于给定值集合 | status IN (1, 2) |
isNull |
是 NULL | email IS NULL |
orderByAsc |
升序排序 | ORDER BY age ASC |
orderByDesc |
降序排序 | ORDER BY age DESC |
java
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.like(User::getName, "张")
.between(User::getAge, 18, 30)
.eq(User::getStatus, 1)
.orderByDesc(User::getAge);
List<User> users = userMapper.selectList(wrapper);
含义是:
查询姓名包含"张"、年龄在 18~30 岁之间、状态为 1 的用户,按年龄从大到小排序。
连续添加的普通条件,默认用 AND 连接。
这些方法返回当前构造器,因此可以连续调用,也就是"链式调用"。
五、特别重要:动态条件
实际项目里,用户可能只输入姓名,也可能只输入年龄,还可能什么都不输入。
java
String name = null;
Integer minAge = 18;
我们希望:
- 姓名有内容,才添加姓名条件。
- 最小年龄不为
null,才添加年龄条件。
可以这样写:
java
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.like(
StringUtils.hasText(name),
User::getName,
name
)
.ge(
minAge != null,
User::getAge,
minAge
);
List<User> users = userMapper.selectList(wrapper);
这里使用的是 Spring 的工具类:
java
import org.springframework.util.StringUtils;
重点看这个结构:
java
eq(boolean condition, 字段, 值)
第一个参数决定:是否把这一条条件加进去。
java
wrapper.eq(true, User::getStatus, 1); // 添加条件
wrapper.eq(false, User::getStatus, 1); // 不添加条件
所以前面的示例只会添加:
java
WHERE age >= 18
不会添加姓名条件。
注意:不要认为传入 null 就一定自动忽略条件。 判断数据库字段是不是 NULL,应使用 isNull();决定是否添加查询条件,应使用布尔参数或 if。
六、现在先记住这条流程
创建构造器
↓
添加条件、排序等
↓
把构造器传给 Mapper 方法
↓
MyBatis-Plus 生成并执行 SQL
↓
获取结果