一步一步学完MyBatis的动态sql标签

写在前面
大家好,我是Think-Coder,比较通俗的暱称,寓意是做一个有思考的程序猿,现在的状态是边做项目边学习;

博客是我平时做项目和学习的过程,很基础,但是每一篇我很认真在写,力求让读者,读的清楚,看的明白。

不是大佬,但努力成为,如果您也对Java、算法感兴趣,可以相互关注,一起成长,相信滴水穿石的力量

一、基础知识

动态sql是什么

  • 动态SQL指的是事先无法预知具体的条件,需要在运行时根据具体的情况动态地生成SQL语句

动态sql作用

二、动态sql标签总览

在这里插入图片描述
参考了网上大佬的博客,开头的博客已经涉及了前两个分支,接着写向下的分支

本篇博客的练习是基于之前的博客环境搭建,因为Dao层接口和测试类大同小异,所以下面只给出映射文件中的sql语句

三、动态sql标签详解

3.1 控制sql语句拼接

3.1.1 if标签

  • 如:<if test=“address != null”>,test属性判断address字段值是否为空

作用

  • 用于select、insert、update语句中
  • 根据参数判断值判断使用哪个查询条件,是否更新某个字段,是否插入某个字段

举例

    <select id="findByUser" resultType="com.thinkcoder.domain.User" parameterType="com.thinkcoder.domain.User">
        select
            id,
            username,
            birthday,
            sex,
            address
        from
            user
        where
            1=1
        <if test="username !=null and username != ''"> //判断username值是否为空
            and username like #{username}
        </if>
        <if test="address != null">                   //判断address值是否为空
            and address like #{address}
        </if>
    </select>

生成的sql语句
假如username值为空,address值不为空

select id,username,birthday,sex,address
from user
where 1=1
and address like #{address}

3.1.2 choose|when|otherwise标签

一般这三个标签一起使用,相当于java中switch语句

  • choose为switch
  • when为case
  • otherwise为default

标签执行流程
在这里插入图片描述

Mybatis提供choose元素,按顺序判断when中条件是否成立
如果一个成立,choose结束
当when所有的条件都不满足时,则执行otherwise中的sql语句

举例

    <select id="findByUser" resultType="com.thinkcoder.domain.User" parameterType="com.thinkcoder.domain.User">
        select
            id,
            username,
            birthday,
            sex,
            address
        from
            user
        where
            1=1
        <choose>
            <when test="username !=null and username != ''">
                and username like #{username}
            </when>
            <when test="address != null">
                and address like #{address}
            </when>
            <otherwise>
                and sex='男'
            </otherwise>
        </choose>
    </select>

生成的sql语句
假如现在username不为空

select id,username,birthday,sex,address
from user
where 1=1
and username like #{username}

直接拼接第一个when元素的后面的sql语句,下面的when和otherwise元素不再判断

if和choose标签区别

  • if可以将所有的sql语句拼接起来,choose|when|otherwise只选择其中的一个标签下的sql语句

3.1.3 foreach标签

作用

  • 遍历集合,构建in条件语句或者批量操作语句

标签属性

属性 含义
collection 表示迭代集合的名称,可以使用@Param注解指定,必选参数
item 表示本次迭代获取元素,若collection为List类型,表示其中元素,为map类型表示key-value的value
open 表示语句以什么开始,通常为’('左括弧,可选参数
close 表示语句以什么结束,通常为’)'右括弧,可选参数
index List中表示当前迭代位置,Map中表示元素key,可选参数
separator 每次迭代后加的字符

参考网上大佬的博客

举例
1.批量插入用户
测试类代码

    @Test
    public void  bulkInsertUser(){
        List<User> users = new ArrayList<User>();
        users.add(new User("赵一",new Date(),"男","河北邯郸"));
        users.add(new User("钱一",new Date(),"女","河北张家口"));
        users.add(new User("孙一",new Date(),"男","河北石家庄"));

        int ids = userDao.bulkInsertUser(users);
        System.out.println(ids);//3
        //提交事务
        session.commit();
    }

IUserDao接口

    //批量添加用户
    //参数users便为collection属性值
    int bulkInsertUser(@Param(value = "users") List<User> users);

