MyBatis 的动态 SQL 包括以下几种元素:
元素名称 | 描述 | 备注 |
---|---|---|
if | 判断语句 | 单条件分支判断 |
choose(when、otherwise) | 相当于 Java 中的 case when 语句 | 多条件分支判断 |
trim(where、set) | 辅助元素 | 用于处理一些 SQL 拼装问题 |
foreach | 循环语句 | 在 IN 语句等列举条件常用 |
详细的使用参考官网文档:http://www.mybatis.org/mybatis-3/zh/dynamic-sql.html
本章内容简单描述这些动态 SQL 在使用的过程中需要注意的地方。
choose, when, otherwise
比如我们要实现如下功能:
- 当学生姓名不为空,则只用学生姓名作为条件查询
- 当学生性别不为空,则只用学生性别作为条件查询
- 当学生姓名和学生性别都为空,则要求学生学生证件号不为空
针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
<select id="listByConditions" parameterType="studentQuery" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from t_student
<where>
<choose>
<when test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</when>
<when test="sex != null">
AND sex = #{sex}
</when>
<otherwise>
AND selfcard_no is not null
</otherwise>
</choose>
</where>
</select>
trim, where, set
比如下面的动态 SQL 有什么问题?
<select id="listByConditions" parameterType="studentQuery" resultMap="BaseResultMap">
SELECT id, name, sex, selfcard_no, note
FROM t_student
WHERE
<if test="ids != null and ids.size() > 0">
id IN
<foreach collection="ids" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</if>
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="sex != null">
AND sex = #{sex}
</if>
<if test="selfcardNo != null">
AND selfcard_no = #{selfcardNo}
</if>
</select>
如果这些条件没有一个能匹配上会发生什么?最终这条 SQL 会变成这样:
SELECT id, name, sex, selfcard_no, note
FROM t_student
WHERE
这样会导致 SQL 语句执行失败。如果仅仅第二个条件匹配又会怎样?这条 SQL 最终会是这样:
SELECT id, name, sex, selfcard_no, note
FROM t_student
WHERE
AND name LIKE CONCAT('%', 'a', '%')
这个查询也会失败。
MyBatis 提供了
<select id="listByConditions" parameterType="studentQuery" resultMap="BaseResultMap">
SELECT id, name, sex, selfcard_no, note
FROM t_student
<where>
<if test="ids != null and ids.size() > 0">
AND id IN
<foreach collection="ids" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</if>
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="sex != null">
AND sex = #{sex}
</if>
<if test="selfcardNo != null">
AND selfcard_no = #{selfcardNo}
</if>
</where>
</select>
foreach
实现批量新增功能,动态 SQL 如下:
<insert id="batchInsertByNoAutoInc" parameterType="list">
<selectKey keyProperty="id" resultType="long" order="BEFORE">
select if(max(id) is null, 1, max(id) + 2) as newId from t_student
</selectKey>
insert into t_student (name, sex, selfcard_no, note)
values
<foreach collection="list" item="item" index="index" separator=",">
(
#{item.name,jdbcType=VARCHAR},
#{item.sex,jdbcType=TINYINT},
#{item.selfcardNo,jdbcType=BIGINT},
#{item.note,jdbcType=VARCHAR}
)
</foreach>
</insert>
批量新增的操作需要确保 list 中必须有值。
作者:殷建卫 链接:https://www.yuque.com/yinjianwei/vyrvkf/opbeni 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。