一步步学Mybatis-怎么样实现动态SQL查询(6)

  上一章咱们已经讲完了关于Mybatis的分页用法,其实MyBatis 还具备的一个强大的特性之一一般是它的动态 SQL 能力。 若是你有使用 JDBC 或其余 类似框架的经验,你就明白要动态的串联 SQL 字符串在一块儿是十分纠结的,确保不能忘了空格或在列表的最后省略逗号。Mybatis中的动态 SQL 能够完全处理这种痛苦。对于动态SQL,最通俗简单的方法就是咱们本身在硬编码的时候赋予各类动态行为的判断,而在Mybatis中,用一种强大的动态 SQL 语 言来改进这种情形,这种语言能够被用在任意映射的 SQL 语句中。动态 SQL 元素和使用 JSTL 或其余类似的基于 XML 的文本处理器类似。MyBatis 采用功能强大的基于 OGNL 的表达式来消除其余元素。html

  本章中咱们利用前几章构建的实例,假设几种应用状况,经过实践了解这几种动态SQL标签的用法,毕竟学习最快的途径就是动手实践~java

  咱们经常使用的几个节点元素有if,choose(when, otherwise),trim(where, if),foreach。真正使用下来我感受有点像XSLT的用法。详细用法说明(点我)
git

  (1)if 的用法github

   还记得上一章中咱们有再ViisitMapper的分页配置中看到if节点吗,若是pageIndex>-1 and pageSize>-1的时候就加入相应的分页SQL,不然就不添加(默认取所有),以下:
web

<select id="getListByPagenate" parameterType="PagenateArgs"
    resultType="Visitor">
    select * from (
    <include refid="getListSql" /> <include refid="orderBySql"/>
    ) t <!-- #{}表示参数化输出,${}表示直接输出不进行任何转义操做,本身进行转移 -->
    <if test="pageStart>-1 and pageSize>-1">
        limit #{pageStart}, #{pageSize}
    </if>
</select>
<sql id="getListSql">
    select * from Visitor where
    status>0
</sql>
<sql id="orderBySql">
    order by ${orderFieldStr} ${orderDirectionStr}
</sql>

  由于咱们的参数pageIndex与pageSize都是int值因此能够这样直接判断,若是是对象实例咱们能够利用null判断来进行一些动态逻辑的控制,具体实际开发中就要看业务需求了。这里我认为要注意的是别十分顺手的吧and写成&&,这个在配置中不会被识别~。sql

  (2)choose (when, otherwise)的用法session

  choose when 主要在多个条件的状况下只知足其中一个条件的应用场景中使用,例如这里就构建一个query条件,分别传递id,name与createTime。假设咱们查询Visitor表时,若是VisitorId有值则,使用Id查询,若是VisitorName有值则采用VisitName查询,以下,仍是在david.mybatis.demo.IVisitorOperation接口类中添加List<Visitor> getListChooseWhenDemo(BasicQueryArgs args)方法。在VisitorMapper中添加相应的的select节点配置:mybatis

package david.mybatis.demo;

import java.util.List;

import david.mybatis.model.BasicQueryArgs;
import david.mybatis.model.PagenateArgs;
import david.mybatis.model.Visitor;
import david.mybatis.model.VisitorWithRn;

public interface IVisitorOperation {
    /*
     * 添加访问者
     */
    public int add(Visitor visitor);
    
    /*
     * 删除访问者
     */
    public int delete(int id);
    
    /*
     * 更新访问者
     */
    public int update(Visitor visitor);
    
    /*
     * 查询访问者
     */
    public Visitor query(int id);
    
    /*
     * 查询List
     */
    public List<Visitor> getList();
    
    /*
     * 分页查询List
     */
    public List<Visitor> getListByPagenate(PagenateArgs args);
    
    /*
     * 分页查询List(包含Rownum)
     */
    public List<VisitorWithRn> getListByPagenateWithRn(PagenateArgs args);
    
    /*
     * 基础查询
     */
    public Visitor basicQuery(int id);
    
    /*
     * 动态条件查询(choose,when)实例
     */
    public List<Visitor> getListChooseWhenDemo(BasicQueryArgs args);
    
    /*
     * 动态条件查询(where,if)实例
     */
    public List<Visitor> getListWhereDemo(BasicQueryArgs args);
    
    /*
     * 动态查询(foreach)实例
     */
    public List<Visitor> getListForeachDemo(List<Integer> ids);
    
}
修改后的IvisitorOperation
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="david.mybatis.demo.IVisitorOperation">    
    <resultMap type="Visitor" id="visitorRs">
        <id column="Id" property="id" />
        <result column="Name" property="name" />
        <result column="Email" property="email" />
        <result column="Status" property="status" />
        <result column="CreateTime" property="createTime" />
    </resultMap>
    <sql id="getListSqlConditions">
        select * from Visitor
    </sql>
    <!-- 知足其中一个条件时候用choose when操做 -->
    <select id="getListChooseWhenDemo" resultMap="visitorRs"
        parameterType="BasicQueryArgs">
        <include refid="getListSqlConditions" />
        <where>
            <if test="queryStatus>0">
                status=#{queryStatus}
            </if>
            <choose>
                <when test="queryId!=0">
                    and id=#{queryId}
                </when>
                <when test="queryName!=null">
                    and name like #{queryName}
                </when>
                <otherwise>
                    and createTime>= #{queryTime}
                </otherwise>
            </choose>
        </where>
    </select>
