QueryWrapper 类的作用与示例详解
通俗易懂的解释
想象一下你去图书馆找书:
- QueryWrapper 就像是一个智能的图书管理员
- 你告诉管理员你的需求:"我要找计算机类、2020年后出版的、作者是张三的书"
- 管理员会根据你的要求组合查询条件,然后去书库帮你找书
在编程中,QueryWrapper 就是这样一个"智能查询构建器",它帮助我们用面向对象的方式构建数据库查询条件,避免直接写复杂的 SQL 语句。
QueryWrapper 的核心作用
- 条件构建:用链式调用组合查询条件
- 安全防护:防止 SQL 注入攻击
- 代码可读:使查询逻辑更清晰
- 数据库无关:支持多种数据库
实际应用示例
基础查询:用户管理系统
// 创建 QueryWrapper 实例
QueryWrapper<User> queryWrapper = new QueryWrapper<>();// 设置查询条件:年龄大于18岁,状态为激活
queryWrapper.gt("age", 18) // age > 18.eq("status", "active"); // status = 'active'// 添加排序:按注册时间倒序
queryWrapper.orderByDesc("register_time");// 执行查询
List<User> userList = userMapper.selectList(queryWrapper);
复杂查询:商品搜索系统
QueryWrapper<Product> wrapper = new QueryWrapper<>();// 组合条件:价格在100-500之间,库存大于0,名称包含"手机"
wrapper.between("price", 100, 500) // 100 <= price <= 500.gt("stock", 0) // stock > 0.like("name", "手机") // name LIKE '%手机%'// 嵌套条件:(品牌是华为或小米) 且 评分大于4.5.and(qw -> qw.eq("brand", "华为").or().eq("brand", "小米")).gt("rating", 4.5);// 分页查询
Page<Product> page = new Page<>(1, 10); // 第1页,每页10条
IPage<Product> result = productMapper.selectPage(page, wrapper);
动态条件构建:订单查询
public List<Order> searchOrders(OrderSearchParams params) {QueryWrapper<Order> wrapper = new QueryWrapper<>();// 根据参数动态添加条件if (params.getUserId() != null) {wrapper.eq("user_id", params.getUserId());}if (params.getStartDate() != null && params.getEndDate() != null) {wrapper.between("create_time", params.getStartDate(), params.getEndDate());}if (params.getMinAmount() != null) {wrapper.ge("total_amount", params.getMinAmount()); // >= minAmount}if (params.getOrderStatus() != null) {wrapper.in("status", params.getOrderStatus());}// 执行查询return orderMapper.selectList(wrapper);
}
QueryWrapper 常用方法详解
方法名 | 作用 | 示例 | 等价 SQL |
---|---|---|---|
eq() | 等于 | eq("status", 1) | status = 1 |
ne() | 不等于 | ne("deleted", 1) | deleted <> 1 |
gt() | 大于 | gt("age", 18) | age > 18 |
ge() | 大于等于 | ge("score", 60) | score >= 60 |
lt() | 小于 | lt("price", 1000) | price < 1000 |
le() | 小于等于 | le("weight", 5) | weight <= 5 |
between() | 在...之间 | between("age", 18, 30) | age BETWEEN 18 AND 30 |
like() | 模糊匹配 | like("name", "张%") | name LIKE '张%' |
in() | 在列表中 | in("category_id", Arrays.asList(1,2,3)) | category_id IN (1,2,3) |
orderByAsc() | 升序排序 | orderByAsc("create_time") | ORDER BY create_time ASC |
select() | 指定返回字段 | select("id", "name", "email") | SELECT id, name, email |
实际应用场景
场景1:权限控制查询
public List<Document> getUserDocuments(Long userId) {QueryWrapper<Document> wrapper = new QueryWrapper<>();wrapper.eq("owner_id", userId) // 用户自己的文档.or() // 或者.inSql("id", "SELECT document_id FROM shares WHERE user_id = " + userId); // 被共享的文档return documentMapper.selectList(wrapper);
}
场景2:统计报表
public Map<String, Object> getSalesReport(int year) {QueryWrapper<Order> wrapper = new QueryWrapper<>();wrapper.select("MONTH(create_time) as month", "SUM(total_amount) as sales").eq("YEAR(create_time)", year).groupBy("MONTH(create_time)").orderByAsc("MONTH(create_time)");return orderMapper.selectMaps(wrapper); // 返回 Map 列表
}
为什么使用 QueryWrapper?
安全:避免 SQL 注入
// 错误做法(有SQL注入风险)
String sql = "SELECT * FROM users WHERE name = '" + userName + "'";// 正确做法(使用QueryWrapper安全)
wrapper.eq("name", userName);
可维护:条件修改方便
// 修改条件只需调整一行代码
wrapper.eq("status", newStatus);
可读:链式调用清晰表达逻辑
wrapper.gt("age", 18).lt("age", 30).eq("gender", "male");
跨数据库:自动适配不同数据库语法
总结
QueryWrapper 就像是一个智能查询助手:
- 你告诉它需要什么条件(等于、大于、包含等)
- 它把这些条件翻译成正确的 SQL
- 帮你安全高效地执行查询