有时候,静态的SQL语句并不能满足应用程序的需求。我们可以根据一些条件,来动态地构建SQL语句。例如,在Web应用程序中,有可能有一些搜索界面,需要输入一个或多个选项,然后根据这些已选择的条件去执行检索操作。在实现这种类型的搜索功能,我们可能需要根据这些条件来构建动态的SQL语句。如果用户提供了任何输入条件,我们需要将那个条件 添加到SQL语句的WHERE子句中。

MyBatis通过使用<if>,<choose>,<where>,<foreach>,<trim>元素提供了对构造动态SQL语句的高级别支持。

  1. if
    语句

    <if>元素被用来有条件地嵌入SQL片段,如果测试条件被赋值为true,则相应地SQL片段将会被添加到SQL语句中。

    假定我们有一个课程搜索界面,设置了 讲师(Tutor)下拉列表框,课程名称(CourseName)文本输入框,开始时间(StartDate)输入框,结束时间(EndDate)输入框,作为搜索条件。假定课讲师下拉列表是必须选的,其他的都是可选的。

    当用户点击 搜索按钮时,我们需要显示符合以下条件的成列表:

  •   特定讲师的课程
  •   课程名包含输入的课程名称关键字的课程;如果课程名称输入为空,则取所有课程
  •   在开始时间和结束时间段内的课程

我们可以对应的映射语句,如下所示:

<resultMap
type="Course"
id="CourseResult">

    <id
column="course_id"
property="courseId"
/>

    <result
column="name"
property="name"
/>

    <result
column="description"
property="description"
/>

    <result
column="start_date"
property="startDate"
/>

    <result
column="end_date"
property="endDate"
/>

</resultMap>

<!-- 查询输入参数定义为 hashmap 类型 -->

<select
id="searchCourses"
parameterType="hashmap"
resultMap="CourseResult">

        SELECT * FROM COURSES

                WHERE TUTOR_ID= #{tutorId}

        <if
test="courseName != null">

        AND NAME LIKE #{courseName}

        </if>

        <if
test="startDate != null">

        AND START_DATE >= #{startDate}

        </if>

        <if
test="endDate != null">

        AND END_DATE <= #{endDate}

        </if>

</select>

Java代码如下:

    public interface CourseMapper

    {

     List<Course> searchCourses(Map<String, Object> map);

    }

    public
