在MyBatis-Plus中,QueryWrapper
是构建动态SQL查询条件的核心工具类,它通过链式调用和Lambda表达式支持,极大简化了条件构造过程。本文将结合代码示例,详细讲解其核心用法及最佳实践。
一、QueryWrapper核心概念
QueryWrapper
继承自 AbstractWrapper
,主要用于构建 SELECT
语句的 WHERE
条件,同时支持以下特性:
类型安全:通过Lambda表达式避免硬编码字段名
链式调用:支持连续的条件拼接
自动防注入:对用户输入参数自动转义
灵活组合:支持嵌套条件、逻辑运算符(AND/OR)
二、基础条件构造方法
1. 等于(eq) / 不等于(ne)
// 查询name等于"张三"且age不等于25的用户 QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("name", "张三") .ne("age", 25); List<User> users = userMapper.selectList(wrapper);
Lambda版本(推荐):
wrapper.lambda().eq(User::getName, "张三") .ne(User::getAge, 25);
2. 模糊查询(like)
// 模糊查询name包含"三"的用户 wrapper.like("name", "三"); // 左模糊查询(LIKE '%三') wrapper.likeLeft("name", "三"); // 右模糊查询(LIKE '三%') wrapper.likeRight("name", "三");
3. 范围查询
// BETWEEN查询(age在20到30之间) wrapper.between("age", 20, 30); // IN查询(id在指定列表中) wrapper.in("id", Arrays.asList(1, 3, 5)); // NOT IN查询 wrapper.notIn("id", Arrays.asList(2, 4, 6));
4. 空值判断
// 查询email为空的记录 wrapper.isNull("email"); // 查询email非空的记录 wrapper.isNotNull("email");
三、高级条件组合
1. 嵌套条件(AND/OR)
// 查询 (age > 20 AND age < 30) OR (name LIKE '%张%') wrapper.and(wq -> wq.gt("age", 20).lt("age", 30)) .or(wq -> wq.like("name", "张"));
Lambda版本:
wrapper.and(wq -> wq.lambda().gt(User::getAge, 20) .lt(User::getAge, 30)) .or(wq -> wq.lambda().like(User::getName, "张"));
2. 排序控制
// 按age降序,create_time升序 wrapper.orderByDesc("age") .orderByAsc("create_time");
3. 选择字段
// 仅查询id和name字段 wrapper.select("id", "name");
Lambda版本:
wrapper.select(User::getId, User::getName);
四、实用示例场景
示例1:分页查询带条件
// 创建分页对象(当前页1,每页10条) Page<User> page = new Page<>(1, 10); QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.lambda() .like(User::getName, "张") .orderByDesc(User::getCreateTime); // 执行分页查询 IPage<User> userPage = userMapper.selectPage(page, wrapper); // 获取分页数据 List<User> records = userPage.getRecords(); long total = userPage.getTotal();
示例2:动态条件构建
public List<User> searchUsers(String keyword, Integer minAge, Integer maxAge) { QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.lambda() .like(StringUtils.isNotBlank(keyword), User::getName, keyword) .gt(minAge != null, User::getAge, minAge) .lt(maxAge != null, User::getAge, maxAge); return userMapper.selectList(wrapper); }
示例3:子查询
// 查询年龄大于平均年龄的用户 QueryWrapper<User> subQuery = new QueryWrapper<>(); subQuery.select("avg(age)").lambda().from(User.class); wrapper.gt("age", subQuery);
五、最佳实践建议
优先使用Lambda版本
避免硬编码字段名,提升代码可维护性:// 错误方式(字段名变更时需修改多处) wrapper.eq("user_name", "张三"); // 正确方式(字段变更自动同步) wrapper.lambda().eq(User::getUserName, "张三");
合理使用条件判断
动态条件推荐使用Predicate
参数:wrapper.lambda() .eq(condition1, User::getField1, value1) .like(condition2, User::getField2, value2);
注意SQL注入防护
避免直接拼接用户输入:// 危险!存在SQL注入风险 wrapper.apply("name = {0}", userInput); // 安全方式 wrapper.eq("name", userInput);
性能优化技巧
为常用查询字段添加数据库索引
避免在循环中频繁创建QueryWrapper
大数据量分页时使用
last("LIMIT 1000")
限制返回量
六、总结
QueryWrapper
通过其流畅的API设计,使复杂SQL条件的构建变得直观高效。掌握其链式调用、Lambda表达式、嵌套条件等特性,可以显著提升MyBatis-Plus的开发效率。实际使用时建议结合Service层封装常用查询方法,保持代码的整洁性和可复用性。
本文由@战地网 原创发布。
该文章观点仅代表作者本人,不代表本站立场。本站不承担相关法律责任。
如若转载,请注明出处:https://www.zhanid.com/biancheng/4222.html