「Java知识」Mybatis的特性详解——动态SQL,拿走不谢
wptr33 2025-01-10 17:38 30 浏览
Mybatis的特性详解——动态SQL
- 1.MyBatis if标签:条件判断
- 2.MyBatis choose、when和otherwise标签
- 5.MyBatis foreach标签
- 仰天大笑出门去,我辈岂是蓬蒿人
动态 SQL 是 MyBatis 的强大特性之一。在 JDBC 或其它类似的框架中,开发人员通常需要手动拼接 SQL 语句。根据不同的条件拼接 SQL 语句是一件极其痛苦的工作。例如,拼接时要确保添加了必要的空格,还要注意去掉列表最后一个列名的逗号。而动态 SQL 恰好解决了这一问题,可以根据场景动态的构建查询。
动态 SQL 只有几个基本元素,与 JSTL 或 XML 文本处理器相似,十分简单明了,大量的判断都可以在 MyBatis 的映射 XML 文件里配置,以达到许多需要大量代码才能实现的功能。
好处: :动态 SQL 大大减少了编写代码的工作量,更体现了 MyBatis 的灵活性、高度可配置性和可维护性。
一、动态sql的元素
MyBatis 的动态 SQL 包括以下几种元素,如下表所示
1.MyBatis if标签:条件判断
MyBatis if 类似于 Java 中的 if 语句,是 MyBatis 中最常用的判断语句。使用 if 标签可以节省许多拼接 SQL 的工作,把精力集中在 XML 的维护上。 if 语句使用方法简单,常常与 test 属性联合使用。
语法如下:
<if test="判断条件">
SQL语句
</if>
当判断条件为 true 时,才会执行所包含的 SQL 语句。
最常见的场景是在 if 语句中包含 where 子句,例如。
<select id="selectAllBaseData" resultMap="myResult">
select id,name from baseData
<if test="name != null">
where name like #{name}
</if>
</select>
以上代表表示根据name去查找相应的信息,但是name是一个可填可不填的条件,不填写的时候不作为查询条件。
可多个 if 语句同时使用。以下语句表示为可以按照 name 或者 id 进行模糊查询。如果您不输入,则返回所有的记录。但是,如果你传递了任意一个参数,它就会返回与给定参数相匹配的记录:
<select id="selectAllBaseData" resultMap="myResult">
select id,name from baseData
<if test="name != null">
where name like #{name}
</if>
<if test="id != id">
AND id like #{id}
</if>
</select>
2.MyBatis choose、when和otherwise标签
MyBatis 中动态语句 choose-when-otherwise 类似于 Java 中的 switch-case-default 语句。由于 MyBatis 并没有为 if 提供对应的 else 标签,如果想要达到 <if>...<else>...</else> </if> 的效果,可以借助 <choose>、<when>、<otherwise> 来实现。
动态语句 choose-when-otherwise 语法如下。
<choose>
<when test="判断条件1">
SQL语句1
</when >
<when test="判断条件2">
SQL语句2
</when >
<when test="判断条件3">
SQL语句3
</when >
<otherwise>
SQL语句4
</otherwise>
</choose>
choose 标签按顺序判断其内部 when 标签中的判断条件是否成立,如果有一个成立,则执行相应的SQL 语句,choose 执行结束;
如果都不成立,则执行 otherwise 中的 SQL 语句。
这类似于 Java 的 switch 语句;
- choose 为 switch,
- when 为 case,
- otherwise 则为 default。
示例
以下示例要求:
当网站名称不为空时,只用网站名称作为条件进行模糊查询;
当网站名称为空,而网址不为空时,则用网址作为条件进行模糊查询;
当网站名称和网址都为空时,则要求网站年龄不为空.
<mapper namespace="net.biancheng.mapper.WebsiteMapper">
<select id="selectWebsite">
SELECT id,name,url,age,country
FROM website WHERE 1=1
<choose>
<when test="name != null and name !=''">
AND name LIKE CONCAT('%',#{name},'%')
</when>
<when test="url != null and url !=''">
AND url LIKE CONCAT('%',#{url},'%')
</when>
<otherwise>
AND age is not null
</otherwise>
</choose>
</select>
</mapper>
这样 MyBatis 就会根据参数的设置进行判断来动态组装 SQL,以满足不同业务的要求。远比 Hibernate 和 JDBC 中大量判断 Java 代码要清晰和明确。
3.MyBatis where标签
where 标签
where 标签主要用来简化 SQL 语句中的条件判断,可以自动处理 AND/OR 条件,语法如下
<where>
<if test="判断条件">
AND/OR ...
</if>
</where>
if 语句中判断条件为 true 时,where 关键字才会加入到组装的 SQL 里面,否则就不加入。where 会检索语句,它会将 where 后的第一个 SQL 条件语句的 AND 或者 OR 关键词去掉。
示例
<select id="selectWebsite" resultType="net.biancheng.po.Website">
select id,name,url from website
<where>
<if test="name != null">
AND name like #{name}
</if>
<if test="url!= null">
AND url like #{url}
</if>
</where>
</select
4.MyBatis set标签
在 Mybatis 中,update 语句可以使用 set 标签动态更新列。set 标签可以为 SQL 语句动态的添加 set 关键字,剔除追加到条件末尾多余的逗号。 代码如下。
<!--使用set元素动态修改一个网站记录 -->
<update id="updateWebsite">
UPDATE website
<set>
<if test="name!=null">name=#{name},</if>
<if test="url!=null">url=#{url},</if>
</set>
WHERE id=#{id}
</update>
5.MyBatis foreach标签
对于一些 SQL 语句中含有 in 条件,需要迭代条件集合来生成的情况,可以使用 foreach 来实现 SQL 条件的迭代。
Mybatis foreach 标签用于循环语句,它很好的支持了数据和 List、set 接口的集合,并对此提供遍历的功能。语法格式如下。
<foreach item="item" index="index" collection="list|array|map key" open="(" separator="," close=")">
#{item}
</foreach>
foreach 标签主要有以下属性,说明如下:
- item:表示集合中每一个元素进行迭代时的别名。
- index:指定一个名字,表示在迭代过程中每次迭代到的位置。
- open:表示该语句以什么开始(既然是 in 条件语句,所以必然以(开始)。
- separator:表示在每次进行迭代之间以什么符号作为分隔符(既然是 in 条件语句,所以必然以,作为分隔符)。
- close:表示该语句以什么结束(既然是 in 条件语句,所以必然以)开始)。
使用 foreach 标签时,最关键、最容易出错的是 collection 属性,该属性是必选的,但在不同情况下该属性的值是不一样的,主要有以下 3 种情况:
- 如果传入的是单参数且参数类型是一个 List,collection 属性值为 list。
- 如果传入的是单参数且参数类型是一个 array 数组,collection 的属性值为 array。
- 如果传入的参数是多个,需要把它们封装成一个 Map,当然单参数也可以封装成 Map。Map 的 key 是参数名,collection 属性值是传入的 List 或 array 对象在自己封装的 Map 中的 key。
示例
修改array里面id为这些的数据status改为0
update project set status = 0 where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
注意事项:在使用 foreach 标签时,应提前预估一下 collection 对象的长度。因为大量数据的 in 语句会影响性能,且还有一些数据库会限制执行的 SQL 语句长度。
6.MyBatis bind标签
每个数据库的拼接函数或连接符号都不同,例如 MySQL 的 concat 函数、Oracle 的连接符号“||”等。这样 SQL 映射文件就需要根据不同的数据库提供不同的实现,显然比较麻烦,且不利于代码的移植。MyBatis 提供了 bind 标签来解决这一问题。
bind 标签可以通过 OGNL 表达式自定义一个上下文变量。
比如,按照网站名称进行模糊查询,SQL 映射文件如下。
<select id="selectWebsite" >
<bind name="pattern" value="'%'+_parameter+'%'" />
SELECT id,name,url,age,country
FROM website
WHERE name like #{pattern}
</select>
bind 元素属性如下:
- value:对应传入实体类的某个字段,可以进行字符串拼接等特殊处理。
- name:给对应参数取的别名。
以上代码中的“_parameter”代表传递进来的参数,它和通配符连接后,赋给了 pattern,然后就可以在 select 语句中使用这个变量进行模糊查询,不管是 MySQL 数据库还是 Oracle 数据库都可以使用这样的语句,提高了可移植性。
大部分情况下需要传递多个参数,下面为传递多个参数时 bind 的用法示例。
示例
//mapper文件中入参
public List<User> selectUser(User user);
-- xml中
<select id="selectUser" resultType="User">
<bind name="pattern_name" value="'%'+name+'%'" />
<bind name="pattern_url" value="'%'+url+'%'" />
SELECT id,name,url,age,country
FROM User
WHERE name like #{pattern_name}
AND url like #{pattern_url}
</select>
7.MyBatis trim标签
在 MyBatis 中除了使用 if+where 实现多条件查询,还有一个更为灵活的元素 trim 能够替代之前的做法。
trim 一般用于去除 SQL 语句中多余的 AND 关键字、逗号,或者给 SQL 语句前拼接 where、set 等后缀,可用于选择性插入、更新、删除或者条件查询等操作。trim 语法格式如下。
<trim prefix="前缀" suffix="后缀" prefixOverrides="忽略前缀字符" suffixOverrides="忽略后缀字符">
SQL语句
</trim>
trim 中属性说明如下
示例
<select id="selectUser" resultType="User">
SELECT id,name,url,age,country
FROM User
<trim prefix="where" prefixOverrides="and">
<if test="name != null and name !=''">
AND name LIKE CONCAT ('%',#{name},'%')
</if>
<if test="url!= null">
AND url like concat ('%',#{url},'%')
</if>
</trim>
</select>
需要Java资料和面试题:转发+关注之后,私信【Java】即可!!!
相关推荐
- MySQL进阶五之自动读写分离mysql-proxy
-
自动读写分离目前,大量现网用户的业务场景中存在读多写少、业务负载无法预测等情况,在有大量读请求的应用场景下,单个实例可能无法承受读取压力,甚至会对业务产生影响。为了实现读取能力的弹性扩展,分担数据库压...
- 3分钟短文 | Laravel SQL筛选两个日期之间的记录,怎么写?
-
引言今天说一个细分的需求,在模型中,或者使用laravel提供的EloquentORM功能,构造查询语句时,返回位于两个指定的日期之间的条目。应该怎么写?本文通过几个例子,为大家梳理一下。学习时...
- 一文由浅入深带你完全掌握MySQL的锁机制原理与应用
-
本文将跟大家聊聊InnoDB的锁。本文比较长,包括一条SQL是如何加锁的,一些加锁规则、如何分析和解决死锁问题等内容,建议耐心读完,肯定对大家有帮助的。为什么需要加锁呢?...
- 验证Mysql中联合索引的最左匹配原则
-
后端面试中一定是必问mysql的,在以往的面试中好几个面试官都反馈我Mysql基础不行,今天来着重复习一下自己的弱点知识。在Mysql调优中索引优化又是非常重要的方法,不管公司的大小只要后端项目中用到...
- MySQL索引解析(联合索引/最左前缀/覆盖索引/索引下推)
-
目录1.索引基础...
- 你会看 MySQL 的执行计划(EXPLAIN)吗?
-
SQL执行太慢怎么办?我们通常会使用EXPLAIN命令来查看SQL的执行计划,然后根据执行计划找出问题所在并进行优化。用法简介...
- MySQL 从入门到精通(四)之索引结构
-
索引概述索引(index),是帮助MySQL高效获取数据的数据结构(有序),在数据之外,数据库系统还维护者满足特定查询算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构...
- mysql总结——面试中最常问到的知识点
-
mysql作为开源数据库中的榜一大哥,一直是面试官们考察的重中之重。今天,我们来总结一下mysql的知识点,供大家复习参照,看完这些知识点,再加上一些边角细节,基本上能够应付大多mysql相关面试了(...
- mysql总结——面试中最常问到的知识点(2)
-
首先我们回顾一下上篇内容,主要复习了索引,事务,锁,以及SQL优化的工具。本篇文章接着写后面的内容。性能优化索引优化,SQL中索引的相关优化主要有以下几个方面:最好是全匹配。如果是联合索引的话,遵循最...
- MySQL基础全知全解!超详细无废话!轻松上手~
-
本期内容提醒:全篇2300+字,篇幅较长,可搭配饭菜一同“食”用,全篇无废话(除了这句),干货满满,可收藏供后期反复观看。注:MySQL中语法不区分大小写,本篇中...
- 深入剖析 MySQL 中的锁机制原理_mysql 锁详解
-
在互联网软件开发领域,MySQL作为一款广泛应用的关系型数据库管理系统,其锁机制在保障数据一致性和实现并发控制方面扮演着举足轻重的角色。对于互联网软件开发人员而言,深入理解MySQL的锁机制原理...
- Java 与 MySQL 性能优化:MySQL分区表设计与性能优化全解析
-
引言在数据库管理领域,随着数据量的不断增长,如何高效地管理和操作数据成为了一个关键问题。MySQL分区表作为一种有效的数据管理技术,能够将大型表划分为多个更小、更易管理的分区,从而提升数据库的性能和可...
- MySQL基础篇:DQL数据查询操作_mysql 查
-
一、基础查询DQL基础查询语法SELECT字段列表FROM表名列表WHERE条件列表GROUPBY分组字段列表HAVING分组后条件列表ORDERBY排序字段列表LIMIT...
- MySql:索引的基本使用_mysql索引的使用和原理
-
一、索引基础概念1.什么是索引?索引是数据库表的特殊数据结构(通常是B+树),用于...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
程序员的开源月刊《HelloGitHub》第 71 期
-
详细介绍一下Redis的Watch机制,可以利用Watch机制来做什么?
-
假如有100W个用户抢一张票,除了负载均衡办法,怎么支持高并发?
-
Java面试必考问题:什么是乐观锁与悲观锁
-
如何将AI助手接入微信(打开ai手机助手)
-
redission YYDS spring boot redission 使用
-
SparkSQL——DataFrame的创建与使用
-
一文带你了解Redis与Memcached? redis与memcached的区别
-
如何利用Redis进行事务处理呢? 如何利用redis进行事务处理呢英文
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)