void
searchCourses()

    {

     Map<String, Object> map = new HashMap<String, Object>();

     map.put("tutorId", 1);

     map.put("courseName", "%java%");

     map.put("startDate", new
Date());

     CourseMapper mapper = sqlSession.getMapper(CourseMapper.class);

     List<Course> courses = mapper.searchCourses(map);

     for (Course course : courses)

     {

System.out.println(course);

     }

    }

  1. choose,when 和otherwise 条件

    有时候,查询功能是以查询类别为基础的。首先,用户需要选择是否希望通过选择讲师,课程名称,开始时间,或结束时间作为查询条件类别来进行查询,然后根据选择的查询类别,输入相应的参数。在这样的情景中,我们需要只使用其中一种查询类别。

    MyBatis 提供了<choose>元素支持此类型的SQL预处理。

    现在让我们书写一个适用此情景的SQL映射语句。如果没有选择查询类别,则查询开始时间在今天之后的课程,代码如下:

    <select
    id="searchCourses"
    parameterType="hashmap"
    resultMap="CourseResult">

            SELECT * FROM COURSES

            <choose>

                    <when
    test="searchBy == 'Tutor'">

                            WHERE TUTOR_ID= #{tutorId}

                    </when>

                    <when
    test="searchBy == 'CourseName'">

                            WHERE name like #{courseName}

                    </when>

                    <otherwise>

                            WHERE TUTOR start_date >= now()

                    </otherwise>

            </choose>

    </select>

    MyBatis计算<choose>测试条件的值,且使用第一个值为TRUE的子句。如果没有条件为true,则使用<otherwise>内的子句。

  2. where
    条件

    有时候,所有的查询条件(criteria)应该是可选的。在需要使用至少一种查询条件的情况下,我们应该使用WHERE子句。并且, 如果有多个条件,我们需要在条件中添加AND或OR。MyBatis提供了<where>元素支持这种类型的动态SQL语句。

    在我们查询课程界面,我们假设所有的查询条件是可选的。进而,当需要提供一个或多个查询条件时,应该改使用WHERE子句。

    <select
    id="searchCourses"
    parameterType="hashmap"
    resultMap="CourseResult">

            SELECT * FROM COURSES

            <where>

                    <if
    test=" tutorId != null ">

                            TUTOR_ID= #{tutorId}

                    </if>

                    <if
    test="courseName != null">

                            AND name like #{courseName}

                    </if>

                    <if
    test="startDate != null">

                            AND start_date >= #{startDate}

                    </if>

                    <if
    test="endDate != null">

                            AND end_date <= #{endDate}

                    </if>

            </where>

    </select>

    <where>元素只有在其内部标签有返回内容时才会在动态语句上插入WHERE条件语句。并且,如果WHERE子句以AND或者OR打头,则打头的AND或OR将会被移除。如果tutor_id参数值为null,并且courseName参数值不为null,则<where>标签会将AND name like#{courseName} 中的AND移除掉,生成的SQL WHERE子句为:where name like#{courseName}。

  3. trim条件

    <trim>元素和<where>元素类似,但是<trim>提供了在添加前缀/后缀 或者移除前缀/后缀方面提供更大的灵活性

    <select
    id="searchCourses"
    parameterType="hashmap"
    resultMap="CourseResult">

    SELECT * FROM COURSES

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

    <if
    test=" tutorId != null ">

    TUTOR_ID= #{tutorId}

    </if>

    <if
    test="courseName != null">

    AND name like #{courseName}

    </if>

    </trim>

    </select>

    这里如果任意一个<if>条件为true,<trim>元素会插入WHERE,并且移除紧跟WHERE后面的AND或OR

  4. foreach循环

    另外一个强大的动态SQL语句构造标签即是<foreach>。它可以迭代遍历一个数组或者列表,构造AND/OR条件或一个IN子句。

    假设我们想找到tutor_id为1,3,6的讲师所教授的课程,我们可以传递一个tutor_id组成的列表给映射语句,然后通过<foreach>遍历此列表构造动态SQL。

    注意:如果参数类型为
    List
    则其 <foreach…/> 的
    collection
    设置为
    list,如果为
    map
    则设置为集合的
    key
    名称。

    <select
    id="searchCoursesByTutors"
    parameterType="map"
    resultMap="CourseResult">

    SELECT * FROM COURSES

    <if
    test="tutorIds != null">

    <where>

    <foreach
    item="tutorId"
    collection="tutorIds">

    OR tutor_id=#{tutorId}

    </foreach>

    </where>

    </if>

    </select>

     
     

    Java代码:

    public interface CourseMapper

    {

            List<Course> searchCoursesByTutors(Map<String, Object> map);

    }

    public
    void
    searchCoursesByTutors()

    {

            Map<String, Object> map = new HashMap<String, Object>();

            List<Integer> tutorIds = new ArrayList<Integer>();

            tutorIds.add(1);

            tutorIds.add(3);

            tutorIds.add(6);

            map.put("tutorIds", tutorIds);

            CourseMapper mapper =

                    sqlSession.getMapper(CourseMapper.class);

            List<Course> courses = mapper.searchCoursesByTutors(map);

            for (Course course : courses)

            {

                    System.out.println(course);

            }

    }

    现在让我们来看一下怎样使用<foreach>生成 IN子句:

    <select
    id="searchCoursesByTutors"
    parameterType="map"
    resultMap="CourseResult">

            SELECT * FROM COURSES

            <if
    test="tutorIds != null">

                    <where>

    tutor_id IN

                            <foreach
    item="tutorId"
    collection="tutorIds"  open="("
    separator=","
    close=")">

     #{tutorId}

                            </foreach>

                    </where>

            </if>

    </select>

  5. set条件

    <set>元素和<where>元素类似,如果其内部条件判断有任何内容返回时,他会插入SET SQL片段。

    <update
    id="updateStudent"
    parameterType="Student">

            update students

            <set>

            <if
    test="name != null">name=#{name},</if>

            <if
    test="email != null">email=#{email},</if>

            <if
    test="phone != null">phone=#{phone},</if>

            </set>

            where stud_id=#{id}

    </update>

    这里,如果<if>条件返回了任何文本内容,<set>将会插入set关键字和其文本内容,并且会剔除将末尾的 ","。

    在上述的例子中,如果 phone!=null,<set>将会让会移除 phone=#{phone}后的逗号",",生成 set phone=#{phone} 。

     
     

