在 mapper 中写 sql 的时候,如果传入的参数两个以上,并且可能为空,就需要用到 where语句动态拼装了。
使用 where语句,if 标签进行拼装,如果某项参数为空, 此项就会略去;如果不为空,此项保留。
而且第一个连接"where"标签的 "and" ,会自动替换成 where。
<select id="selectByNameAndProductId" resultMap="BaseResultMap" parameterType="map"> select <include refid="Base_Column_List"/> from immall_product <where> <if test="productName != null"> and name like #{productName} </if> <if test="productId != null"> and id = #{productId} </if> </where> </select>
如果 productName 和 productId 都不为空,上面 where 语句等同于
where name like #{productId} and id = #{productId}
如果 productId为空,where语句等同于
where name like #{productId}
如果 productName为空,where语句等同于
where id = #{productId}
为什么要这么写?
productName 和 productId 作为参数,可能存在空值的情况。
如果不采用 where 动态拼装,可能会写成(1):
select
<include refid="Base_Column_List"/>
from immall_product
where name like #{productId} and id = #{productId}
此时只要有一项参数未传入,sql 语句就会错误,这两个参数并不是 “并” 的关系。
也可能写成(2):
select
<include refid="Base_Column_List"/>
from immall_product
<if test="productName != null">
where name like #{productName}
</if>
<if test="productId != null">
and id = #{productId}
</if>
此时若 productName 为空,and 直接接入前面的 表格名,sql语句错误。
还可能写成(3):
select
<include refid="Base_Column_List"/>
from immall_product
where 1 = 1
<if test="productName != null">
and name like #{productName}
</if>
<if test="productId != null">
and id = #{productId}
</if>
这种在业务中,是没有运行问题的,但是 “1 =1” 这种跟业务逻辑没有半点关系的语句放在这里,不够好。
而 mybatis 的 where 标签很贴心,帮我们解决了这些烦恼。where 动态拼装。
处理 List 数据时,可以使用 foreach标签:
<select id="selectByNameAndCategoryIds" resultMap="BaseResultMap" parameterType="map"> select <include refid="Base_Column_List"/> from immall_product where status = 1 <if test="productName != null"> and name like #{productName} </if> <if test="categoryList != null"> and category_id in <foreach item="item" index="index" open="(" separator="," close=")" collection="categoryList"> #{item} </foreach> </if> </select>