zoukankan      html  css  js  c++  java
  • mybatis动态sql

    mybatis动态SQL

    转自:http://www.toutiao.com/i6399345397927510530/
    MyBatis还有一个方便的功能就是动态SQL,可以根据条件智能生成SQL语句。这里的例子全部来自MyBatis文档。

    if标签
    下面这个例子使用了MyBatis的if元素,在标题不为空的情况下在查询结果中包含标题的查询。
    <select id="findActiveBlogWithTitleLike" resultType="Blog">
      SELECT * FROM BLOG WHERE state = ‘ACTIVE’
      <if test="title != null">
        AND title like #{title}
      </if>
    </select>

    where/trim/set标签
    如果需要在多个情况中包含某一个查询条件。可以向下面这样,使用choose、when、otherwise。如果使用过JSTL的话,会发现这和JSTL的条件标签非常类似。
    <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>

    对于下面这个例子,如果state为空,无法生成合法的SQL语句。
    <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>

    MyBatis自然也有相应的解决办法。就是使用where标签改写。where标签非常智能。如果标签内部没有合适的语句,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标签还不能满足需求。这时候还可以使用trim标签进行更高级的定制。trim标签中的prefix和suffix属性会被用于生成实际的SQL语句,会和标签内部的语句拼接。如果语句的前面或后面遇到prefixOverrides或suffixOverrides属性中指定的值,MyBatis会自动将它们删除。在指定多个值的时候,别忘了每个值后面都要有一个空格,保证不会和后面的SQL连接在一起。下面这个例子和where标签完全等效。
    <trim prefix="WHERE" prefixOverrides="AND |OR ">
      ...
    </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>

    与它等价的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>

    bind标签
    bind标签可以将非OGNL表达式值绑定到其中。下面的例子将结果映射中的值绑定到了OGNL表达式中,从而可以直接使用#{}语法访问。
    <select id="selectBlogsLike" resultType="Blog">
      <bind name="pattern" value="'%' + _parameter.getTitle + '%'" />
      SELECT * FROM BLOG WHERE title LIKE #{pattern}
    </select>

    SQL构造类
    有时候需要在Java代码中生成SQL语句。如果我们直接编写的话会是一件非常麻烦的事情。由于Java不支持跨行字符串,所以我们要么在一行里面写一个非常非常长的SQL语句,要么用加号拼接出一个笨拙的字符串。MyBatis提供了SQL构造类,我们可以方便的使用这个类构造出SQL语句。
    下面这几个例子同样来自于MyBatis文档。SQL构造类有两种用法:匿名类和流式构造。构造完成之后,调用toString()方法即可生成对应的SQL语句。
    // 匿名内部类
    public String deletePersonSql() {
      return new SQL() {
        {
          DELETE_FROM("PERSON");
          WHERE("ID = #{id}");
        }
      }.toString();
    }
    // 流式构造
    public String insertPersonSql() {
      return new SQL().INSERT_INTO("PERSON").VALUES("ID, FIRST_NAME", "#{id}, #{firstName}").VALUES("LAST_NAME", "#{lastName}").toString();
    }
    // 如果需要条件构造,只能使用匿名类方式,注意匿名类要引用方法参数的话,参数必须声明为final的
    public String selectPersonLike(final String id, final String firstName, final String lastName) {
      return new SQL(){
        {
          SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FIRST_NAME, P.LAST_NAME");
          FROM("PERSON P");
          if (id != null) {
            WHERE("P.ID like #{id}");
          }
          if (firstName != null) {
            WHERE("P.FIRST_NAME like #{firstName}");
          }

          if (lastName != null) {
            WHERE("P.LAST_NAME like #{lastName}");
          }
          ORDER_BY("P.LAST_NAME");
        }
      }.toString();
    }
    public String deletePersonSql() {
      return new SQL(){
        {
          DELETE_FROM("PERSON");
          WHERE("ID = #{id}");
        }
      }.toString();
    }

  • 相关阅读:
    如何高效处理bug?
    如何获取字符串函数的实现?
    数据处理-csv,pandas
    CentOS 下安装SAC(Seismic Analysis Code)
    CentOS安装使用ffmpeg
    Tensorflow问题记录 --pydot Failed to import pydot. You must install pydot and graphviz for pydotprint to work
    Tensorflow学习记录 --TensorFlow高效读取数据tfrecord
    Committee to boost development of Chinese language teachers
    Consensus-based decentralized auctions for robust task allocation
    Chinese market critical to US firms: US-China Business Council
  • 原文地址:https://www.cnblogs.com/lzhl/p/6589655.html
Copyright © 2011-2022 走看看