动态SQL

本文详细介绍了如何使用MyBatis的动态SQL进行多条件查询和更新操作,包括if、where、set和trim元素的使用,以及foreach在处理复杂查询中的应用。还探讨了在不同场景下,如传入数组、List和Map类型的参数时,如何利用foreach进行迭代,并展示了如何使用choose元素实现类似Java switch的逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

3.1使用动态SQL完成完成多条件查询

➢if:利用if实现简单的条件选择
➢choose(when,otherwise):相当于Java中的switch语句,通常与when和otherwise搭配
➢where:简化SQL语句中where的条件判断
➢set:解决动态更新语句
➢trim:可以灵活地去除多余的关键字
➢foreach:迭代一个集合,通常用于in条件

3.1.1使用if+where实现条件查询

1.if回顾上章的演示示例–根据用户角色(角色id精确匹配)和用户名称(模糊匹配)完成对用户表的查询操作,在该示例中,采用的是封装对象入参,进行查询.通过之前的学习,我们了解到在查询条件不是很多并且较为固定分情况下,最好的解决方案是采用多参数直接入参的方式,这样的代码比较清晰,可读性强,那么现在就改造一下这示例.
在这里插入图片描述
在上述代码中,参数使用了@param注解,并将参数roleld重置名诶userRole,故UserMapper.xml的代码无须改造
通过该运行结果发现,查询出来的用户列表为空,这个查询结果是否正确?

在上述示例中,我们改造了SQL语句,利用if元素实现简单的条件判断,if元素的test属性表示进入if内部需要满足的条件.整个SQL语义非常简单,诺提供了userRole参数(即:满足条件userRole!=null),那么SQL的where条件就要满足:u.userRole=#{userRole}.同样,诺提供了userName参数(即:满足条件userName!=null且userName!=’’),那么SQL的where 条件就要满足u.userName like concaat(‘%’,#{userName},’%’),最终返回满足这些where条件的数据列表.这是一个非常有用的功能,相比于之前使用JDBC,诺达到同样的选择项,需要通过if.else语句进行SQL的拼接,而MyBatis的动态SQL就要简单许多
2.where
同样对于上述示例,诺不输入任何值,即测试方法中两个参数均传入空值,正常情况下控制台一个输出所有的用户列表信息

与之前的运行结果一样,后台SQL语句报错,不同的是SQL语句没有where子句,却多了一个where,造成SQL异常错误的原因也后之前分析的一样

综上分析诺要解决此类问题,就要智能地处理and和where,动态SQL中的where元素可以满足要求

Where元素主要用来简化SQL语句的where条件判断,并智能地处理and和or,部必担心多余关键字导致的语法错误

3.1.2技能训练

3.1.3使用if+trim实现多条件查询

在MyBatis中除了使用if+where实现多条件查询,还有一个更为灵活的元素trim可以替代之前的做法

trim元素也会自动别其标签内是否有返回值,诺有返回值,会在自己包含的内容前加上某些前缀,也可在其后面加上某些后缀,与之对应的属性是prefix和suffix;也可把包含内容的首部某些内容覆盖(即忽略),或者把尾部的某些内容覆盖,与之对应的属性是prefixOverrides和suffixOverrides;
正因为trim有这样强大的功能,我们可以利用trim来代替where元素,并实现与where元素相同的效果

trim的属性
➢prefix: 前缀,作用是通过自动识别是否有返回值后,在trim包含的内容上加上前缀,如此处的where,
➢suffix: 后缀,作用是在trim包含的内容上加上后缀。
➢prefixOverrides: 对于trim 包含内容的首部进行指定内容(如此处的"and|or) 的忽略。
➢suffixOverrides: 对于trim包含内容的首尾部进行指定内容的忽略。
最后运行测试方法根据传入的不同参数.分别进行智能的SQL语句拼接处理,效果等同于where元素,此处不再赘述。

3.2使用动态SQL实现更新操作

3.2.1使用if+set改造更新操作

通过日志中的SOL语句和参数,我们发现未被设值的参数也进行了set操作。那么如何解决?
就需要使用动态SQL中的set元素来处理。
set元素主要用于更新操作,它的主要功能和where元素差不多,主要是在包含的语句前输出一个set,若包含的语句是以逗号结束的,会自动把该逗号忽略掉,再配合if 元素就可以动态地更新需要修改的字段:而不需修改的字段,则可以不再被更新。下面改造UserMapper xml中的修改用户信息语句

3.2.2技能训练1

3.2.3使用if+trim改造修改操作

3.2.4技能训练2

3.3使用foreach完成复杂查询

3.3.1MyBatis入参为数组类型的foreach迭代

我们先了解一下foreach的基本用法和属性,foreach 主要用在构建in条件中,它可以在SQL语句中迭代一一个集合。它的属性主要有: item. index. collection. separator. close. open。下 面通过一个根据指定角色列表来获取用户信息列表的示例进行详细介绍。
首先修改UserMapper java,增加接口方法:根据传入的用户角色列表获取该角色列表下的用户信息,参数为角色列表(rolelds), 该参数类型为整型数组。

对于SQL条件循环(in 语句),需要使用foreach标签。通过上述代码,来介绍下french的基本
➢item: 表示集合中每一个元素进行迭代时的别名(如此处的 “rolelds“).
➢index: 指定一一个名称,用于表示在迭代过程中,每次选代到的位置。(此处省略,未指定)。
➢open: 表示该语句以什么开始(既然是in条件语句,所以必然是以"(”开始)。
➢separator: 表示在每次进行迭代之间以什么符号作为分隔符(既然是in条件语句,所以必然是以“,”作为分隔符)。
➢close: 表示该语句以什么结束(既然是in条件语句,所以必然是以”)” 结束)。
➢collection: 最关键并最容易出错的属性,需格外注意,该属性必须指定,不同情况下,该属性的值是不一样的。主要有三种情况:
若入参为单参数且参数类型是一个List的时候,clletion 属性值为ist,
◆若入参为单参数且参 数类型是一个数组的时候,cllction 属性值为aray (此处传入参数nteger] rolelds 为数组类型,故此处cletienn属性值设为aray ).
◆若传入参数为多参数, 就需要把它们封装为一个Map进行处理。
select中返回的是一个resultMap(id=”userMapByRole”).该resultMap也进行了相应的字段映射.最后修改测试类,增加测试方法

