Mybatis—动态SQL之常用标签的使用

前言

今天我们来聊聊Mybatis的动态SQL的使用,动态SQL可以说是mybatis的核心,可以对SQL语句进行灵活操作,通过表达式进行判断,对SQL进行灵活拼接,组装。在实际项目开发中,我们还可以将在业务层处理的逻辑转移到SQL中进行处理,因为SQL语句通常会比程序代码执行的要快,毕竟数据库是专门做数据处理和计算的嘛。

我们以 student_score 表为例来说明:
在这里插入图片描述

if+where 语句

SQL语句中 < if > 标签和代码中的 if 语句作用是一样的,都是条件判断。加上 if 标签的SQL语句会自动的去判断传入的条件是否为空。

1、< if >标签的使用

	//会自动去判断传入的 name 和 math 是否为空,
	//如果name为空则SQL语句中不会拼接 name=?查询语句
	//如果math为空则SQL语句中不会拼接 math=?查询语句
    <select id="findByName" resultType="com.agri.wen.entity.StudentEntity">
         SELECT
         sc.id,sc.name
         FROM
         student_score sc
         WHERE 1=1
        <if test="name !=null and name!=''">
            sc.name=#{name}
        </if>
        <if test="math !=null and math!=''">
            sc.math=#{math}
        </if>
         ORDER BY
         sc.math DESC
     </select>

上述SQL完成的查询:
1、当name不为空,math为空时,根据name去查询
2、当math不为空,name为空时,根据math去查询
3、当name和math都不为空,同时根据name和math去查询
4、当name和math都为空,无条件查询表中数据。where后加 1=1 恒等式是为了避免当查询条件全都为空时报错。

2、< if > + < where >标签的使用

    <select id="findByName" resultType="com.agri.wen.entity.StudentEntity">
         SELECT
         sc.id,sc.name
         FROM
         student_score sc
        <where>
            <if test="name !=null and name!=''">
                sc.name=#{name}
            </if>
            <if test="math !=null and math!=''">
               and sc.math=#{math}
            </if>
        </where>
         ORDER BY
         sc.math DESC
     </select>

注意:
1、 < where > 标签会判断如果它包含的标签中有返回值的话,它就插入一个 where
2、如果标签返回的内容是以AND 或OR开头的,它会自动剔除掉。
比如:当 name 为空并且 math 不为空时,此时标签返回的内容是以 and 开头的,这是 where 标签会自动把 and 剔除掉。
3、如果使用了 < where > 标签,当条件都为空时,此时SQL语句的作用是没有条件查询表中数据。
(此时不加1=1恒等式也不会报错)

SQL 片段

在Mapper文件中可以定义SQL片段,有时候某个SQL语句(或某些查询字段)可能用的很多,就可以把这块SQL语句抽离出来写成SQL片段。定义后的SQL语句可以引用该SQL片段,简化代码,从而使代码得到复用。

1、重复使用的字段

 <sql id="studentCoreInfo">
    (id,`name`,math,english)
 </sql>
 
 <insert id="insertByEntity">
        insert into
        student_score
        <include refid="studentCoreInfo"/>
        values
        <foreach collection="studentList" item="list" index="index" separator=",">
            (#{list.id},#{list.name},#{list.math},#{list.english})
        </foreach>
 </insert>

2、重复使用的SQL语句

   <sql id="ByNameAndMathSQL">
        <if test="math !=null and math!=''">
        and math=#{math}
        </if>
        <if test="name!=null and name!=''">
        and name=#{name}
        </if>
   </sql>
	
   <select id="findByName" resultType="com.agri.wen.entity.StudentEntity">
        SELECT
        *
        FROM
        student_score sc
        WHERE 1=1
        <include refid="ByNameAndMathSQL"/>
        ORDER BY
        sc.math DESC
    </select>

注意:
1、where后加 1=1 恒等式是为了避免当查询条件全都为空时报错。
2、最好基于单表来定义SQL片段,提高片段的可重用性。
3、在SQL片段中最好不要包括where

foreach 语句

我们可以使用 foreach 标签 来做循环操作,比如批量插入,批量更新等。当向 SQL 传递数组,List 或 Map 时可以使用 foreach 解析。

先来看下foreach标签中的几个属性:

collection:指定输入对象中的集合属性
item:每次遍历生成的对象
open:开始遍历时的拼接字符串
close:结束时拼接的字符串
separator:遍历对象之间需要拼接的字符串

1、foreach 标签的使用

需求:根据list集合中的id和English去更新表中name和math字段的值,实现批量更新。
Dao层代码:

Boolean updateByEntity(@Param("studentEntities") List<StudentEntity> studentEntities);

Mapper:

   //对list集合做批量更新操作
   //根据list中的id和English去更新表中name和math字段
  <update id="updateByEntity">
        <foreach collection="studentEntities" item="entity" open="" close="" separator=";">
            UPDATE student_score sc
            SET sc.NAME = #{entity.name},
            sc.math = #{entity.math}
            WHERE
            sc.id = #{entity.id} and sc.english=#{entity.english}
        </foreach>
    </update>

注意:
数据库链接URL地址要加上 &allowMultiQueries=true ,默认不支持同时执行多条语句。
打印出来的SQL语句:
在这里插入图片描述

2、foreach标签结合 case when的使用

需求:根据list集合中的id去更新表中name和math字段的值,实现批量更新。
Dao层代码:

Boolean updateByEntity(@Param("studentEntities") List<StudentEntity> studentEntities);

Mapper:

    <update id="updateByEntity">
         update student_score sc
         set name=
         <foreach collection="studentEntities" item="entity" separator=" " open="case id" close="end ,">
             when #{entity.id} then #{entity.name}
         </foreach>
         math=
         <foreach collection="studentEntities" item="entity" separator=" " open="case id" close="end">
             when #{entity.id} then #{entity.math}
         </foreach>
         where id in
         <foreach collection="studentEntities" item="entity" separator="," open="(" close=")">
             #{entity.id}
         </foreach>
     </update>

此时数据库链接URL地址不需要加 &allowMultiQueries=true 同时执行多条语句的配置,因为这种写法是在一条SQL中完成的更新操作。

打印出来的SQL语句:
在这里插入图片描述

choose(when ,otherwise)语句

有时候我们不想用到所有的查询条件,只想选择其中一个,查询条件有一个满足即可,使用choose标签可以解决这种情况,类似java的switch语句。

   <select id="QueryByNameIdMath" resultType="com.agri.wen.entity.StudentEntity">
        SELECT
        *
        FROM
        student_score sc
        <where>
            <choose>
                <when test="name !=null and name!=''">
                    sc.name=#{name}
                </when>
                <when test="math !=null and math!=''">
                    and sc.math=#{math}
                </when>
                <otherwise>
                    and id=#{id}
                </otherwise>
            </choose>
        </where>
        ORDER BY
        sc.math DESC
    </select>

虽然SQL中写了三个查询条件,但是只能选择一个作为查询条件
1、如果name不为空,查询语句就是根据name条件进行查询
2、如果name为空,那么看math是否为空,如果不为空,那么查询语句就是根据math条件去进行查询
3、如果name为空,math也为空,那么查询条件为根据id去进行查询
4、如果name为空,math不为空,id也不为空,此时查询语句是根据math去进行查询, id 的查询条件并不会一起查询。只能选择一个作为查询条件。

猜你喜欢

转载自blog.csdn.net/Sophia_0331/article/details/106727400
今日推荐