Mybatis-Plus中QueryWrapper 与 LambdaQueryWrapper 的区别
·
QueryWrapper 与 LambdaQueryWrapper 的区别
1. 基本区别
QueryWrapper
java
// 使用字符串表示字段名
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "张三")
.gt("age", 18)
.like("email", "@qq.com");
LambdaQueryWrapper
java
// 使用Lambda表达式引用字段
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.eq(User::getName, "张三")
.gt(User::getAge, 18)
.like(User::getEmail, "@qq.com");
2. 核心区别对比
| 特性 | QueryWrapper | LambdaQueryWrapper |
|---|---|---|
| 字段引用方式 | 字符串硬编码 | Lambda表达式 |
| 类型安全性 | 编译期不检查字段是否存在 | 编译期检查,类型安全 |
| 重构友好性 | 重命名字段需手动修改字符串 | IDE自动重构 |
| 代码可读性 | 一般 | 更好,直接关联实体类 |
| 性能 | 相同 | 相同 |
| 防SQL注入 | 都防SQL注入 | 都防SQL注入 |
3. 详细对比
3.1 类型安全性
java
// QueryWrapper - 编译期不报错,运行时报错
queryWrapper.eq("nam", "张三"); // 拼写错误,编译时不检查
// LambdaQueryWrapper - 编译期报错
lambdaWrapper.eq(User::getNam, "张三"); // 编译时报错:找不到getNam方法
3.2 重构友好性
java
// QueryWrapper - 重命名需要手动修改
// 假设把字段 name 改为 username
queryWrapper.eq("name", "张三"); // ❌ 需要手动改为 "username"
// LambdaQueryWrapper - IDE自动重构
lambdaWrapper.eq(User::getName, "张三"); // ✅ 重命名实体类字段时自动更新
3.3 复杂查询对比
java
// QueryWrapper
QueryWrapper<CapitalInfo> queryWrapper = new QueryWrapper<>();
if (StringUtils.isNotBlank(capitalName)) {
queryWrapper.like("capital_name", capitalName);
}
if (capitalYear != null) {
queryWrapper.eq("capital_year", capitalYear);
}
// LambdaQueryWrapper
LambdaQueryWrapper<CapitalInfo> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.like(StringUtils.isNotBlank(capitalName), CapitalInfo::getCapitalName, capitalName)
.eq(capitalYear != null, CapitalInfo::getCapitalYear, capitalYear);
4. 实际使用示例
QueryWrapper 使用场景
java
// 1. 动态字段名(字段名是变量)
String fieldName = getFieldNameFromRequest(); // 可能是 "name" 或 "username"
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq(fieldName, "张三"); // Lambda方式无法实现
// 2. 复杂动态SQL拼接
QueryWrapper<User> wrapper = new QueryWrapper<>();
if (condition1) {
wrapper.eq("field1", value1);
} else {
wrapper.isNull("field1");
}
if (condition2) {
wrapper.in("field2", Arrays.asList(1, 2, 3));
}
// 3. 表连接查询
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("u.status", 1)
.eq("r.role_type", "admin")
.apply("u.role_id = r.id");
LambdaQueryWrapper 使用场景
java
// 1. 常规查询(推荐)
LambdaQueryWrapper<CapitalInfo> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(CapitalInfo::getCapitalState, 1)
.like(CapitalInfo::getCapitalName, "测试")
.orderByDesc(CapitalInfo::getCreateTime);
// 2. 链式调用
List<CapitalInfo> list = capitalInfoMapper.selectList(
new LambdaQueryWrapper<CapitalInfo>()
.eq(CapitalInfo::getCapitalYear, 2024)
.in(CapitalInfo::getCapitalType, Arrays.asList("A", "B", "C"))
.groupBy(CapitalInfo::getCapitalSource)
);
// 3. 条件判断简化
LambdaQueryWrapper<CapitalInfo> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(queryDTO.getCapitalState() != null, CapitalInfo::getCapitalState, queryDTO.getCapitalState())
.like(StringUtils.isNotBlank(queryDTO.getCapitalName()), CapitalInfo::getCapitalName, queryDTO.getCapitalName());
5. 性能比较
两者在性能上没有区别,最终都会转换为相同的SQL语句:
sql
-- 两者生成的SQL相同 SELECT * FROM capital_info WHERE capital_state = 1 AND capital_name LIKE '%测试%' ORDER BY create_time DESC
6. 最佳实践建议
推荐使用 LambdaQueryWrapper 的情况:
-
查询条件固定,字段名不会动态变化
-
注重代码可维护性和类型安全
-
实体类字段可能重构的情况
-
新项目开发,优先使用Lambda方式
推荐使用 QueryWrapper 的情况:
-
字段名需要动态生成
-
多表连接查询,涉及多个表的字段
-
处理遗留代码,保持一致性
-
构建复杂动态SQL,使用字符串更灵活
7. 混合使用示例
java
// 可以使用QueryWrapper的lambda()方法
QueryWrapper<CapitalInfo> wrapper = new QueryWrapper<>();
wrapper.lambda() // 转换为Lambda方式
.eq(CapitalInfo::getCapitalState, 1)
.like(CapitalInfo::getCapitalName, "测试");
// 或者反过来
LambdaQueryWrapper<CapitalInfo> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.eq(CapitalInfo::getCapitalState, 1);
QueryWrapper<CapitalInfo> queryWrapper = lambdaWrapper.getWrapper();
// 可以继续添加字符串方式的查询条件
queryWrapper.apply("DATE(create_time) = CURDATE()");
8. 结论
| 方面 | 推荐 | 原因 |
|---|---|---|
| 新项目开发 | LambdaQueryWrapper | 类型安全,重构友好 |
| 字段名固定 | LambdaQueryWrapper | 减少硬编码错误 |
| 字段名动态 | QueryWrapper | 灵活性强 |
| 代码可读性 | LambdaQueryWrapper | 直观明了 |
| 兼容性 | QueryWrapper | 所有场景都适用 |
建议:在大部分业务场景下,优先使用 LambdaQueryWrapper,因为它提供了更好的开发体验和代码安全性。只有在需要动态字段名或处理复杂SQL时,才使用 QueryWrapper。
更多推荐



所有评论(0)