百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

MyBatis where、set、trim

wptr33 2025-01-10 17:38 31 浏览

1. 前言

在前面的小节中,我们一起学习了 if 标签,在通过 if 判断动态插入或查询的时候容易产生多余的前缀(如 WHERE)或后缀(如 , ),为了解决这类问题 MyBatis 提供了 where、set、trim 三个实用的标签。

其中 where 和 set 标签都是 trim 标签的一种特殊情况,不过使用频率非常高,因此被单独定义成了标签。本小节我们将一起来学习它们。

2. 定义

慕课解释:wheresettrim 三个标签都是为了解决 MyBatis 在动态生成 SQL 时,产生了多余的前缀和后缀的问题。

3. 实例

3.1 where 实例

<select id="selectUserByIdAndName" resultType="com.imooc.mybatis.model.User">
  SELECT * FROM imooc_user
  <where>
    <if test="id != null">
      id = #{id}
    </if>
    <if test="username != null">
      AND username = #{username}
    </if>
  </where>
</select>

在这个例子中,id 和 username 均非固定的过滤参数,只有当其不为 null 时才会加入到 SQL 语句中。此处 where 标签的作用大概有如下 3 个:

  1. 在 id 和 username 都为空的情况下,where 标签不会产生任何 SQL 代码段,最后的 SQL 语句为:SELECT * FROM imooc_user
  2. 在 id 不为空,username 为空的情况下,或者在 id 不为空,username 也不为空的情况下,where 标签会自动给 SQL 代码段添加上 WHERE 前缀;
  3. 在 id 为空,username 不为空的情况下,where 标签会自定去除 AND 前缀,此时生成的 SQL 语句为: SELECT * FROM imooc_user WHERE username = ?

3.2 set 实例

<update id="updateUsernameAndScoreById">
  UPDATE imooc_user
  <set>
    <if test="username != null">
      username = #{username},
    </if>
    id = #{id}
  </set>
  WHERE id = #{id}
</update>

set 标签会自动在 SQL 语句中添加上相应的 SET 前缀,并根据里面的条件动态地添加相应的字段。

由于 SQL update 的语法问题,如 set 标签里面条件均不满足,此时 set 标签也不会添加上 SET 前缀,但此时 SQL 会报语法错误,所以 set 标签中还是得有一个必然存在的赋值。

3.3 trim 实例

<update id="updateUsernameAndScoreById">
  UPDATE imooc_user
  <trim prefix="SET" suffixOverrides=",">
    <if test="username != null">
      username = #{username},
    </if>
    <if test="id != null">
      id = #{id}
    </if>
  </trim>
  WHERE id = #{id}
</update>

这里的 trim 实例实现了与 set 实例同样的功能,set 标签是 trim 标签的一种特殊情况。

trim 标签共有 4 个属性,它们的作用分别如下:

  • prefix: 前缀属性,若标签内不为空则在 SQL 中添加上前缀;
  • prefixOverrides: 前缀覆盖属性,若标签中有多余的前缀,将会被覆盖(其实就是丢弃该前缀);
  • suffix: 后缀属性,若标签内不为空则在 SQL 中添加上后缀;
  • suffixOverrides: 后缀覆盖属性,若标签中有多余的后缀,将会被覆盖(其实就是丢弃该后缀)。

这个例子中,trim 标签的前缀为SET,后缀覆盖属性为,,所以在标签内不为空的情况下给 SQL 语句添加了 SET 关键字,且标签内若有多余的,后缀也会被丢弃。

4. 实践

4.1 例1. 动态插入用户

请使用 MyBatis 完成对 imooc_user 表动态插入用户的功能,若用户属性值不为 null 则插入该字段,否则不插入字段。

分析:

按照 MyBatis 的开发模式,先在 UserMapper.xml 文件中添加动态插入用户的 insert 标签,然后在 UserMapper.java 中添加上对应的方法。

步骤:

首先,在 UserMapper.xml 中添加 insert 标签,并在标签中写入 SQL,使用 trim 标签来动态判断属性是否为空,若不为空则插入该字段。

<insert id="insertUserDynamic" parameterType="com.imooc.mybatis.model.User">
  INSERT INTO imooc_user
  <trim prefix="(" suffix=")" suffixOverrides=",">
    <if test="username != null">
      username,
    </if>
    <if test="age != null">
      age,
    </if>
    <if test="score != null">
      score,
    </if>
  </trim>
  VALUES
  <trim prefix="(" suffix=")" suffixOverrides=",">
    <if test="username != null">
      #{username},
    </if>
    <if test="age != null">
      #{age},
    </if>
    <if test="score != null">
      #{score},
    </if>
  </trim>
</insert>

这里,我们使用了两个 trim 标签,一个用来动态写入字段名,另一个用来动态写入字段值;trim 标签的前缀为(,后缀为),当出现多余的,时,会通过后缀覆盖属性来丢弃。

然后在 UserMapper.java 中添加上对应的接口方法:

package com.imooc.mybatis.mapper;

import org.apache.ibatis.annotations.Mapper;
import com.imooc.mybatis.model.User;

@Mapper
public interface UserMapper {
   int insertUserDynamic(User user);
}

结果:

通过如下代码,我们运行 insertUserDynamic 这个方法。

UserMapper userMapper = session.getMapper(UserMapper.class);
User user = new User();
user.setUsername("dynamic");
user.setScore(100);
int rows = userMapper.insertUserDynamic(user);
System.out.println(rows);

成功后,结果为:

1

TIPS: 注意,在 username、score 和 age 均为 null 时, insertUserDynamic 快报 SQL 语法错误,但理论上若是所有属性均为空,那么也不应该插入。

5. 小结

  • where、set 以及 trim 将 MyBatis 的动态 SQL 发挥到了极致,为开发者节省了大量的精力和时间。
  • trim 标签是 MyBatis 中最为强大的一个标签,使用它可以方便的完成 SQL 动态插入和动态更新。

相关推荐

oracle数据导入导出_oracle数据导入导出工具

关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...

继续学习Python中的while true/break语句

上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个else解...

python continue和break的区别_python中break语句和continue语句的区别

python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...

简单学Python——关键字6——break和continue

Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...

2-1,0基础学Python之 break退出循环、 continue继续循环 多重循

用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...

Python 中 break 和 continue 傻傻分不清

大家好啊,我是大田。今天分享一下break和continue在代码中的执行效果是什么,进一步区分出二者的区别。一、continue例1:当小明3岁时不打印年龄,其余年龄正常循环打印。可以看...

python中的流程控制语句:continue、break 和 return使用方法

Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...

L017:continue和break - 教程文案

continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...

作为前端开发者,你都经历过怎样的面试?

已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...

面试被问 const 是否不可变?这样回答才显功底

作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...

2023金九银十必看前端面试题!2w字精品!

导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。答案:CSS的盒模型是用于布局和定位元素的概念。它由内容区域...

前端面试总结_前端面试题整理

记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...

由浅入深,66条JavaScript面试知识点(七)

作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录由浅入深,66条JavaScript面试知识点(一)由浅入深,66...

2024前端面试真题之—VUE篇_前端面试题vue2020及答案

添加图片注释,不超过140字(可选)1.vue的生命周期有哪些及每个生命周期做了什么?beforeCreate是newVue()之后触发的第一个钩子,在当前阶段data、methods、com...

今年最常见的前端面试题,你会做几道?

在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...