昨天我们深入学习了Mybatis的核心对象SqlSessionFactoryBuilder,掌握MyBatis核心配置文件以及元素的使用,也掌握MyBatis映射文件及其元素的使用。那么今天我们需要掌握的是更加复杂的查询操作。
MyBatis 中的动态 SQL 是一种在 SQL 查询语句中根据不同的条件来动态生成不同的 SQL 片段的技术。它允许你根据不同的情况来构建查询条件,避免写大量重复的 SQL 语句。
元素 | 说明 |
---|---|
< if > | 判断语句,用于单条件判断 |
< choose >(< when >、< otherwise >) | 相当于Java中的switch…case…default语句,用于多条件判断 |
< where > | 简化SQL语句中where的条件判断 |
< trim > | 可以灵活地去除多余的关键字 |
< set > | 用于SQL语句的动态更新 |
< foreach > | 循环语句,常用于in语句等列举条件中 |
使用
元素: 可以根据条件来动态生成 SQL 片段。例如:
<select id="findByCondition" parameterType="map" resultType="User">
SELECT * FROM users
<where>
<if test="name != null">
AND name = #{name}
if>
<if test="age != null">
AND age = #{age}
if>
where>
select>
代码解释如下:
标签定义了一个查询语句,并指定了它的唯一标识符(id)、输入参数类型(parameterType)和结果类型(resultType)。
SELECT * FROM users
是实际的 SQL 查询语句,表示从名为 “users” 的表中选取所有列的数据。
标签是 MyBatis 提供的一个用于构建动态 SQL 的元素,它会在生成的 SQL 语句中添加 “WHERE” 关键字,并且只会在至少有一个条件满足时添加。
标签是
标签中的子元素,用于判断某个条件是否成立。它的 “test” 属性用于指定一个条件表达式。
如果 test="name != null"
成立,那么会在生成的 SQL 语句中添加一个 “AND name = #{name}” 的条件。
如果 test="age != null"
成立,那么会在生成的 SQL 语句中添加一个 “AND age = #{age}” 的条件。
这样,在实际执行查询时,如果传入的参数中有 “name”,那么会根据 “name” 的值添加相应的查询条件;同样地,如果传入的参数中有 “age”,那么会根据 “age” 的值添加相应的查询条件。
使用
元素: 类似于 switch 语句,根据条件选择一个分支进行处理。
<select id="findByCondition" parameterType="map" resultType="User">
SELECT * FROM users
<where>
<choose>
<when test="name != null">
AND name = #{name}
when>
<when test="age != null">
AND age = #{age}
when>
<otherwise>
AND 1=1
otherwise>
choose>
where>
select>
代码解释:
这段代码使用了 MyBatis 中的动态 SQL 元素
元素,也称为
构造。这样的构造允许你在 SQL 查询中根据条件动态地生成不同的部分。
包含了多个
元素,每个
元素对应一个条件判断,如果条件满足,就会生成相应的 SQL 查询条件。如果所有条件都不满足,就会执行
部分。
简单来说,这个查询语句的意思是:
name
不为 null
,则添加条件 AND name = #{name}
到查询语句中。age
不为 null
,则添加条件 AND age = #{age}
到查询语句中。null
),则添加条件 AND 1=1
到查询语句中。这个条件相当于一个恒为真的条件,因此不会影响查询结果。使用
元素: 可以根据条件来剪切 SQL 片段的开始或结尾,以防止出现多余的关键字。
<select id="findByCondition" parameterType="map" resultType="User">
SELECT * FROM users
<where>
<trim prefix="AND (" suffix=")" prefixOverrides="OR">
<if test="name != null">
OR name = #{name}
if>
<if test="age != null">
OR age = #{age}
if>
trim>
where>
select>
上述代码使用了 MyBatis 的动态 SQL 元素中的
元素,用于构建更复杂的条件语句。
元素用于构建一个以 AND
为前缀和 )
为后缀的条件片段,同时在生成条件语句时去除可能多余的 OR
。
简单来说,这个查询语句的意思是:
name
不为 null
,则将 OR name = #{name}
添加到条件片段中。age
不为 null
,则将 OR age = #{age}
添加到条件片段中。
元素的 prefix
属性指定前缀,suffix
属性指定后缀,prefixOverrides
属性指定需要去除的前缀。在这个例子中,prefix
是 AND (
,suffix
是 )
,prefixOverrides
是 OR
。这样,如果有至少一个条件满足,就会生成类似 AND ( condition1 OR condition2 )
的查询语句。如果没有条件满足,就会生成 AND ()
,这不会影响查询结果。
使用
元素: 可以用来遍历集合或数组参数,生成多个相同的 SQL 片段。
<select id="findByIds" parameterType="list" resultType="User">
SELECT * FROM users
WHERE id IN
<foreach item="id" collection="list" open="(" separator="," close=")">
#{id}
foreach>
select>
这段代码是一个 MyBatis 的动态 SQL 查询语句,用于根据传入的一组 id 值查询对应的用户信息。这个查询语句利用了
元素,允许在 SQL 查询中动态地生成 IN
子句。
具体来说,这个查询语句的意思是:
users
表中的所有列(SELECT *
)。WHERE
子句进行过滤,条件是 id
值在传入的 list
参数中。
元素用于循环遍历传入的 list
参数,将每个 id
值包装在 (
和 )
之间,并使用 ,
作为分隔符。在这个查询语句中,
元素的属性含义如下:
item
:指定在每次循环中使用的变量名,这里是 id
。collection
:指定要遍历的集合参数的名字,这里是 list
。open
:指定循环的开始字符,这里是 (
。separator
:指定循环每个元素之间的分隔符,这里是 ,
。close
:指定循环的结束字符,这里是 )
。这样,如果传入一个列表参数 list
,比如 [1, 2, 3]
,就会生成类似 SELECT * FROM users WHERE id IN (1, 2, 3)
的查询语句,从而查询对应的用户信息。
这些动态 SQL 的特性使得 MyBatis 在构建灵活和动态的查询条件时非常方便,避免了硬编码大量重复的 SQL 语句。
在学习了上面的几个动态SQL的常用元素,现在我们来尝试一下编写一下我们自己项目的动态SQL。
的动态SQl查询语句,若有账号名称Account则按账号名称Account查询,若有网站名WebsiteName则用WebsiteName查询,若俩个都有则俩个都匹配的才查询。 可以看到Mybatis是会根据我们输入的查询条件进行拼接生成动态的SQL。
的动态sql语句,情景时:若有账号名Account,则优先使用账号名进行查询。若无账户名,有网站名WebsiteName,那么就按网站名搜索。若账号名,网站名都无,那么就采用默认查询passwordms表中的所有信息。 在使用
元素时,只要test属性中的表达式为true,就会执行元素中的条件语句,但是在实际应用中,有时只需要从多个选项中选择一个去执行。这时候使用
就是非常合适的,如果使用
则是不合适的。
可以看到Mybatis是会根据我们输入的查询条件进行拼接生成动态的SQL。
、
的动态sql语句,情景时:在sql中where 后面直接跟and 或者 or之类的关键字都是错误的,会导致我们的SQL语句运行不成功在这个示例中我们写了个
,
在
条件中Account满足时,程序会自动在AND Account=#{Account}前面、后面,添加上前后缀生成新的语句:
AND (AND Account=#{Account}),
若是WebsiteName也满足的话,新的sql语句为:
AND (AND Account=#{Account} AND WebsiteName = #{WebsiteName} )
我们写的prefixOverrides=“AND”,会自动将()里面的多余的前缀AND去除,即生成:
AND ( Account=#{Account} AND WebsiteName = #{WebsiteName} )
看到这里是不是觉得那外面还有一个where呢?where AND (Account=#{Account} AND WebsiteName = #{WebsiteName})
也是错的对不?实际上
会自动帮我们去除()外多余的AND和OR防止SQL语句出错。
因此这个流程下来我们的语句就变成了:
where ( Account=#{Account} AND WebsiteName = #{WebsiteName} )
我们去输入测试类看看就知道是不是了
根据我们上面讲的流程:那么推测生成的动态sql语句应该是:
where ( WebsiteName=#{WebsiteName} )
根据我们上面讲的流程:那么推测生成的动态sql语句应该是:
Select * from passwordms,因为if里面的条件每一个成立,所以where也不会添加进去,但是会自动删除语句中多余的AND或OR
可以看到Mybatis是会根据我们输入的查询条件进行拼接生成动态的SQL,并且正确无误。
、
的动态sql语句,情景时:如果想要更新某一个对象,就需要发送所有的字段给持久化对象,然而在实际应用中,大多数情况下都是更新某一个或几个字段。如果更新的每一条数据都要将其所有的属性都更新一遍,那么执行效率是非常差的。为了解决更新数据的效率问题,MyBatis提供了
元素。 除了可以用
元素来进行更新操作外,也使用
元素来进行更新操作, 在映射文件中使用
元素和
元素组合进行update语句动态SQL组装时,如果
元素内包含的内容都为空,则会出现SQL语法错误。因此,在使用
元素进行字段信息更新时,要确保传入的更新字段不能都为空。
除此以外还可以跟前面的
元素联合起来一起使用。其中,
元素,suffixOverrides属性指定去除的
元素所包含内容的后缀为逗号 。
接下来进行测试类测试:
可以看到嗷,正常数据更新了,但是呢,其实是有问题的,不管数据是不是更原来的一样,都会对数据库进行一次更新的操作。
// 判断两个对象的数据是否相等
private boolean isDataEqual(PasswordMS oldData, PasswordMS newData) {
return Objects.equals(oldData.getAccount(), newData.getAccount())
&& Objects.equals(oldData.getWebsiteName(), newData.getWebsiteName());
}
可以看到测试成功,正确提示!
好的那么更新操作就学到这里了。
元素可以在 MyBatis 中对集合进行迭代操作,通常用于构建 IN 条件的查询语句。
元素的属性属性 | 说明 |
---|---|
item | 表示集合中每一个元素进行迭代时的别名。该属性为必选。 |
index | 在List和数组中,index是元素的序号,在Map中,index是元素的key。该属性可选。 |
open | 表示foreach语句代码的开始符号,一般和close=“)”合用。常用在in条件语句中。该属性可选。 |
separator | 表示元素之间的分隔符,例如,在条件语句中,separator=“,”会自动在元素中间用“,”隔开,避免手动输入逗号导致SQL错误,错误示例如in(1,2,)。该属性可选。 |
close | 表示foreach语句代码的关闭符号,一般和open="("合用。常用在in条件语句中。该属性可选。 |
collection | 用于指定遍历参数的类型。注意,该属性必须指定,不同情况下,该属性的值是不一样的。 |
属性的取值 在遍历参数时,
属性的值是必须指定的。不同情况下,该属性的取值也是不一样的,主要有以下三种情况:List类型、数值类型、Map类型。
的动态sql语句,情景时:要从数据表passwordms中查询出id为1、2、3的账号信息,就可以利用数组作为参数,存储id的属性值1、2、3,并通过
元素迭代数组完成账号信息的批量查询操作。好那么我们来编写我们的Mapper文件:
<select id="findByIds" parameterType="list" resultType="PasswordMS">
SELECT * FROM passwordms
WHERE id IN
<foreach item="id" collection="list" open="(" separator="," close=")">
#{id}
foreach>
select>
在我们的代码中,findByIds
是查询的 ID,parameterType
设置为 list
表示传入的参数是一个 List,resultType
设置为 PasswordMS
表示返回结果是 PasswordMS
类型的对象。
编写测试类:
@Test
void findByIds() {
SqlSession session = MyBatisUtil.createSqlSession();
List<Integer> idList = Arrays.asList(1, 2, 3); // 要查询的 id 列表
// 传入参数查询,返回结果
List<PasswordMS> passwordMSList = session.selectList("findByIds", idList);
for (PasswordMS s : passwordMSList) {
logger.info("id:" + s.getId() + ",账号:" + s.getAccount() + ",密码:" + s.getPassword() + ",网站名:" + s.getWebsiteName() + ",网站网址:" + s.getWebsiteURL() + ",网站缩略图:" + s.getWebsiteImage() + ",账号描述:" + s.getAccountDescription());
}
// 关闭 session
session.close();
}
可以看出,通过使用
元素就能够方便地在 MyBatis 中对集合进行迭代操作,构建需要的查询条件。
这是第三天对SSM框架的学习,深入学习了MyBatis的动态SQL,它允许我们根据不同的条件在 SQL 查询中动态地构建、拼接和执行 SQL 语句。动态 SQL 可以帮助你编写更加灵活、可复用和动态的数据库查询语句,适用于各种复杂的业务场景。
想要跟着学习的可以去我的资源里面找对应的文件下载,我的md文件也会发上去,项目文件会上传可以自己跟着学习一下。
PS:sql语句自己编写┗|`O′|┛ 嗷~~
作者:Stevedash
发表于:2023年8月23日 16点28分