3.3.2MyBatis入参List类型的foreach迭代

注意 foreach元素非常强大,允许我们指定一个集合,并指定开始和结束的字符,也可以加入一个分隔符到迭代器中,并能够处理该分隔符,不会出现多余的分隔符.

3.3.3技能训练1

3.3.4MyBatis入参为Map类型的foreach迭代

通过对foreach标签的clletion属性的学习,我们发现不管传入的是单参数还是多参数,都可以得到有效解决。若单参数入参,是否可以封装成Map进行入参呢?答案是肯定的,单参数也可以封装Map进行入参。实际上,MyBatis 在进行参数入参的时候,都会把它封装成一一个Map,而Map的key就是参数名,对应的参数值就是Map的value。若参数为集合的时候,Map 的key会根据传入的是List还是数组对象相应地指定为"is" 或者array"。 现在就更改之前的演示示例:根据用户角色列表,获取该角色列表下用户列表的信息,此处参数不使用List或者数组,直接封装成Map来实现。口测试万法进门两w,_.
(1) MyBatis接收的参数类型:基本类型、对象、List、 数组、Map。
(2)无论MyBatis的入参是哪种参数类型,MyBatis都会将参数放在一个Map中,对于单参入参的情况:
➢若入参为基本类型: 变量名作为key,变量值为value,此时生成的Map只有一个元素。
➢若入参为对象:对象的属性名作为key,属性值为value。
➢若入参为List:默认“list” 作为key,该List即为value。
➢若入参为数组:默认“array” 作为key,该数组即为value。
➢若入参为Map:键值不变。

3.3.5技能训练2

3.3.6choose(when,otherwise)

对于某些查询需求,虽有多个查询条件,但是我们不想应用所有的条件,只想选择其中一种情况下的查询结果。其实和Java中switch语句相似,MyBatis 提供choose元素来满足这种需求choose元素的作用相当于Java中的switch语句,基本上跟JSTL中choose的作用和用法是一-样的,通常都是搭配when. otherwise 使用。下面就通过一个示例来演示说明其用法.

根据条件(用户名称.用户角色用户编码、创建时间)查询用户表,具体要求:查询条件提供前三个(用户名称,用户角色、用户编码)中的任意一一个即可,若前三个条件都不提供,那么 默认提供最后一个条件(创建时间: 在指定的年份内)来完成查询操作。

When元素:当其test属性综合条件满足的时候,就会输出when元素中的内容.跟Java中switch效果差不多的是同样按照条件的顺序来处理,并当when中一旦有条件满足的时候就会跳出choose,即所有的when和otherwise条件中,只有一个条件会输出

otherwise元素:当when中的条件都不满足的时候,就会自动输出otherwise的内容

3.3.7技能训练3

3.4MyBatis实现分页功能

3.4.1MyBatis分页

MvBatis实现分页查询,属于DAO层操作,由于DAO层是不牵涉任何业务实现的,所以实现分页的方法中第一个参数为limit的起始位置(下标从0开始),而不是用户输入的真正的页码(页码从1开始),之前我们已经学习过页码如何转换成limit的起始位置下标,即:起始位置下标= (页码-1)X页面容量,那么这个转换操作必然不能在DAO层实现,需要在业务层实现。故我们在测试类中传入的参数为下标,而不是页码。

3.4.2技能训练

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值