mybatis if else(手把手讲解)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
在数据库操作中,根据不同的业务场景动态生成 SQL 语句是一项核心技能。MyBatis 作为 Java 领域广受欢迎的持久层框架,提供了强大的动态 SQL 功能,其中 <if>
和 <choose>
标签是实现条件分支的核心工具。本文将通过循序渐进的方式,结合实际案例,深入解析 MyBatis 中的条件判断逻辑,帮助开发者高效掌握这一技能。
动态 SQL 的核心思想:灵活与可维护性
在传统 SQL 编写中,若需根据多个条件组合生成查询语句,通常需要通过字符串拼接或编写多套 SQL 语句,这会导致代码冗余、可读性差等问题。MyBatis 的动态 SQL 通过 XML 标签和注解,将 SQL 语句的生成逻辑与 SQL 语法解耦,实现了代码的模块化和复用。
形象比喻:可以将动态 SQL 看作一个“智能厨师”,它根据你提供的食材(参数)和菜谱(逻辑规则),自动调整烹饪步骤(SQL 语句),最终产出符合需求的菜品(查询结果)。
基础标签:<if>
的使用场景与语法
1. <if>
标签的基本语法
<if>
标签用于判断某个条件是否成立,若成立则执行标签内的 SQL 片段。其核心语法如下:
<if test="condition">
SQL 片段
</if>
其中,test
属性支持多种表达式,如直接判断字段是否非空、比较运算符(==
、!=
)、逻辑运算符(&&
、||
)等。
2. 典型案例:条件查询用户信息
假设需根据用户姓名或邮箱查询用户信息,可编写如下 SQL:
<select id="selectUsers" resultType="User">
SELECT * FROM users
WHERE 1=1
<if test="name != null">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="email != null">
AND email = #{email}
</if>
</select>
解释:
WHERE 1=1
是动态 SQL 的常见技巧,确保条件组合时无需处理AND
或OR
的前缀问题。- 每个
<if>
标签单独判断参数是否存在,若存在则拼接对应的条件。
3. 进阶技巧:嵌套表达式与空值处理
若需处理更复杂的条件,例如“年龄在 18 到 30 岁之间”,可以使用逻辑运算符:
<if test="ageMin != null && ageMax != null">
AND age BETWEEN #{ageMin} AND #{ageMax}
</if>
此外,对于可能为空的字段,需注意 MyBatis 的空值判断逻辑:
test="field"
:等同于field != null
。test="field == null"
:需显式判断空值。
多分支控制:<choose>
、<when>
、<otherwise>
当需要实现类似 if-else
的多分支逻辑时,<choose>
标签是关键。其结构与 Java 的 switch
语句类似,但支持更灵活的条件判断。
1. <choose>
标签的语法结构
<choose>
<when test="condition1">
SQL 片段1
</when>
<when test="condition2">
SQL 片段2
</when>
<otherwise>
默认 SQL 片段
</otherwise>
</choose>
核心规则:
- 按顺序匹配第一个满足条件的
<when>
,执行其内容。 - 若无符合条件的
<when>
,则执行<otherwise>
内容。
2. 实际案例:分场景查询订单状态
假设需根据参数 status
的值(如 new
、paid
、shipped
)动态生成不同的查询条件:
<select id="selectOrders" resultType="Order">
SELECT * FROM orders
WHERE 1=1
<choose>
<when test="status == 'new'">
AND status = 'NEW'
</when>
<when test="status == 'paid'">
AND status = 'PAID' AND payment_date > NOW() - INTERVAL 7 DAY
</when>
<otherwise>
AND status != 'CANCELED'
</otherwise>
</choose>
</select>
逻辑分析:
- 若
status
参数为new
,则筛选状态为NEW
的订单。 - 若为
paid
,则筛选状态为PAID
且最近一周内付款的订单。 - 其他情况则排除已取消的订单。
综合案例:动态 SQL 的复杂场景应用
案例背景
某电商平台需根据用户输入的多个筛选条件(如商品名称、价格区间、分类、库存状态)动态生成商品查询 SQL。
1. 需求拆解与标签组合
- 商品名称模糊查询:使用
<if>
判断名称是否非空。 - 价格区间筛选:使用
<if>
结合BETWEEN
。 - 分类多选:使用
<foreach>
遍历分类列表。 - 库存状态选择:使用
<choose>
处理in_stock
、out_of_stock
或默认值。
2. 完整 XML 配置
<select id="searchProducts" resultType="Product">
SELECT * FROM products
WHERE 1=1
<if test="name != null">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="minPrice != null and maxPrice != null">
AND price BETWEEN #{minPrice} AND #{maxPrice}
</if>
<if test="categories != null and categories.size() > 0">
AND category IN
<foreach item="category" collection="categories"
open="(" separator="," close=")">
#{category}
</foreach>
</if>
<choose>
<when test="stockStatus == 'in_stock'">
AND stock > 0
</when>
<when test="stockStatus == 'out_of_stock'">
AND stock = 0
</when>
<!-- 默认不筛选库存状态 -->
</choose>
</select>
3. 参数传递与调用示例
Java 代码中可通过 Map
或自定义对象传递参数:
Map<String, Object> params = new HashMap<>();
params.put("name", "手机");
params.put("minPrice", 1000);
params.put("maxPrice", 5000);
params.put("categories", Arrays.asList("electronics", "phones"));
params.put("stockStatus", "in_stock");
List<Product> products = mapper.searchProducts(params);
常见问题与最佳实践
1. 空值与逻辑陷阱
- 问题:若参数
age
为0
,直接使用<if test="age">
会误判为false
(因0
等价于布尔值false
)。 - 解决方案:显式比较
<if test="age != null">
。
2. 性能优化建议
- 避免全表扫描:确保每个条件都有对应的索引支持。
- 合并相似逻辑:若多个
<if>
条件可能生成相同 SQL 片段,可提前合并以减少冗余。
3. 调试技巧
- 日志输出:通过
log4j
或mybatis.configuration.log-impl
配置,查看最终生成的 SQL 语句。 - 单元测试:编写参数覆盖不同条件的测试用例,验证 SQL 生成的正确性。
结论
MyBatis 的 <if>
和 <choose>
标签为动态 SQL 提供了强大的灵活性,但合理的设计和严谨的测试仍是关键。通过本文的案例解析,开发者可以掌握:
- 如何通过
<if>
实现单条件分支。 - 如何利用
<choose>
构建多条件分支逻辑。 - 在复杂场景下组合多个标签实现灵活查询。
掌握这些技能后,开发者能够更高效地应对业务需求的变化,同时保持代码的可维护性和可读性。建议读者通过实际项目练习,并结合日志工具调试,逐步提升动态 SQL 的应用能力。