MyBatis操作数据库进阶——动态SQL

动态 SQL 是根据程序运行时的条件灵活生成不同 SQL 语句‌的技术。它的核心目的是在不修改代码‌ 的前提下,通过条件判断、循环等逻辑,动态拼接 SQL 片段,解决传统 SQL 语句死板、难以应对复杂业务场景的问题。

一、<if> 标签

先来观察下面的图片:

我们在成功注册一个新账号时,可能会让我们填写如上图的用户信息表,但是我们可以选择跳过,也可以选择填写,若选择填写,我们可以选择填写全部信息,也可以选择填写部分信息(入只填写名字和出生日期),将图片提交给后端后,后端需要使用insert语句将这些个人信息保存到数据库,但是并不是所有人都将表中信息完整填写,难道后端需要写多条insert语句吗?显然这非常麻烦,因此我们可以使用动态SQL的标签,如 <if> 来解决这个问题:

一、接口定义

Integer insertUserByCondition(UserInfo userInfo);

二、Mapper.xml实现

更改后:

  <insert id="insertUserByCondition">
      insert into user_info (username,password,age,
    <if test="gender!=null">
      gender,
    </if>
    phone) values (#{username},#{password},#{age},
    <if test="gender!=null">
      #{gender},
    </if>
    #{Phone});
  </insert>

测试代码,以及测试结果:

<1>gender为空

<2>gender不为空

在上面的,似乎只需要 if 标签就可以完成所有的动态查询操作,但是为什么后面还有 trim 等标签,这是因为只使用 if 标签是有可能出错的,如:

代码测试:

(1)插入phone字段:

执行成功

(2)不插入phone字段:

可以看到,程序报错,接下来查看MyBatis日志,

可以看到,由于没有填入最后一个字段,导致SQL语句多了一个逗号

为了避免 if 标签可能带来的SQL语法错误问题,可以使用 trim 标签解决


二、<trim> 标签

在前面的 if 标签报错的例子中,虽然通过将逗号放在 if 标签内来避免出错,但如果有多个可选字段甚至全部字段都可选,就无法避免了,因此,如果是有多个可选标签,一般使用标签结合标签的方式

<trim> 标签有4个属性,分别为:

• prefix:表示整个语句块,以prefix的值作为前缀

• suffix:表示整个语句块,以suffix的值作为后缀

• prefixOverrides:表示整个语句块要去除的前缀

• suffixOverrides:表示整个语句块要去除的后缀

接下来将上面出错的例子再加上一层 trim 标签:

    <insert id="insertUser3">
        insert into user_info
        <trim prefix="(" suffix=")" suffixOverrides=",">
            username,password,age,gender,
            <if test="phone!=null">
                phone
            </if>
        </trim>
            values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            #{username},#{password},#{age},#{gender},
            <if test="phone!=null">
                #{phone}
            </if>
        </trim>
    </insert>

再次测试代码:

可以看到经过修改,成功插入数据


 三、<where> 标签

前面我们使用的动态插入语句,主要是用在存储用户信息等方面的(如注册时可能要求填写个人爱好,性别的数据),而这里的动态查询语句,主要是对某方面的数据进行过滤筛查(如下图中当我们选择机身内存为1TB或其它时,就会触发动态查询,只显示内存为1TB的手机)

那么,如何使用 <where> 标签进行动态查询?

我们将下面的SQL改造为动态SQL:

SELECT
 * 
FROM
 userinfo 
WHERE
 age = 18 
 AND gender = 1 
 AND delete_flag =0

 改造后代码:

    <select id="queryByCondition" resultType="spring.mybatis.demo.model.UserInfo">
        select * from user_info
        <where>
            <if test="age!=null">
                age = #{age}
            </if>
            <if test="gender!=null">
                and gender = #{gender}
            </if>
            <if test="deleteFlag!=null">
                and delete_flag = #{deleteFlag}
            </if>
        </where>
    </select>

代码测试:

代码执行成功


四、<set> 标签

 同样,在更新数据时有选择性的更新(如在只将性别更改为男,而其它信息如兴趣爱好等不做改变),下面学习 <set> 标签的使用方法:
 

<update id="updateUserByCondition">
        update user_info
        <set>
            <if test="username!=null">
                username = #{username},
            </if>
            <if test="age!=null">
                age = #{age},
            </if>
            <if test="deleteFlag!=null">
                delete_flag = #{deleteFlag}
            </if>
        </set>
        where id = #{id}
 </update>
代码测试:代码执行成功

五、<foreach> 标签

当对一组数据进行批量操作时(如批量删除、批量更新),就可以使用 <foreach> 标签,它有几个核心属性:

• collection:绑定方法参数中的集合,如 List,Set,Map或数组对象

• item:遍历时的每⼀个对象

• open:语句块开头的字符串

• close:语句块结束的字符串

• separator:每次遍历之间间隔的字符串

如根据id批量删除:

    <delete id="deleteByIds">
        delete from user_info
        in
        <foreach collection="ids" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </delete>


六、<include> 标签

 在xml文件中的SQL语句中,可能存在很多有相同SQL语句片段,<include>标签可以将这项重复的片段提取出来,减少冗余

 接下来学习 <include> 标签的使用:

一、提取重复SQL片段放入 <sql> 标签中,并设置 id 属性(用于后面引用),如:

<sql id="allColumn">
 id, username, age, gender, phone, delete_flag, create_time, update_time
</sql>

二、被提取SQL片段的位置加入<include>标签,并用 refid 属性指定某个<sql>,引用其中的SQL片段,如

<select id="queryAllUser" resultMap="BaseMap">
 select

 <include refid="allColumn"></include>//将 <sql> 定义的片段插入到当前 SQL 语句中,实现逻辑复用‌

 from userinfo
</select>

<select id="queryById" resultType="com.example.demo.model.UserInfo">
 select

 <include refid="allColumn"></include>

 from userinfo where id= #{id}
</select>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值