IT培训-高端面授IT培训机构
云和教育:云和数据集团高端IT职业教育品牌 全国咨询热线:0371-67988003
课程 请选择课程
    校区 请选择校区
      • 华为
        授权培训中心
      • 腾讯云
        一级认证培训中心
      • 百度营销大学
        豫陕深授权运营中心
      • Oracle甲骨文
        OAEP中心
      • Microsoft Azure
        微软云合作伙伴
      • Unity公司
        战略合作伙伴
      • 普华基础软件
        战略合作伙伴
      • 新开普(股票代码300248)
        旗下丹诚开普投资
      • 中国互联网百强企业锐之旗
        旗下锐旗资本投资

      云和数据大咖分享:Mybatis动态SQL

      • 发布时间:
        2020-09-05
      • 版权所有:
        云和教育
      • 分享:
      MyBatis 令人喜欢的一大特性就是动态 SQL。在使用 JDBC 的过程中, 根据条件进行 SQL 的拼接是很麻烦且很容易出错的。
      MyBatis 动态 SQL 的出现, 解决了这个麻烦。
      动态SQl是MyBatis的强大特性之一,可以完成对SQL语句的动态组装。
      比如说传入一个User对象,要根据这个User中的数据查询用户的完整信息:
      如果User对象中只有name属性有值,sql语句是:select * from user_tb  where name=#{name}

      如果User对象中只有tel属性有值,sql语句是:select * from user_tb where tel=#{tel}

      如果User对象的name、tel都有值,sql语句是:select * from user_tb where name=#{name} and tel=#{tel}

      有时候sql语句不是一成不变的,要根据传入的数据动态生成要执行的sql语句,动态sql就适合这种情况。
      最好将日志的控制台输出级别设置为DEBUG,这样在控台能看到SQL语句。
      1.MyBatis中的动态sql元素

      <if>  相当于java中的if,用于单分支的条件判断

      <choose>、<when>、<otherwise>  相当于java中的switch…case…default,用于多分支的条件判断,从多个选项中选择一个

      <foreach> 循环,常和sql的in语句搭配使用

      <where>、<trim>、<set>  辅助元素,用于一些处理sql拼装、特殊字符的问题

      2.<where>、<if>的使用

      xml

      <select id=”queryUser” parameterType=”user” resultType=”user”>

      SELECT * FROM user_tb

      <where>

      <if test=”name!=null and name!=””>

      name=#{name}

      </if>

      <if test=”tel!=null and tel!=””>

      AND tel=#{tel}

      </if>

      </where>

      </select>

      <where>相当于sql语句中的关键字WHERE。

      <if>中的test表示条件,条件成立就把元素体中的字符串拼接到sql语句中,否则不拼接。

      > test属性的注意点

      > 相等判断:==,!=

      > 逻辑与:只能用and,不能用&&

      > 逻辑或:or、||均可

      tel不进行数学运算,使用字符串类型。

      <where>中有<if>成立时,<where>才会在sql语句中添加WHERE关键字,否则不添加。

      <where>会自动剔除元素体中多余的AND、OR。

      比如传入的User对象只设置了tel,拼接的sql语句是:SELECT  *  FROM  user_tb  WHERE  AND  tel=#{tel},<where>会自动剔除多余的AND。

      不使用<where>的写法:

      xml

      <select id=”queryUser” parameterType=”user” resultType=”user”>

      SELECT * FROM user_tb  WHERE 1=1

      <if test=”name!=null and name!=””>

      AND name=#{name}

      </if>

      <if test=”tel!=null and tel!=””>

      AND tel=#{tel}

      </if>

      </select>

      <where>会自动去掉多余的AND,但不会自动加上缺少的AND,我们通常在每个<if>中都加上AND,防止把AND写掉了。

      3.<trim>的使用

      <trim>可以定制需要的功能,比如使用<trim>达到<where>的效果:

      xml

      <select id=”queryUser” parameterType=”user” resultType=”user”>

      SELECT * FROM user_tb

      <trim prefix=”WHERE” prefixOverrides=”AND”>

      <if test=”name!=null and name!=””>

      name=#{name}

      </if>

      <if test=”tel!=null and tel!=””>

      AND tel=#{tel}

      </if>

      </trim>

      </select>

      prefix会在这段字符串之前加上指定的前缀,如果里面的<if>都不满足条件,则不加前缀。

      prefixOverrides指定要去除的多余的字符串。

      4.<choose>、<when>、<otherwise>的使用

      有时候我们只需要从多个选项中选择一个,比如登录教务系统,让你选择角色:数据库管理员、教职工、学生:

      xml

      <select id=”queryPwd” parameterType=”user” resultType=”string”>

      SELECT password FROM user_tb WHERE name=#{name}

      <choose>

      <when test=”role==’admin'”>

      AND role=’admin’

      </when>

      <when test=”role==’teacher'”>

      AND role=’teacher’

      </when>

      <when test=”role==’student'”>

      AND role=’student’

      </when>

      </choose>

      </select>

      传入的值是admin、teacher、student,数据库中的role字段也是这几个值,这种传入的值和数据库中存储的值一致的可以直接这样写:

      xml

      <select id=”queryPwd” parameterType=”user” resultType=”string”>

      SELECT password FROM user_tb WHERE name=#{name} AND role=#{role}

      </select>

      如果不一致,比如性别,传入的是male、female,数据库中存储的是0、1,就需要使用<choose>转换一下。

      xml

      <choose>

      <when test=””>

      </when>

      <when test=””>

      </when>

      <otherwise>

      </otherwise>

      </choose>

      <choose>相当于switch,<when>相当于case,<otherwise>相当于default。

      5.<set>的使用

      更新操作传入一个pojo类的对象,但我们并不知道哪些属性是有值的(需要更新的),不能更新全部字段,因为有的字段没有手动赋值,不能用JVM赋的null、0去覆盖数据表中原来的值。

      <set>可解决此问题:

      xml

      <select id=”updateUser” parameterType=”user”>

      UPDATE user_tb

      <set>

      <if test=”name!=null and name!=””>

      name=#{name},

      </if>

      <if test=”tel!=null and tel!=””>

      tel=#{tel},

      </if>

      <if test=”address!=null and address!=””>

      name=#{name},

      </if>

      </set>

      where id=#{id}

      </select>

      <set>用于传入pojo类型,更新数据表的多个字段。先判断字段是否有值,有值才更新该字段。

      <set>用于更新操作,会自动在这段字符串前面加sql关键字“SET”(里面有<if>为真),并自动去除多余的逗号(一般自己写第一个<if>,然后copy下来改,最后面往往会多一个逗号)。

      如果里面的<if>都为假,即没有要更新的字段,不会自动在前面加”SET”,此时这个update语句有语法错误,会报错,所以要保证至少有一个字段需要更新。

      6.<foreach>的使用

      <foreach>用于迭代集合、数组,常配合sql的关键字in使用,用于增删查改的批量操作。

      示例:按照手机号随机抽取3位幸运观众(根据手机号码查询用户信息)——批量查。

      xml

      <select id=”queryUser” parameterType=”list” resultType=”user”>

      SELECT * FROM user_tb WHERE tel IN

      <foreach collection=”list” index=”index” item=”item” open=”(” separator=”,” close=”)”>

      #{item}

      </foreach>

      </select>

      java

      ArrayList<String> telList = new ArrayList<>();

      telList.add(“110”);

      telList.add(“119”);

      telList.add(“120”);

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

      List<User> userList = mapper.queryUser(telList);

      System.out.println(userList);

       collection   要迭代的数据类型,数组=>array,List=>list,Map=>Map的key的数据类型。使用数组容易出错,尽量用List代替数组。

      index   本次迭代的下标,指定一个临时变量表示下标

      item   本次迭代的元素,指定一个临时变量表示本次迭代的元素

      open   拼接这段字符串时以什么开头

      close  拼接这段字符串以什么结尾

      separator   迭代的元素之间用什么连接(分隔)

      collection是必需的,其余均可选。

      更严谨的写法:

      xml

      <select id=”queryUser” parameterType=”list” resultType=”user”>

      SELECT * FROM user_tb WHERE tel IN

      <if test=”list!=null and list.size>0″>

      <foreach collection=”list” index=”index” item=”item” open=”(” separator=”,” close=”)”>

      #{item}

      </foreach>

      </if>

      </select>

      如果传入的是List类型,要使用List对象本身时,约定使用list表示List对象本身。

      文/云和数据高级JAVA开发工程师