</mapper>
choose-when-otherwise动态条件配置

  (3)where if (trim)的用法app

   where关键词的好处是在于,若是有相应的过滤条件的话,它知道在适当的时候插入where关键词。并且它也知道在什么时候该去掉相应的AND与OR的链接符,主要应对以下情景框架

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

  不会由于全部条件不知足变为

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
  WHERE
</select>

  或者由于没有知足第一个条件,单单知足后面的条件变成

<select id="findActiveBlogLike"
     resultType="Blog">
    SELECT * FROM BLOG
    WHERE
    AND title like ‘someTitle’
</select>

  因此针对这种咱们能够在创建choose when条件示例,一样在IVisitorOperation接口类中加入相应的方法public List<Visitor> getListWhereDemo(BasicQueryArgs args),把VisitorMapper配置文件中的相对应配置加上去以下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="david.mybatis.demo.IVisitorOperation">    
    <sql id="getListSqlConditions">
        select * from Visitor
    </sql>
    <!-- 知足条件的都加上去操做 -->
    <select id="getListWhereDemo" resultMap="visitorRs"
        parameterType="BasicQueryArgs">
        <include refid="getListSqlConditions" />
        
        <where> 
            <if test="queryStatus>0"> 
                status>0 
            </if> 
            <if test="queryId>0"> 
                and id=#{queryId} 
            </if> 
            <if test="queryName!=null"> 
                and name like=#{queryName} 
            </if> 
            <if test="queryTime!=null"> 
                and createTime>=#{queryTime} 
            </if>
        </where>
        <!--
        <trim prefix="WHERE" prefixOverrides="AND |OR ">
            <if test="queryStatus>0">
                status>0
            </if>
            <if test="queryId>0">
                and id=#{queryId}
            </if>
            <if test="queryName!=null">
                and name like=#{queryName}
            </if>
            <if test="queryTime!=null">
                and createTime>=#{queryTime}
            </if>
        </trim>
        -->
    </select>
</mapper>
Where if动态条件配置

  (4)foreach的用法

  在经常使用的动态SQL中咱们有个业务场景是要where id in 一大串的ID,像这种状况咱们就能够用到foreach啦,没必要本身辛辛苦苦去拼接Id字符串啦。一样的步骤仍是在IVisitorOperation接口类中加入相应的方法public List<Visitor> getListForeachDemo(List<Integer> ids),而后再对应的Mapper文件中配置上相应的节点元素信息,以下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="david.mybatis.demo.IVisitorOperation">    
    <sql id="getListSqlConditions">
        select * from Visitor
    </sql>
    <!-- Foreach循环条件 -->
    <select id="getListForeachDemo" resultMap="visitorRs">
        <include refid="getListSqlConditions"/>
        where status>0 and id in 
        <foreach collection="list" item="item" index="index" open="(" separator="," close=")">
            ${item}
        </foreach>
    </select>
</mapper>
Foreach动态条件配置

  最后你只须要在DemoRun中创建相应的测试方法,Mybatis里面的动态SQL也就完成啦,下面测试用的DemoRun方法

/*
     * 动态查询foreach实例
     */
    public static void getListForeachDemo(List<Integer> ids) {
        SqlSession session = MybatisUtils.getSqlSession();
        IVisitorOperation vOperation = session.getMapper(IVisitorOperation.class);
        List<Visitor> ls = vOperation.getListForeachDemo(ids);
        for (Visitor visitor : ls) {
            System.out.println(visitor);
        }
    }
    
    /*
     * 动态查询where if实例
     */
    public static void getListWhereCondition(int id, String name, Date createTime) {
        name = name == "" ? null : name;
        SqlSession session = MybatisUtils.getSqlSession();
        BasicQueryArgs args = new BasicQueryArgs(id, name, createTime);
        IVisitorOperation vOperation = session.getMapper(IVisitorOperation.class);
        List<Visitor> ls = vOperation.getListWhereDemo(args);
        if (ls.size() == 0)
            System.out.println("查无匹配!");
        else {
            for (Visitor visitor : ls) {
                System.out.println(visitor);
            }
        }
    }

    /*
     * 动态查询choose when实例
     */
    public static void getListChooseWhenDemo(int id, String name, Date createTime) {
        name = name == "" ? null : name;
        SqlSession session = MybatisUtils.getSqlSession();
        BasicQueryArgs args = new BasicQueryArgs(id, name, createTime);
        IVisitorOperation vOperation = session.getMapper(IVisitorOperation.class);
        List<Visitor> ls = vOperation.getListChooseWhenDemo(args);
        if (ls.size() == 0)
            System.out.println("查无匹配!");
        else {
            for (Visitor visitor : ls) {
                System.out.println(visitor);
            }
        }
    }
DemoRun方法

最后一章会讲述,怎么MybatisGenerator生成工具生成这些配置与文件~

相关文章
相关标签/搜索