全网最全MyBatis基于XML使用系列三:动态Sql

Mybatis系列

1、全网最详细的Mybatis介绍和基本使用

2、全网最全MyBatis基于XML使用系列一:全局配置详解

3、全网最全MyBatis基于XML使用系列二:参数、返回结果处理

4、网最全MyBatis基于XML使用系列三:动态Sql

5、全网最全MyBatis基于XML使用系列四:缓存

基于XML的详细使用——动态sql

Mybatis之所以强大,也是因为它具有动态SQL的特性。在实际场景业务中,很多情况不是简单的一句select * from语句就能解决问题,而是需要很多条件的判断和字段的拼接组成,因此Mybatis提供动态SQL来解决这种问题。

动态SQL解决了什么问题?

  • 1、在映射文件中,会编写很多有重叠部分的SQL语句,比如SELECT语句和WHERE语句等这些重叠语句,该如何处理

  • 2、SQL语句中的where条件有多个,但是页面只传递过来一个条件参数,此时会发生问题。

动态SQL有很多标签,再次主要举例常用的标签用法

if标签

  • EmpMapper.xml
<select id="getEmpByCondition" resultType="com.mybatis.bean.Emp">
    select * from emp where
    <if test="empno!=null">
        empno > #{empno} and
    </if>
    <if test="ename!=null">
        ename like #{ename} and
    </if>
    <if test="sal!=null">
        sal > #{sal}
    </if>
</select>
复制代码
  • EmpMapper.java
public List<Emp> getEmpByCondition(Emp emp);
复制代码
  • Test.java
   public void test10() {
       SqlSession sqlSession = sqlSessionFactory.openSession();
       try {
           EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
           Emp emp = new Emp();
           emp.setEmpno(6500);
           emp.setEname("%E%");
           emp.setSal(500.0);
           List<Emp> empByCondition = mapper.getEmpByCondition(emp);
           for (Emp emp1 : empByCondition) {
               System.out.println(emp1);
          }
      } catch (Exception e) {
           e.printStackTrace();
      } finally {
           sqlSession.close();
      }
  }
复制代码

上述代码就是对if标签的简单实用,但是需要主要,如果说传入的参数值为空字符串时会怎么样?这个时候拼接的sql语句就会出现问题,,例如不传参数或者丢失最后一个参数,那么语句中就会多一个where或者and的关键字,因此在mybatis中也给出了具体的解决方案:使用where标签来进行解决。

where标签

where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

<select id="getEmpByCondition" resultType="com.mybatis.bean.Emp">
       select * from emp
    <where>
        <if test="empno!=null">
            empno > #{empno}
        </if>
        <if test="ename!=null">
            and ename like #{ename}
        </if>
        <if test="sal!=null">
            and sal > #{sal}
        </if>
    </where>
</select>
复制代码

trim标签

trim标签一般用于去除sql语句中多余的and关键字,逗号,或者给sql语句前拼接 “where“、“set“以及“values(“ 等前缀,或者添加“)“等后缀,可用于选择性插入、更新、删除或者条件查询等操作

<!--
        trim截取字符串:
        prefix:前缀,为sql整体添加一个前缀
        prefixOverrides:去除整体字符串前面多余的字符
        suffixOverrides:去除后面多余的字符串
        -->
<select id="getEmpByCondition" resultType="com.mybatis.bean.Emp">
        select * from emp
    <trim prefix="where" prefixOverrides="and" suffixOverrides="and">
        <if test="empno!=null">
            empno > #{empno} and
        </if>
        <if test="ename!=null">
            ename like #{ename} and
        </if>
        <if test="sal!=null">
            sal > #{sal} and
        </if>
    </trim>
</select>
复制代码

foreach标签

动态SQL的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。

foreach标签主要是用来做数据的循环遍历

例如:select * from emp where deptno in(1,2,3) 在这样的语句中,传入的参数部分必须依靠foreach遍历才能实现。

<!--foreach是对集合进行遍历
           collection="deptnos" 指定要遍历的集合
           close="" 表示以什么结束
           index="" 给定一个索引值
           item="" 遍历的每一个元素的值
           open="" 表示以什么开始
           separator="" 表示多个元素的分隔符
           -->
  <select id="getEmpByDeptnos" resultType="Emp">
     select * from emp where deptno in
      <foreach collection="deptnos" close=")" index="idx" item="deptno" open="(" separator=",">
         #{deptno}
      </foreach>
  </select>
复制代码

set标签

set标签用于动态更新语句。set 元素可以用于动态包含需要更新的列,忽略其它不更新的列

<update id="updateEmpByEmpno">
    update emp
    <set>
        <if test="empno!=null">    
             empno=#{empno},
        </if>
        <if test="ename!=null">
             ename = #{ename},
        </if>
        <if test="sal!=null">
            sal = #{sal}
        </if>
    </set>
    <where>
      empno = #{empno}
     </where>
</update>
复制代码

bind标签

bind标签允许你在 OGNL 表达式以外创建一个变量,并将其绑定到当前的上下文

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

sql标签

sql标签主要用来定义可重用的 SQL 代码片段,以便在其它语句中使用。 参数可以静态地(在加载的时候)确定下来,并且可以在不同的 include 元素中定义不同的参数值

<select id="selectUsers" resultType="map">
        select
<include refid="userColumns"><property name="testName" value="test1"/></include>,
<include refid="userColumns"><property name="testName" value="test2"/></include>
        from some_table st1
        cross join some_table st2
</select>
复制代码