在这条 MyBatis 动态 SQL 中,where 1=1 是动态拼接 WHERE 条件的经典技巧 ,核心作用是:解决 "第一个动态条件前是否需要加 AND" 的问题,让条件拼接逻辑更简洁、无歧义。
一、先看核心问题:没有 1=1 会怎样?
假设去掉 where 1=1,SQL 会变成:
where
<if test="query.shopIdList != null and query.shopIdList.size()>0">
and a.shopId in (...)
</if>
<if test="query.shopId != null and query.shopId != ''">
and a.shopId=#{query.shopId}
</if>
...
如果第一个动态条件不满足 (比如 shopIdList 为 null),最终拼接的 SQL 会是:
select ... from dws_shop_itemcate_sum a where and a.shopId=xxx
where 后直接跟 and,触发 SQL 语法错误 (BadSqlGrammarException)。
二、where 1=1 的核心作用
1=1 是一个恒成立的条件(不会过滤任何数据),但它能:
- 占住
where后的第一个位置 ,所有动态条件都可以统一以and开头,无需判断 "是不是第一个条件"; - 不影响查询结果 :
1=1永远为真,不会过滤任何数据,最终的查询结果只由后续的动态条件决定; - 简化逻辑 :开发时不用逐个判断 "当前条件是不是第一个",所有动态条件都按
and 条件写即可,降低出错概率。
三、代码执行示例(更直观)
场景 1:仅传 shopIdList([9001,9002])
最终拼接的 SQL:
select ... from dws_shop_itemcate_sum a
where 1=1 and a.shopId in (9001,9002)
场景 2:仅传 shopId(9003)+ beginTime(2025-01-01)
最终拼接的 SQL:
select ... from dws_shop_itemcate_sum a
where 1=1 and a.shopId=9003 and a.reportDate>='2025-01-01'
场景 3:不传任何动态条件
最终拼接的 SQL:
select ... from dws_shop_itemcate_sum a where 1=1
(等价于 select ... from dws_shop_itemcate_sum a,查询全表)
四、替代方案(MyBatis 更优雅的写法)
MyBatis 提供了 <where> 标签,可以替代 1=1,自动处理多余的 and/or:
<select id="sumNumberCardDataByShop" resultType="StNumberCardDataBO">
select
<include refid="numberCard_queryColumn"/>
from dws_shop_itemcate_sum a
<where> <!-- 替代 where 1=1 -->
<if test="query.shopIdList != null and query.shopIdList.size()>0">
a.shopId in <!-- 去掉 and -->
<foreach collection="query.shopIdList" item="shopId"
index="index" open="(" close=")" separator=",">
#{shopId}
</foreach>
</if>
<if test="query.shopId != null and query.shopId != ''">
and a.shopId=#{query.shopId} <!-- 保留 and -->
</if>
<if test="query.beginTime != null and query.beginTime !=''">
<![CDATA[ and a.reportDate>=#{query.beginTime} ]]>
</if>
<if test="query.endTime != null and query.endTime !=''">
<![CDATA[ and a.reportDate<=#{query.endTime}]]>
</if>
</where>
</select>
<where> 标签的优势:
- 若有动态条件满足:自动添加
where,并去掉第一个条件前的and/or; - 若没有动态条件满足:不生成
where子句(避免where 1=1全表查询); - 比
1=1更优雅,是 MyBatis 推荐的写法。
五、总结
where 1=1的本质:用恒真条件占位,让所有动态条件统一以and开头,避免语法错误;- 优缺点:
- 优点:简单易懂,新手友好;
- 缺点:若所有动态条件都不满足,会生成
where 1=1导致全表查询(可能性能低);