MyBatis分条件查询实战:动态SQL高效实现多条件搜索

MyBatis 分条件查询实战指南:从基础到高级的优雅实现

在 Java 企业级开发中,数据查询是最核心的业务场景之一。然而,现实世界的需求往往不是简单的“查所有”或“按 ID 查”,而是复杂的动态条件查询(Dynamic Query)。例如,一个电商后台的订单列表,用户可能只输入“订单号”,也可能同时输入“订单号”、“用户ID”、“状态”和“时间范围”。 如果为每个可能的组合编写单独的 SQL 或方法,代码将变得臃肿且难以维护。MyBatis 提供的动态 SQL 功能正是解决这一痛点的利器。本文将深入探讨如何利用 MyBatis 实现高效、优雅的分条件查询。

一、 为什么需要动态 SQL?

在传统 JDBC 或简单 ORM 中,处理多条件查询通常面临以下困境: 1. SQL 拼接复杂:需要在 Java 代码中手动拼接 SQL 字符串,极易出错且存在 SQL 注入风险。 2. 代码冗余:每增加一个查询条件,就需要修改 SQL 语句或增加新的 Mapper 方法。 3. 性能隐患:不当的拼接可能导致索引失效或产生大量的执行计划缓存。 MyBatis 通过 XML 中的标签(如 ``, ``, ``)或注解中的 `${}`/`#{}` 结合,允许我们在 SQL 模板中嵌入逻辑判断,从而自动生成最终的 SQL 语句。

二、 核心标签解析

实现分条件查询,主要依赖以下几个动态 SQL 标签:

1. `` 标签:条件判断

这是最基础的标签,用于判断某个字段是否为空或满足特定条件。 ```xml ``` 注意:`WHERE 1=1` 是一种常见的技巧,用于简化后续 `AND` 的拼接。虽然它让 SQL 看起来不那么优雅,但在处理可选条件时非常实用。

2. `` 标签:智能处理 WHERE 子句

`` 标签会自动处理 `WHERE` 关键字,并智能去除多余的 `AND` 或 `OR`,无需再写 `1=1`。 ```xml ``` 当第一个 `` 条件不满足时,`` 不会添加 `WHERE` 关键字;当后续条件满足时,它会自动处理前面的 `AND`。

3. ``, ``, ``:互斥条件

类似于 Java 中的 `switch-case`,用于实现“多选一”的逻辑。 ```xml ```

4. `` 标签:集合遍历

用于处理 `IN` 查询或批量操作。 ```xml ```

三、 最佳实践与进阶技巧

1. 使用 Wrapper 对象封装查询条件

不要直接在 Mapper 方法中传递多个基本类型参数。建议创建一个查询 DTO(Data Transfer Object),如 `OrderQuery`,将查询条件封装在其中。 ```java public class OrderQuery { private String orderNo; private Integer status; private Date createTimeStart; private Date createTimeEnd; // getters and setters } ```

2. 避免 SQL 注入

始终使用 `#{}` 而不是 `{}` 仅用于列名、表名等动态结构,且需确保来源安全。

3. 处理空字符串与 null

在 `` 判断中,务必同时检查 `null` 和空字符串(`""`)。 ```xml AND name LIKE CONCAT('%', #{name}, '%') ```

4. 动态排序(ORDER BY)

排序字段通常无法使用 `#{}` 预编译,因此需要使用 `${}`,但需严格校验输入值。 ```xml ```

5. 使用 MyBatis-Plus 简化开发

如果项目允许引入第三方库,MyBatis-Plus 提供了强大的 `QueryWrapper` 或 `LambdaQueryWrapper`,可以进一步简化动态查询代码: ```java QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.like(StringUtils.isNotBlank(orderNo), "order_no", orderNo) .eq(status != null, "status", status) .ge(createTimeStart != null, "create_time", createTimeStart); List orders = orderMapper.selectList(queryWrapper); ``` 这种方式代码更简洁,类型更安全,且无需编写 XML。

四、 常见问题与解决方案

问题 原因 解决方案
SQL 注入风险 使用 `${}` 拼接用户输入 严格校验输入,或使用 `#{}` 预编译
性能问题 动态 SQL 导致执行计划无法缓存 确保查询条件有索引,避免全表扫描
标签嵌套混乱 XML 结构复杂难维护 提取公共 SQL 片段,使用 `` 标签复用
空集合查询报错 `` 遍历空集合 在 `` 中判断集合大小

五、 总结

MyBatis 的分条件查询功能是其灵活性的核心体现。通过合理使用 ``, ``, `` 等动态 SQL 标签,我们可以构建出既灵活又安全的查询逻辑。 关键要点回顾: 1. 优先使用 `` 标签,避免手动处理 `1=1` 和 `AND` 拼接。 2. 封装查询对象,保持接口清晰。 3. 警惕 SQL 注入,谨慎使用 `${}`。 4. 考虑引入 MyBatis-Plus,在复杂项目中进一步提升开发效率。 掌握这些技巧,你将能够轻松应对各种复杂的业务查询需求,写出高质量、可维护的 MyBatis 代码。


相关标签: