--------------------------------MaBatis动态sql--------------------------

1)动态SQL基于OGNL的表达式,可以方便的在SQL语句中实现某些逻辑,用于实现动态SQL的元素如下:

  (1)if:利用if实现简单的条件选择。

  (2)choose(when,otherwise):相当于Java中的switch语句。通常与when和otherwise搭配。

  (3)where :简化SQL语句中where的条件判断,主要用来简化SQL语句中的where条件判断,并能智能的处理and和          or,不必要担心关键字导致的语法错误。

       (4)set:解决动态更新语句

  (5)trim:可以灵活的去除多余的关键字。

  (6)foreach:迭代一个集合,通常用于in条件

2) 

现在前台有个表单!
表单中有三项条件 来查询 符合条件的学生!
01.根据学生姓名查询
02.根据老师姓名查询
03.根据年级名称查询

针对于上述的情况,我们发现三个查询条件 不在同一个表中!

第一种情况:

  把学生姓名,老师姓名,年级名称封装成一个Map集合
  Map<String.Object>  map=new  HashMap<String,Object>();
  //把三个条件放进map
  map.put("studentName",学生姓名);
  map.put("teacherName",老师姓名);
  map.put("gradeName",年级名称);
  //调用dao层方法
  dao.xxx(map);

  然后去mapper.xml文件中执行sql语句

  select s.name,s.id,s.age  from  student s,teacher t,grade g
  where s.tId=t.id and s.gId=g.id
  and s.name=#{studentName}   //开始使用map中的key
  and t.name=#{teacherName}
  and g.name=#{gradeName}


第二种情况:

   用户可以传递几个参数,我们在方法定义时就书写几个形参!

   在接口中书写方法

   List<Student> selectStduentsByCondition(String stuName,String teacherName,String gradeName);

  在mapper.xml文件中书写sql

 select s.name,s.id,s.age  from  student s,teacher t,grade g
  where s.tId=t.id and s.gId=g.id
  and s.name=#{0}   //开始使用参数的下标
  and t.name=#{1}
  and g.name=#{2}



总结#{}中可以存放的内容

01. 当参数是对象的时候,存放的是对象的属性
02. 存放map时的注意点
    001.当参数是map集合时,存放的是map的key
    002.如果map的value是对象时,存放的是对象的属性
