MyBatis的动态sql

108 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路


1、if

<select id="findActiveBlogWithTitleLike" resultType="Blog">
  SELECT * FROM BLOG
  WHERE state = ‘ACTIVE’
  <if test="title != null">
    AND title like #{title}
  </if>
</select>

这条语句提供了可选的查找文本功能。如果不传入 “title”,那么所有处于 “ACTIVE” 状态的 BLOG 都会返回;如果传入了 “title” 参数,那么就会对 “title” 一列进行模糊查找并返回对应的 BLOG 结果。

2、choose、when和otherwise

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>

传入了 “title” 就按 “title” 查找,传入了 “author” 就按 “author” 查找的情形。若两者都没有传入,就返回标记为 featured 的 BLOG。

3、where

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
  <where>
    <if test="state != null">
         state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>

where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

4、set

<update id="updateAuthorIfNecessary">
  update Author
    <set>
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio}</if>
    </set>
  where id=#{id}
</update>

set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。

5、trim

  • prefix="" 前缀:trim标签体中是整个字符串拼串 后的结果。 prefix给拼串后的整个字符串加一个前缀
  • prefixOverrides="" 前缀覆盖: 去掉整个字符串前面多余的字符
  • suffix="" 后缀:suffix给拼串后的整个字符串加一个后缀
  • suffixOverrides="" 后缀覆盖:去掉整个字符串后面多余的字符
<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>

上面是和where 元素等价的自定义 trim 元素。prefixOverrides 属性会忽略通过管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子会移除所有 prefixOverrides 属性中指定的内容,并且插入 prefix 属性中指定的内容。

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

与 set 元素等价的自定义 trim 元素

6、foreach

<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST
  WHERE ID in
  <foreach item="item" index="index" collection="list" open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

foreach 元素允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。

  • collection:指定输入对象中的集合属性
    • list 类型的参数会特殊处理封装在map中
    • map 类型的参数 map 的 key 为 list
  • item:每次遍历生成的对象
  • open:开始遍历时的拼接字符串
  • close:结束时拼接的字符串
  • separator:遍历对象之间需要拼接的字符串
  • index:索引
    • 遍历 list 的时候 index 为索引
    • 遍历 map 的时候 index 为 map 的 key,item 为map 的 value

7、sql和include

<sql id="sql1">
	select * from Blog where id = #{id}
</sql>
<select id="queryBlog" parameterType="map" resultType="blog">
	<!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
	<include refid="sql1">
		<property name="id" value="1"/>
	</include>
	<!-- 在这里还可以引用其他的 sql 片段 -->
</select>

有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。

8、bind

<select id="selectBlogsLike" resultType="Blog">
	<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
	SELECT * FROM BLOG
	WHERE title LIKE #{pattern}
</select>

bind:可以将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值

9、内置对象

  • _parameter:代表整个参数 单个参数:_parameter就是这个参数 多个参数:参数会被封装为一个map;_parameter就是代表这个map

  • _databaseId:如果配置了databaseIdProvider标签。 _databaseId就是代表当前数据库的别名