mybatis动态SQL标签的用法

Multi-db vendor support

一个部署了“_databaseId”变量的 databaseIdProvider
对于动态代码来说是可用的,这样就可以遵照不同的数据库厂商构建特定的口舌。比如下边的事例:

<insert id="insert">
  <selectKey keyProperty="id" resultType="int" order="BEFORE">
    <if test="_databaseId == 'oracle'">
      select seq_users.nextval from dual
    </if>
    <if test="_databaseId == 'db2'">
      select nextval for seq_users from sysibm.sysdummy1"
    </if>
  </selectKey>
  insert into users values (#{id}, #{name})
</insert>
动态 SQL 中可插拔的脚本语言

MyBatis 从 3.2
最先匡助可插拔的脚本语言,因而你可以在插入一种语言的驱动(language
driver)之后来写基于这种语言的动态 SQL 查询。

能够通过兑现上面接口的模式来插入一种语言:

public interface LanguageDriver {
  ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql);
  SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType);
  SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType);
}

假使有了自定义的语言驱动,你就足以在 mybatis-config.xml
文件中校它设置为默认语言:

<typeAliases>
  <typeAlias type="org.sample.MyLanguageDriver" alias="myLanguage"/>
</typeAliases>
<settings>
  <setting name="defaultScriptingLanguage" value="myLanguage"/>
</settings>

除外安装默认语言,你也可以针对优异的语句指定特定语言,这足以透过如下的
lang 属性来完成:

<select id="selectBlog" lang="myLanguage">
  SELECT * FROM BLOG
</select>

抑或在您正在拔取的炫耀中加上评释 @Lang 来完成:

public interface Mapper {
  @Lang(MyLanguageDriver.class)
  @Select("SELECT * FROM BLOG")
  List<Blog> selectBlog();
}

注意 可以将 Apache Velocity 作为动态语言来利用,更多细节请参考
MyBatis-Velocity 项目。

trim, where, set

前边多少个例证已经相应地化解了一个臭名昭著的动态 SQL
问题。现在设想回到“if”示例,本次我们将“ACTIVE =
1”也设置成动态的原则,看看会暴发咋样。

<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>
</select>

假如这么些条件从不一个能匹配上将会咋样?最终这条 SQL 会变成这样:

SELECT * FROM BLOG
WHERE

这会造成查询败北。假设一味第二个标准配合又会怎么着?这条 SQL 最后会是这么:

SELECT * FROM BLOG
WHERE 
AND title like ‘someTitle’

那些查询也会破产。那么些问题不可能大概的用标准化句式来解决,假诺你也已经被迫这样写过,那么您很可能未来未来都不想再如此去写了。

MyBatis
有一个简单的拍卖,这在90%的图景下都会有用。而在不可能使用的地点,你能够自定义处理形式来令其正常工作。一处简易的修改就能取得想要的效力:

<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
元素知道只有在一个上述的if条件有值的处境下才去插入“WHERE”子句。而且,若末了的情节是“AND”或“OR”伊始的,where
元素也通晓怎样将她们去除。

假使 where 元素没有按常规套路出牌,大家如故得以因此自定义 trim
元一直定制我们想要的职能。比如,和 where 元素等价的自定义 trim 元素为:

<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ... 
</trim>

prefixOverrides
属性会忽略通过管道相隔的文书连串(注意此例中的空格也是不可或缺的)。它带来的结果就是有所在
prefixOverrides 属性中指定的始末将被移除,并且插入 prefix
属性中指定的内容。

好像的用来动态更新语句的化解方案叫做 set。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
关键字,同时也会免去无关的逗号,因为用了尺度语句之后很可能就会在变化的赋值语句的背后留下这一个逗号。

若您对等价的自定义 trim 元素的榜样感兴趣,这这就应该是它的精神:

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

只顾这里我们忽略的是后缀中的值,而又一回附加了前缀中的值。

foreach

动态 SQL 的其余一个常用的画龙点睛操作是急需对一个聚众进行遍历,通常是在构建
IN 条件语句的时候。比如:

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

foreach
元素的效果是非常强大的,它同意你指定一个汇聚,讲明可以用在要素体内的集合项和目录变量。它也允许你指定开闭匹配的字符串以及在迭代当中放置分隔符。那么些因素是很智能的,由此它不会有时地附加多余的分隔符。

留神
你可以将此外可迭代对象(如列表、集合等)和其他的字典或者数组对象传递给foreach作为集合参数。当使用可迭代对象或者数组时,index是眼下迭代的次数,item的值是此次迭代获取的因素。当使用字典(或者Map.Entry对象的相会)时,index是键,item是值。

到此我们早已到位了关乎 XML 配置文件和 XML
映射文件的琢磨。下一部分将详细探索 Java
API,这样才能从已开立的炫耀中收获最大好处。

bind

bind 元素可以从 OGNL 表明式中开创一个变量并将其绑定到上下文。比如:

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

稍微时候,我们不想用到拥有的原则语句,而只想从中择其简单。针对这种情况,MyBatis
提供了 choose 元素,它有点像 Java 中的 switch 语句。

要么地点的例子,不过本次变为提供了“title”就按“title”查找,提供了“author”就按“author”查找,若两者都尚未提供,就回到所有符合条件的BLOG(实际情状也许是由管理员按一定策略选出BLOG列表,而不是重返大量无意义的擅自结果)。

<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>

动态 SQL

MyBatis 的有力特性之一便是它的动态 SQL。固然你有拔取 JDBC
或另外类似框架的经验,你就能体会到依据不同尺度拼接 SQL
语句有多么苦痛。拼接的时候要确保不可能忘了必需的空格,还要小心省掉列名列表最后的逗号。利用动态
SQL 这一特征可以彻底摆脱这种伤痛。

层见迭出拔取动态 SQL 不可以是单独的一片段,MyBatis 当然使用一种强大的动态 SQL
语言来改革这种景观,这种语言可以被用在随意的 SQL 映射语句中。

动态 SQL 元素和行使 JSTL 或任何类似基于 XML 的文本处理器相似。在 MyBatis
以前的本子中,有成千上万的要素需要来打听。MyBatis 3
大大提高了它们,现在用不到原来一半的元素就足以了。MyBatis
选取功用强大的依照 OGNL 的表明式来扫除其他因素。

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach
if

动态 SQL 平常要做的业务是有标准地含有 where 子句的一有些。比如:

<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结果再次回到(就以此例子而言,细心的读者会发觉里头的参数值是可以分包部分掩码或通配符的)。

假使想可选地因而“title”和“author”五个标准化搜索该如何做吧?首先,改变语句的称呼让它更具实际意义;然后要是进入另一个原则即可。

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’ 
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>
网站地图xml地图