mybatis动态 SQL

本文根据mybatis官方网站的相关信息编写,相关资料请参考http://www.mybatis.org/mybatis-3/zh/dynamic-sql.html

MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。mybatis支持if、choose (when, otherwise)、trim (where, set)、foreach、bind、多数据库支持和动态 SQL 中的可插拔脚本语言
1、if条件
动态 SQL 通常要做的事情是根据条件包含 where 子句的一部分。if条件中可以使用and或者or来拼接多个逻辑运算。比如:

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

2、choose (when, otherwise)
choose (when, otherwise)也是条件语句,相当于java中的switch(case, default)。例如

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

3、trim
trim通常用户where,set。作用是多个条件拼接SQL时,如果所有的if不满足或者有些if不满足会导致SQL语句不完整,结果执行SQL时报错。trim是用来规避这种事情发生的。例如:

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

如果不使用trim进行where,则会出现如下的不完整的SQL语句

1、SELECT * FROM BLOG WHERE
2、SELECT * FROM BLOG WHERE AND title like '%abc%'

使用trim优化如下

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
  <where>//或者使用trim
    <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>

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

4、foreach
foreach对集合进行遍历,相当于java中的for。例如

<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>
  • item 表示每个元素变量(如果迭代Map对象或者Map.Entry对象的集合时,它表示的时对象的值[value])
  • index 表示索引变量(如果迭代Map对象或者Map.Entry对象的集合时,它表示的时对象的键[key])
  • open 表示拼接后的元素使用“(”开始
  • close 表示拼接后的元素使用“)”结束
  • separator 表示元素直接使用“,”符号拼接
    上述的语句转换后的SQL如下
SELECT * FROM POST P WHERE ID in(1,2,3)

5、bind
bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如

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

6、多数据库支持
一个配置了“_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>

7、动态 SQL 中的可插拔脚本语言
MyBatis 从 3.2 开始支持可插拔脚本语言,这允许你插入一种脚本语言驱动,并基于这种语言来编写动态 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 项目。

你前面看到的所有 xml 标签都是由默认 MyBatis 语言提供的,而它由别名为 xml 的语言驱动器 org.apache.ibatis.scripting.xmltags.XmlLanguageDriver 所提供。

你可能感兴趣的:(MyBatis)