IUserDao.xml映射文件

    <insert id="bulkInsertUser">
        insert into 
        	user(username,birthday,sex,address) 
        values
        <foreach collection="users" item="user" index="index" separator=",">
            (#{user.username},#{user.birthday},#{user.sex},#{user.address})
        </foreach>
    </insert>

生成的sql语句如下

   insert into 
   	   user(username,birthday,sex,address) 
   values
   	   ("赵一","2020-06-03 10:47:59","男","河北邯郸"),
   	   ("钱一","2020-06-03 10:47:59","女","河北张家口"),
   	   ("孙一","2020-06-03 10:47:59","男","河北石家庄")

2.批量查询用户in语句
测试类代码

    @Test //用于测试批量查询用户
    public void findInIds(){
        List<Integer> ids = new ArrayList<Integer>();
        ids.add(77);
        ids.add(78);
        
        List<User> users = userDao.findInIds(ids);
        for(User user : users){
            System.out.println(user);
        }
    }

IUserDao接口

    //批量查询用户
    List<User> findInIds(@Param(value = "ids") List<Integer> ids);

IUserDao.xml映射文件

    <!--批量查询用户-->
    <select id="findInIds" resultType="com.thinkcoder.domain.User">
        select
            id,
            username,
            birthday,
            sex,
            address
        from
            user
        <where>
            <if test="ids != null and ids.size() > 0">
                <foreach collection="ids" open = "id in (" close=")" item="id" separator=",">
                    #{id}
                </foreach>
            </if>
        </where>
    </select>

foreach迭代过程
在这里插入图片描述

生成的sql语句

   select
       id,
       username,
       birthday,
       sex,
       address
   from
       user
   where
   	   id in (77,78)

3.2 格式化输出

3.2.1 where标签

作用

  • 防止多余关键字and 或 or 出现

举例

     where
         1=1
     <if test="username !=null and username != ''"> //判断username值是否为空
         and username like #{username}
     </if>
     <if test="address != null">                   //判断address值是否为空
         and address like #{address}
     </if>

此时1=1的作用就是去掉多余的and或or
如果不用1=1的sql语句

	where 
	and address like #{address}

where 和 and 关键字一起出现,此时sql语句报错,因此就有了where标签

where标签例子

   select
       id,
       username,
       birthday,
       sex,
       address
   from
       user
   <where>
		<if test="username !=null and username != ''"> //判断username值是否为空
	       and username like #{username}
	   </if>
	   <if test="address != null">                   //判断address值是否为空
	       and address like #{address}
	   </if>
   </where>

除了where标签,后面的trim标签也可以实现

3.2.2 trim标签

作用

  • 1.去除sql语句中多余的关键字(如,and,or),逗号
  • 2.在sql语句前拼接"where"、“set”、以及"values(“等前缀,或者添加”)"等后缀

相关属性

属性 描述
prefix sql语句拼接的前缀
suffix sql语句拼接的后缀
prefixOverrides 去除sql语句前面的关键字
suffixOverrides 去除sql语句后面的关键字

举例
1.去除多余的and关键字

   select
       id,
       username,
       birthday,
       sex,
       address
   from
       user
   <trim prefix = "where" prefixOverrides = "and">
		<if test="username !=null and username != ''"> //判断username值是否为空
	       and username like #{username}
	   </if>
	   <if test="address != null">                   //判断address值是否为空
	       and address like #{address}
	   </if>
   </where>

prefix:加上where的前缀
prefixOverrides = “and”:覆盖where相连的and

2.去除多余的逗号,

   <update id="updateUser" parameterType="com.thinkcoder.domain.User">
       update user
       <trim prefix="set" suffixOverrides=",">
           <if test="username != null and username != ''">
               username = #{username},
           </if>
           <if test="sex != null and sex != ''">
               sex = #{sex},
           </if>
       </trim>
       where id=#{id}
   </update>

如果sex为空则sql语句为

  update user set username = #{username},where id=#{id}

此时suffixOverrides=","将set语句后的,去掉

3.2.3 Set标签

作用

  • set标签将多余逗号去掉,一般用于update语句中
   <update id="updateUser" parameterType="com.thinkcoder.domain.User">
       update user
       <set>
           <if test="username != null and username != ''">
               username = #{username},
           </if>
           <if test="sex != null and sex != ''">
               sex = #{sex},
           </if>
       </set>
       where id=#{id}
   </update>

3.3 sql片段复用

  • sql标签:重复的 sql 提取出来
  • include标签:使用sql标签,将重复的sql片段引用起来

举例
sql标签

<!-- 抽取重复的语句代码片段 -->
<sql id="defaultSql">
	select * from user
</sql>

include标签

<!-- 配置查询所有操作 -->
<select id="findAll" resultType="user">
	<include refid="defaultSql"></include>
</select>

<!-- 根据 id 查询 -->
<select id="findById" resultType="com.thinkcoder.domain.User" parameterType="int">
	<include refid="defaultSql"></include>
	where id = #{uid}
</select>

四、总结

基本的内容就总结完毕了,重点在于之后的实践,看完之后记得自己总结下哦,总结出来的东西才是自己的,加油

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章