这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战
MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。
动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
IF 语句
<!--
如果名字为空,那么只根据密码查询,反之,则根据名字来查询
select * from blog where name = #{name} and password = #{password}
-->
<select id="selectUserByNameAndPassword" parameterType="map" resultType="pojo.User">
select *
from user
where
<if test="name!=null">
name = #{name}
</if>
<if test="password!=null">
and password = #{password}
</if>
</select>
复制代码
上述语句中,如果 title 为空那么查询语句为 select * from user where and password = #{password}
,这是错误的 SQL 语句
Where 语句
<!--
如果名字为空,那么只根据密码查询,反之,则根据名字来查询
select * from blog where name = #{name} and password = #{password}
-->
<select id="selectUserByNameAndPassword" parameterType="map" resultType="pojo.User">
select *
from user
<where>
<if test="name != null">
name = #{name}
</if>
<if test="password != null">
and password = #{password}
</if>
</where>
</select>
复制代码
“where”标签:如果它包含的标签中有返回值的话,它就会插入一个‘where’。此外,如果标签返回的内容是以 AND 或 OR 开头的,则它会将其剔除掉。
Set 语句
<!--
update user set name=#{name},password=#{password} where id=#{id}
-->
<update id="updateUserById" parameterType="pojo.User">
update user
<set>
<if test="name!=null">
name=#{name},
</if>
<if test="password!=null">
password = #{password}
</if>
</set>
where id = #{id}
</update>
复制代码
Choose语句
类似于 Java 的 switch 语句,查询条件有一个满足即可。
<select id="selectUserByNameAndPassword" parameterType="map" resultType="pojo.User">
select *
from user
<where>
<choose>
<when test="name != null">
name = #{name}
</when>
<when test="password != null">
and password = #{password}
</when>
<otherwise>
and id=#{id}
</otherwise>
</choose>
</where>
</select>
复制代码
foreach
foreach 元素的功能是非常强大的,它允许你指定一个集合,声明可以用在元素体内的集合项和索引变量。它也允许你指定开闭匹配的字符串以及在迭代中间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。
动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候。比如:
<!--select * from user where id in (1,2,3)-->
<select id="selectUser" resultType="pojo.User">
select *
from user
where id in
<!--
List 实例将会以 "list" 作为键
数组实例的键是 "array"
-->
<foreach collection="array" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
复制代码
- collection:指定输入对象中的集合属性
- item:每次遍历生成的对象
- open:开始遍历时的拼接字符串
- close:结束时拼接的字符串
- separator:遍历对象之间需要拼接的字符串
注意:可以将一个 List 实例或者数组作为参数对象传给 MyBatis,当你这么做的时候,MyBatis 会自动将它包装在一个 Map 中并以名称为键。List 实例将会以 "list" 作为键,而数组实例的键将是 "array"。
SQL片段
有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。
-
提取重复 SQL 片段:
<sql id="if-name-password"> <if test="name != null"> name = #{name} </if> <if test="password != null"> and password = #{password} </if> </sql> 复制代码
-
引用SQL片段:
<select id="selectUserByNameAndPassword" parameterType="map" resultType="pojo.User"> select * from user <where> <!-- 引用 sql 片段,如果 refid 指定的不在本文件中,那么需要在前面加上 namespace --> <include refid="if-name-password"></include> <!-- 在这里还可以引用其他的 sql 片段 --> </where> </select> 复制代码
注意:
- 最好基于单表来定义 sql 片段,提高片段的可重用性
- 在 sql 片段中不要包括 where
近期评论