笔记:MyBatis 动态SQL的更多相关文章

  1. MyBatis:学习笔记(4)——动态SQL

    MyBatis:学习笔记(4)——动态SQL 如果使用JDBC或者其他框架,很多时候需要你根据需求手动拼装SQL语句,这是一件非常麻烦的事情.MyBatis提供了对SQL语句动态的组装能力,而且他只有 ...

  2. MyBatis:学习笔记(4)——动态SQL

    MyBatis:学习笔记(4)——动态SQL

  3. mybatis实战教程(mybatis in action)之八:mybatis 动态sql语句

    mybatis 的动态sql语句是基于OGNL表达式的.可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类:1. if 语句 (简单的条件判断)2. c ...

  4. mybatis原理分析学习记录,mybatis动态sql学习记录

    以下个人学习笔记,仅供参考,欢迎指正. MyBatis 是支持定制化 SQL.存储过程以及高级映射的持久层框架,其主要就完成2件事情: 封装JDBC操作 利用反射打通Java类与SQL语句之间的相互转 ...

  5. 记Mybatis动态sql

    目录 记MyBatis动态SQL 1.< SQL >标签 2.< if >标签 3.分支标签 1.第一种:用在查询条件上用choose-when:otherwise可不要 2. ...

  6. 9.mybatis动态SQL标签的用法

    mybatis动态SQL标签的用法   动态 SQL MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么 ...

  7. 自己动手实现mybatis动态sql

    发现要坚持写博客真的是一件很困难的事情,各种原因都会导致顾不上博客.本来打算写自己动手实现orm,看看时间,还是先实现一个动态sql,下次有时间再补上orm完整的实现吧. 用过mybatis的人,估计 ...

  8. Mybatis动态SQL单一基础类型参数用if标签

    Mybatis动态SQL单一基础类型参数用if标签时,test中应该用 _parameter,如: 1 2 3 4 5 6 <select id="selectByName" ...

  9. 超全MyBatis动态SQL详解!( 看完SQL爽多了)

    MyBatis 令人喜欢的一大特性就是动态 SQL. 在使用 JDBC 的过程中, 根据条件进行 SQL 的拼接是很麻烦且很容易出错的. MyBatis 动态 SQL 的出现, 解决了这个麻烦. My ...

  10. Mybatis动态SQL简单了解 Mybatis简介(四)

    动态SQL概况 MyBatis 的强大特性之一便是它的动态 SQL 在Java开发中经常遇到条件判断,比如: if(x>0){ //执行一些逻辑........ }   Mybatis应用中,S ...

随机推荐

  1. linux系统/sbin/init执行过程

    对于Linux的启动过程,之前一直都是研究到内核运行/sbin/init,启动第一个用户进程为止,因为这部分一直都是在内核态工作,所以对于学习内核还是有帮助的,当时/sbin/init之后的过程也需要 ...

  2. 安装Apache提示APR not found的解决办法

    不知道为什么在安装apache2.2.22版本的时候没有任何问题,直接使用命令 ./configure --prefix=/home/www/www_test/software/apache-2.2. ...

  3. eclipse怎么恢复原状

    eclipse怎么恢复原状 今天,我在写JSP页面时,将eclipse缩小窗口,后来我准备恢复,但是窗口却变成下面的状态

  4. ASP.NET 页面双向静态化

    而我们预期的结果应该如下图,实际只请求两次. 用301重定向可以解决该循环请求产生的问题. OK, let's begin. 本文的Demo和Source是基于上一篇的,如果下面的一些文件或文件夹没有 ...

  5. python爬虫--爬取某网站电影信息并写入mysql数据库

    书接上文,前文最后提到将爬取的电影信息写入数据库,以方便查看,今天就具体实现. 首先还是上代码: # -*- coding:utf-8 -*- import requests import re im ...

  6. 翻译--Thinking in React

    无聊翻译篇react入门文章,去年学习react时看了一遍,很不错的一篇文章. https://reactjs.org/docs/thinking-in-react.html 部分为意译,旨在让new ...

  7. 【Java入门提高篇】Day14 Java中的泛型初探

    泛型是一个很有意思也很重要的概念,本篇将简单介绍Java中的泛型特性,主要从以下角度讲解: 1.什么是泛型. 2.如何使用泛型. 3.泛型的好处. 1.什么是泛型? 泛型,字面意思便是参数化类型,平时 ...

  8. 手机端仿ios的1-n级联动脚本二

    一,图片 二,代码 2.1,html脚本 var weekdayArr=['周日','周一','周二','周三','周四','周五','周六'];var timeArr = ['08:30','09: ...

  9. [POJ2774]Long Long Message

    vjudge 一句话题意 给两个串,求最长公共子串. sol 把两个串接在一起求后缀数组.其实中间最好用一个没有出现过的字符连接起来. 判断如果\(SA[i]\)和\(SA[i-1]\)不属于同一个串 ...

  10. [UOJ207]共价大爷游长沙

    UOJ sol 这题真是太神啦! 对于S集合中的每个点对,给他们随机附上一个相同权值. 两个点在边(x,y)的两侧当且仅当一个点在x的子树中,另一个点不在x的子树中(假设x是y的儿子) 维护一下子树点 ...