03.如果传递一个参数,存放的是占位符
04.如果传递多个参数,存放的是参数对应的下标,从0开始
<mapper namespace="com.xdf.dao.StudentDao"> <!--必须是对应的dao接口的全类名-->

    <!--
      我们在前台表单中  有 三个输入框!
      用户输入了几个???我们不知道
      #{stuName}#{stuAge}
      必须是map集合中的key
    <select id="selectStduentsByMap" resultType="Student">
     select id,name,age from student
     where name like  concat('%',#{stuName},'%')
     and  age>#{stuAge}
    </select> -->

    <select id="selectStduentsByMap" resultType="Student">
        select id,name,age from student
        where name like  concat('%',#{stuName},'%')
        and  age>#{stuAge}
        AND  id>#{student.id}
    </select>

    <!--按照参数的下标进行封装   下标从0开始-->
    <select id="selectStduentsByCondition" resultType="Student">
        select id,name,age from student
        where name like  concat('%',#{0},'%')
        and  age>#{1}
    </select>


</mapper>

 上面都是写死的。没用动态标签,看下面

<mapper namespace="com.xdf.dao.StudentDao"> <!--必须是对应的dao接口的全类名-->

   <!-- 01.用户传递一个Student对象  但是我们不知道用户对那些属性赋了值
      注意点  特殊字符的使用
      && (逻辑与)  必须换成 (and) 或者 (&amp;)
      where 1=1  每次拼接查询都会 执行 影响性能
   -->
      <select id="selectStudentsByIf" resultType="Student">
         SELECT  id,name,age from  student  where 1=1
         <if test="name!=null and name!=''">
               and  name like concat('%',#{name},'%')
         </if>
         <if test="age &gt; 0">
               and  age > #{age}
         </if>
      </select>



    <!--where 标签 替换where 1=1-->
      <select id="selectStudentsByWhere" resultType="Student">
         SELECT  id,name,age from  student
          <where>
              <if test="name!=null and name!=''">
                  and  name like concat('%',#{name},'%')
              </if>
              <if test="age &gt; 0">
                  and  age > #{age}
              </if>
          </where>
      </select>


    <!--
    choose标签    类似java中的switch
       01.当我们的年龄不为空 按照年龄查询
       02.当我们的姓名不为空 按照姓名查询
       03.如果都会空 执行otherwise
          如果没有otherwise标签,会查询所有
       04.如果多个条件满足,执行第一个满足的when
    如果条件只允许执行一个  就是用choose
      因为值执行一个sql  所以不需要加and
    想多个条件执行,使用if
      因为有多个sql需要拼接 所以 不能省略and
    在mybatis中 底层不会给我们生成and
    -->
    <select id="selectStudentsByChoose" resultType="Student">
          SELECT  id,name,age from  student
        <where>
           <choose>
                <when test="name!=null and name!=''">
                      name like concat('%',#{name},'%')
                </when>
                <when test="age > 0">
                      age>#{age}
                </when>
               <otherwise>
                 1!=1
              </otherwise>
           </choose>
        </where>
    </select>


    <!-- foreach 遍历数组
    我们之前在mysql中查询的语句
    SELECT  id,NAME,age FROM student   WHERE id IN (12,13,14)
    问题??
    01.我们知道用户输入的是12,13,14,吗???
    02.1213,14是动态获取的  是dao中方法的参数 int [] nums
    03.nums的每个元素 就是  12,13,14
    04.用户是不是有可能一个值都没有传入
    05.只要是数组    在mybatis对应的值就是array
     -->
    <select id="selectStudentsByForeachArray" resultType="Student">
        SELECT  id,NAME,age FROM student
        <if test="array.length>0"> /*证明用户有值传入*/
             where id IN         /*(12,13,14) 动态的拼接*/
            <foreach collection="array" item="varId" open="(" separator="," close=")">
                #{varId}
            </foreach>
        </if>
    </select>

    <!--遍历 List集合  在mybatis对应的值就是list-->
    <select id="selectStudentsByForeachList" resultType="Student">
        SELECT  id,NAME,age FROM student
        <if test="list.size>0">
             where id IN
            <foreach collection="list" item="varId" open="(" separator="," close=")">
                #{varId}
            </foreach>
        </if>
    </select>
    <!--遍历 Student集合 -->
    <select id="selectStudentsByForeachStudent" resultType="Student">
        SELECT  id,NAME,age FROM student
        <if test="list.size>0">
             where id IN
            <foreach collection="list" item="stu" open="(" separator="," close=")">
                #{stu.id} /*必须是对象中的属性*/
            </foreach>
        </if>
    </select>

    <!--遍历 map集合   map集合在mybatis中没有设置对应的值
    myMap就是我们dao层方法的@Param("myMap")
    遍历myMap.keys 就是获取map集合中的所有key的集合
    -->
    <select id="selectStudentsByForeachMap" resultType="Student">
        <include refid="seleteStudents"/>
            where id IN
        <if test="myMap.keys.size>0">
            <foreach collection="myMap.keys"  item="mapKey" open="(" separator="," close=")">
                #{mapKey}
            </foreach>
        </if>
    </select>

    <!--
     sql片段:  提取mapper文件中所有的sql公共部分
    -->

    <sql id="seleteStudents">
          SELECT  id,NAME,age FROM student
    </sql>


</mapper>

4)使用if+trim实现多条件查询

     

trim 属性

                prefix:前缀覆盖并增加其内容

                suffix:后缀覆盖并增加其内容

                prefixOverrides:前缀判断的条件

                suffixOverrides:后缀判断的条件

<where> <if>  
<if>标签单独使用,如下

<select id="selectSudent" parameterType="String" resultType="java.util.List">
    SELECT * FROM student
    <if test="name!=null and name!=''">
        WHERE 
          name like CONCAT('%',#{name},'%')
    </if></select>

如果name为空或空串 则进行全部查询,效率会下降



当进行多条件下查询是,<where> <if>  可以提高查询速度 和优化查询语句
<select id="selectSudent" parameterType="String" resultType="java.util.List">
    SELECT name,sex FROM student
    <where>
        <if test="name!=null and name!=''">
               name like CONCAT('%',#{name},'%')
        </if>        <if test="sex!=null and sex!=''">            AND sex=#{sex}        </if>    </where></select>




<set> <if>
使用
<update id="updateStudent" parameterType="com.frank.Student">
    UPDATE student
    <set>
        <if test="name!=null and name!=''">
            name= #{name},
        </if>
        <if test="sex!=null and sex!=''">
             sex=#{sex}
        </if>
    </set>
    WHERE no=#{no}
</update>



<trim> <if>
我个人感觉<trim>标签就是<where><set>结合 他同时具有两者的功能

<select id="selectSudent" parameterType="String" resultType="java.util.List">
    SELECT name,sex FROM student
    <trim prefix="WHERE" prefixOverrides="AND|OR">
        <if test="name!=null and name!=''">
         name like CONCAT('%',#{name},'%')
        </if>
        <if test="sex!=null and sex!=''">
            AND sex=#{sex}
        </if>
    </trim>
</select>

<update id="updateStudent" parameterType="com.frank.Student">
    UPDATE student
    <trim prefix="SET" suffixOverrides=",">
        <if test="name!=null and name!=''">
            name= #{name},
        </if>
        <if test="sex!=null and sex!=''">
             sex=#{sex}
        </if>
    </trim>
    WHERE no=#{no}
</update>
原文地址:https://www.cnblogs.com/laosunlaiye/p/7586867.html