sqle
sqle copied to clipboard
解析Mybatis xml文件互斥if标签有问题
版本信息(Version)
问题描述(Describe)
含有互斥if时,解析有问题. 原内容如下:
<select id="queryWoBillInfoByBillId" resultType="java.util.Map">
select
spb.deal_code as "account",
swb.contact_phone as "contactPhone",
(select bpb2 .city_code from baf.baf_pub_bureau bpb2 where bpb2.bureau_id=spb.nativenet_id) as "cityId",
(select bpb.business_name from baf.baf_pub_business bpb where bpb.business_id = spb.specialty_id) as "proType",
swb.sub_name as "userName",
swb.inst_address as "address"
from
<if test="isHis == 0">
pub.svr_pub_bill spb,
wo.svr_wo_bill swb
</if>
<if test="isHis == 1">
pub.svr_pub_bill_his spb,
wo.svr_wo_bill_his swb
</if>
where
spb.bill_id = swb.bill_id
and spb.bill_id = #{billId}
</select>
解析出来的sql如下
select
spb.deal_code as "account",
swb.contact_phone as "contactPhone",
(select bpb2 .city_code from baf.baf_pub_bureau bpb2 where bpb2.bureau_id=spb.nativenet_id) as "cityId",
(select bpb.business_name from baf.baf_pub_business bpb where bpb.business_id = spb.specialty_id) as "proType",
swb.sub_name as "userName",
swb.inst_address as "address"
from
pub.svr_pub_bill spb,
wo.svr_wo_bill swb
pub.svr_pub_bill_his spb,
wo.svr_wo_bill_his swb
where
spb.bill_id = swb.bill_id
and spb.bill_id = ?
截图或日志(Log)
如何复现(To Reproduce)
问题原因
解决方案
变更影响面
受影响的模块或功能
外部引用的潜在问题或风险
版本兼容性
测试建议
TODO
- [ ] 修复后在微信群艾特:圣雄肝帝
复现过程
使用下面内容填充的xml文件在快捷审核中能够稳定复现
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.YourMapper">
<select id="queryWoBillInfoByBillId" resultType="java.util.Map">
select
spb.deal_code as "account",
swb.contact_phone as "contactPhone",
(select bpb2.city_code from baf.baf_pub_bureau bpb2 where bpb2.bureau_id=spb.nativenet_id) as "cityId",
(select bpb.business_name from baf.baf_pub_business bpb where bpb.business_id = spb.specialty_id) as "proType",
swb.sub_name as "userName",
swb.inst_address as "address"
from
<if test="isHis == 0">
pub.svr_pub_bill spb,
wo.svr_wo_bill swb
</if>
<if test="isHis == 1">
pub.svr_pub_bill_his spb,
wo.svr_wo_bill_his swb
</if>
where
spb.bill_id = swb.bill_id
and spb.bill_id = #{billId}
</select>
</mapper>
补充
MyBatis 支持的动态 SQL 标签主要用于在 XML 映射文件中根据条件动态生成 SQL 语句。这些标签基于 <script> 标签内编写,常用于 <select>、<insert>、<update>、<delete> 等语句中。
以下是 MyBatis 支持的所有动态 SQL 标签(来自 org.apache.ibatis.scripting.xmltags 包):
✅ 条件判断类标签:
-
<if>-
根据 test 条件判断是否包含某段 SQL。
-
示例:
<if test="name != null"> AND name = #{name} </if>
-
-
<choose>-
类似 Java 中的 switch-case。
-
子标签有
<when>和<otherwise>。<choose> <when test="status == 'active'"> AND status = 'ACTIVE' </when> <when test="status == 'inactive'"> AND status = 'INACTIVE' </when> <otherwise> AND status = 'UNKNOWN' </otherwise> </choose>
-
✅ 逻辑组合类标签:
-
<where>-
自动处理
AND/OR前缀,拼接 SQL 的 WHERE 子句。<where> <if test="name != null">name = #{name}</if> <if test="age != null">AND age = #{age}</if> </where>
-
-
<set>-
用于动态拼接
UPDATE语句中的 SET 子句,自动去除最后一个逗号。<set> <if test="name != null">name = #{name},</if> <if test="age != null">age = #{age},</if> </set>
-
-
<trim>-
高级标签,可以定制前缀、后缀、前后缀覆盖等。
-
常用于代替
<where>或<set>。<trim prefix="WHERE" prefixOverrides="AND |OR "> <if test="name != null">AND name = #{name}</if> <if test="age != null">OR age = #{age}</if> </trim>
-
✅ 循环类标签:
-
<foreach>-
用于遍历集合(如 List、Array、Map),生成
IN (...)语句等。<foreach collection="ids" item="id" open="(" separator="," close=")"> #{id} </foreach>
-
✅ 其他标签:
-
<bind>-
用于创建临时变量,可以用于字符串拼接、正则表达式处理等。
<bind name="pattern" value="'%' + name + '%'" /> <if test="name != null">AND name LIKE #{pattern}</if>
-
✅ 根标签(MyBatis 3.5+ 推荐):
-
<script>-
顶层包装标签,声明该 SQL 为动态 SQL。
<select id="findUser" resultType="User"> <script> SELECT * FROM user <where> <if test="name != null">AND name = #{name}</if> </where> </script> </select>
-