mybatis实现动态sql

第一章、动态SQL

MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。

例如,下面需求就会使用到拼接sql语句:

【需求】:查询男性用户,如果输入了用户名,按用户名模糊查询,如果没有输入用户名,就查询所有男性用户

正常的sql语句:查询男性并且用户名中包含zhang

在这里插入图片描述

select * from tb_user where sex = "男" and user_name like '%zhang%'

在这里插入图片描述

select * from tb_user where  sex = "男"  

​ 实现需求时还要判断用户是否输入用户名来做不同的查询要求,而这里似乎没有办法判断是否输入了用户名,因此可以考虑使用动态sql来完成这个功能。

​ 动态 SQL 元素和后面学习的 JSTL 或基于之前学习的类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 开始精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的 OGNL 的表达式来淘汰其它大部分元素。

常见标签如下:

if:判断   if(1 gt 2){}
choose (when, otherwise):分支判断    switch:多选一
trim (where, set):去除
foreach:循环遍历标签

动态SQL中的业务逻辑判断需要使用到以下运算符: ognl表达式

1.   e1 or e2 满足一个即可
2.   e1 and e2 都得满足 
3.    e1 == e2,e1 eq e2 判断是否相等
4.    e1 != e2,e1 neq e2 不相等
5.    e1 lt e2:小于   lt表示less than 
6.    e1 lte e2:小于等于,其他gt(大于),gte(大于等于) gt 表示greater than
7.    e1 in e2 
8.    e1 not in e2
9.    e1 + e2,e1 * e2,e1/e2,e1 - e2,e1%e2
10.   !e,not e:非,求反
11.   e.method(args)调用对象方法
12.   e.property对象属性值
13.   e1[ e2 ]按索引取值,List,数组和Map
14.   @class@method(args)调用类的静态方法
15.   @class@field调用类的静态字段值

1、if标签

格式:

 <if test="判断条件">满足条件执行的代码</if>
说明:1)if标签:判断语句,用于进行逻辑判断的。如果判断条件为true,则执行if标签的文本内容2)test属性:用来编写表达式,支持ognl;

【需求】:查询男性用户,如果输入了用户名,按用户名模糊查询,如果没有输入用户名,就查询所有男性用户

正常的sql语句:查询男性并且用户名中包含zhang

在这里插入图片描述

select * from tb_user where sex = "男" and user_name like '%zhang%'

在这里插入图片描述

select * from tb_user where  sex = "男"  

​ 实现需求时还要判断用户是否输入用户名来做不同的查询要求,而这里似乎没有办法判断是否输入了用户名,因此可以考虑使用动态sql来完成这个功能。

​ 上述动态sql语句部分: and user_name like ‘%zhang%’

1.1、定义接口方法

​ 在UserMapper接口中,定义如下方法:

   /*** 根据用户名模糊查询* @param userName* @return*/List<User> queryLikeUserName(@Param("userName") String userName);
1.2、编写SQL

​ 在UserMapper.xml文件中编写与方法名同名的sql语句:

  <select id="queryLikeUserName" resultType="user">select * from user where sex='男'<if test="userName!=null and userName.trim()!=''">and username like '%${userName}%'</if></select>

【注】<if> 判断中:

1、if标签:用来判断;

2、test属性:使用OGNL表达式,完成具体的判断业务逻辑;

3、这里使用的字符串拼接,所以这里不能是#取值,只能使用$取值,否则会报错

1.3、测试

【userName有值】

在这里插入图片描述

对应的SQL语句是:select * from user where sex=“男” and username like ‘%孙%’

【userName没有值】

在这里插入图片描述

对应的SQL语句是:select * from user where sex=“男”

【小结】

1、if标签:用来在sql中处理判断是否成立的情况;
2、属性:test中书写OGNL表达式,如果结果为true,if标签的文本中的内容会被拼接到SQL中,反之不会被拼接到SQL中;
3、if标签的应用场景:适用于 二选一 

2、choose,when,otherwise

choose标签:分支选择(多选一,遇到成立的条件即停止)when子标签:编写条件,不管有多少个when条件,一旦其中一个条件成立,后面的when条件都不执行。test属性:编写ognl表达式otherwise子标签:当所有条件都不满足时,才会执行该条件。

需求:

编写一个查询方法,设置两个参数,一个是用户名,一个是住址。根据用户名或者住址查询所有男性用户:如果输入了用户名则按照用户名模糊查找,否则就按照住址查找,两个条件只能成立一个,如果都不输入就查找用户名为“孙悟空”的用户。

【需求分析】

1、查询所有男性用户,如果输入了用户名则按照用户名模糊查找;

SELECT * FROM  user WHERE  sex = "男" AND  username LIKE  '%孙%';

2、查询所有男性用户,如果输入了住址则按照住址查询;

SELECT * FROM  user WHERE  sex = "男" AND  address = "花果山水帘洞";

3、查询所有男性用户,如果都不输入就查找用户名为“孙悟空”的用户。

SELECT * FROM  user WHERE  sex = "男" AND username = '孙悟空';
2.1、定义接口方法

在UserMapper接口中,定义接口方法:

 /*查询用户名或者地址*/List<User> queryByUserNameOrAddress(@Param("userName") String userName, @Param("address") String address);
2.2、编写SQL

在UserMapper.xml中编写对应的SQL语句

<!--根据用户名或者住址查询所有男性用户:如果输入了用户名则按照用户名模糊查找,否则就按照住址查找,两个条件只能成立一个,如果都不输入就查找用户名为“孙悟空”的用户。--><select id="queryByUserNameOrAddress" resultType="user">select * from user where sex='男'<choose><when test="userName!=null and userName.trim()!=''">and username like '%${userName}%'</when><when test="address!=null and address.trim()!=''">and address = #{address}</when><otherwise>and username='孙悟空'</otherwise></choose></select>
2.3、测试

编写测试类,对这个方法进行测试:

@Test
public void queryByUserNameOrAddress(){List<User> userList = userMapper.queryByUserNameOrAddress("", null);System.out.println("userList = " + userList);
}

【小结】

1、choose,when,otherwise标签组合的作用类似于java中的switch语句,使用于多选一;

3、where

where标签:拼接多条件查询时 1、能够添加where关键字; 2、能够去除多余的and或者or关键字

案例:按照如下条件查询所有用户,

如果输入了用户名按照用户名进行查询,
如果输入住址,按住址进行查询,
如果两者都输入,两个条件都要成立。

【需求分析】

1、如果输入了用户名按照用户名进行查询,

SELECT * FROM  user WHERE user_name = '孙悟空';

2、如果输入住址,按住址进行查询,

SELECT * FROM  user WHERE address='花果山水帘洞';

3、如果两者都输入,两个条件都要成立。

SELECT * FROM  user WHERE user_name = '孙悟空' AND address='花果山水帘洞';
3.1、定义接口方法

在UserMapper接口中定义如下方法:

List<User> queryByUserNameAndAge(@Param("userName") String userName, @Param("address") String address);
3.2、编写SQL

在UserMapper.xml中编写SQL

 <!--如果输入了用户名按照用户名进行查询,如果输入住址,按住址进行查询,如果两者都输入,两个条件都要成立。说明:如果按照如下写sql语句会有问题,假设用户名username是空,那么用户名的sql语句不参与条件,此时sql语句就会变为:SELECT * FROM  user where AND address = #{address}where后面直接书写了and显然不满足sql语句语法,这里会报错我们可以使用where标签解决上述问题:where标签:拼接多条件查询时 1、能够添加where关键字; 2、能够去除多余的and或者or关键字--><!-- <select id="queryByUserNameAndAge" resultType="user">SELECT * FROM  user where<if test="userName != null and userName.trim()!=''">username = #{userName}</if><if test="address!=null and address.trim()!=''">AND address = #{address}</if></select>--><!-- SELECT * FROM user WHERE address = ?where子标签将and去掉了--><select id="queryByUserNameAndAge" resultType="user">SELECT * FROM  user<where><if test="userName != null and userName.trim()!=''">username = #{userName}</if><if test="address!=null and address.trim()!=''">AND address = #{address}</if></where></select>

说明:

1.说明:如果按照如下写sql语句会有问题,假设用户名username是空,那么用户名的sql语句不参与条件,此时
sql语句就会变为:SELECT * FROM user where AND address = #{address}
where后面直接书写了and显然不满足sql语句语法,这里会报错
我们可以使用where标签解决上述问题:
where标签:拼接多条件查询时 1、能够添加where关键字; 2、能够去除多余的and或者or关键字

2.SELECT * FROM user WHERE address = ?
where子标签将and去掉了

3.3、测试
@Testpublic void queryByUserNameAndAge() {List<User> userList = userMapper.queryByUserNameAndAge("", "花果山水帘洞");System.out.println("userList = " + userList);}

在这里插入图片描述

只传入住址,此时where子标签去掉了and.

【小结】

1、<where>标签作用:用于拼接多选一或者同时成立的SQL情况;
2、<where>还会根据情况,动态的去掉SQL语句中的AND或者or;

4、set

set标签:在update语句中,可以自动添加一个set关键字,并且会将动态sql最后多余的逗号去除。

案例:修改用户信息,如果参数user中的某个属性为null,则不修改。

如果在正常编写更新语句时,如下:

在这里插入图片描述

update user SET username = ?, birthday=?, sex=?, where id = ? 

那么一旦在传递的参数中没有address,此时生成的sql语句就会因为多了一个逗号而报错。

4.1、定义接口方法

在UserMapper接口中定义如下方法:

void updateSelectiveUser(User user);
4.2、编写SQL

在UserMapper.xml文件中编写如下SQL:

    <!--选择性地对user数据进行修改--><update id="updateSelectiveUser">update user<set><if test="username != null and username.trim()!=''">username = #{username},</if><if test="birthday != null">birthday=#{birthday},</if><if test="sex != null and sex.trim()!=''">sex=#{sex},</if><if test="address != null and address.trim()!=''">address=#{address}</if></set>where id = #{id}</update>
4.3、测试
 @Testpublic void updateSelectiveUser() {User user = new User();user.setUsername("锁哥1");user.setBirthday(new Date());user.setSex("男");user.setAddress("");user.setId(7);userMapper.updateSelectiveUser(user);}

【结果】

 update user SET username = ?, birthday=?, sex=? where id = ? 

【小结】

1、<set>标签替代了sql语句中的set关键字;
2、<set>标签还能把sql中多余的,去掉;

5、foreach

foreach标签:遍历集合或者数组
<foreach collection="集合名或者数组名" item="元素" separator="标签分隔符" open="以什么开始" close="以什么结束">#{元素}
</foreach>collection属性:接收的集合或者数组,集合名或者数组名item属性:集合或者数组参数中的每一个元素 separator属性:标签分隔符 open属性:以什么开始 close属性:以什么结束

需求:按照id值是1,2,3来查询用户数据;

5.1、定义接口方法

在UserMapper接口中定义如下方法:

List<User> queryByIds(@Param("arrIds") Integer[] arrIds);

这里一定加@Param(“arrIds”),否则报错

5.2、编写SQL
	<!--根据多个id值查询--><select id="queryByIds" resultType="user">SELECT * FROM  user WHERE id IN<foreach collection="arrIds" item="ID" separator="," open="(" close=")">#{ID}</foreach></select>
5.3、测试
    @Testpublic void queryByIds() {Integer[] arrIds = {1,2,3};List<User> userList = userMapper.queryByIds(arrIds);System.out.println("userList = " + userList);}

在这里插入图片描述

【小结】

<foreach>标签的作用:用于对查询参数进行遍历取值;

6、小结

If标签:条件判断test属性:编写ognl表达式where标签:用于sql动态条件拼接,添加where关键字,可以将动态sql多余的第一个and或者or去除。set标签: 用于更新语句的拼接,添加set关键字,并可以将动态sql中多余的逗号去除foreach标签:用于遍历参数中的数组或者集合collection属性:参数中的数组或者集合item属性:表示数组或者集合中的某个元素,取出数据使用#{item的属性值}separator属性:分隔符open:以什么开始close:以什么结束

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/40920.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[ C++ ] 深入理解模板( 进 阶 )

目录 非类型模板参数 类模板没有实例化的情况 模板的特化 注意函数特化中遇到的问题 建议&#xff1a;&#xff08;直接使用函数重载&#xff09; 类模板特化 全特化 偏特化 偏特化有以下两种表现方式&#xff1a; 部分特化&#xff08;将模板参数类表中的一部分参数特化…

旅游系统(附管理端+前台)PHP源码

一. 前言 今天小编给大家带来了一款可学习&#xff0c;可商用的&#xff0c;旅游系统 源码&#xff0c;支持二开&#xff0c;无加密。支持景点管理&#xff0c;登录&#xff0c;景点预定&#xff0c;意见反馈&#xff0c;统计等功能。详细界面和功能见下面视频演示。 二. 视频…

【flutter问题记录】 无效的源发行版:17

问题描述 在看开源项目的时候&#xff0c;clone下来后一直编译失败&#xff0c;提示&#xff1a;无效的源发行版:17&#xff0c;看描述大概是jdk的版本问题&#xff0c;但是在Android studio各种指定都无用&#xff0c;网上资料也没有flutter项目的解决方案&#xff0c;最后在…

广州自闭症机构哪家好?

在广州&#xff0c;众多的自闭症康复机构中&#xff0c;星贝育园自闭症儿童康复学校以其独特的优势脱颖而出。 一、专业的师资团队 我们拥有一支经验丰富、专业素养极高的师资队伍。每位老师都经过严格的专业培训&#xff0c;深入了解自闭症儿童的特点和需求。他们不仅具…

深入挖掘海外快手kwai ads推广巴西slots手游广告独家优势

深入挖掘海外快手kwai ads推广巴西slots手游广告独家优势 在数字化时代&#xff0c;广告投放已成为各行各业不可或缺的一部分&#xff0c;特别是在游戏行业&#xff0c;如何有效地推广游戏产品&#xff0c;吸引玩家的眼球&#xff0c;成为了每一个游戏开发商和广告主所关注的焦…

假设性文档嵌入 HyDE:大模型 + 对比学习,从关键词相似度搜索到语义搜索

假设性文档嵌入 HyDE&#xff1a;大模型 对比学习&#xff0c;从关键词相似度搜索到语义搜索 提出背景流程图解法拆解类比1. 单一文档嵌入空间的搜索2. 指令跟随型语言模型&#xff08;InstructLM&#xff09;的引入3. 生成文档的嵌入编码 提出背景 论文&#xff1a;https://…

python怎么样将一段程序无效掉

1、python中可以用注释屏蔽一段语句&#xff0c;具体方法如下&#xff0c;首先打开一段python的示例程序&#xff1a; 2、然后单行注释的方法是在语句前面加上#&#xff0c;程序运行后添加注释的地方的语句会被自动跳过&#xff0c;这里可以看到将打印变量a的语句添加注释就没有…

【实验室精选】PFA反应瓶带鼓泡球 高效气体鼓泡 化学分析优选

PFA反应瓶带鼓泡球是一种特殊设计的实验室容器&#xff0c;它集成了鼓泡球和PFA&#xff08;全氟烷氧基&#xff09;材料的反应瓶&#xff0c;用于气体的鼓泡和液体的混合。以下是它的一些特点和用途&#xff1a; 特点&#xff1a; 鼓泡球设计&#xff1a;鼓泡球周围布满小孔&…

界面材料知识

界面材料是用于填充芯片和散热器之间的空隙&#xff0c;将低导热系数的空气挤出&#xff0c;换成较高导热系数的材料&#xff0c;以提高芯片散热能力。参考下图 图片来源网上 热阻是衡量界面材料性能最终的参数&#xff0c;其中与热阻有关的有&#xff1a; 1、导热系数&#x…

从零开始学习SLAM(三)

旋转向量 #include <Eigen/Geometry> #include <Eigen/Core>AngleAxisd 类有几种构造函数&#xff0c;其中最常用的是&#xff1a; Eigen::AngleAxisd(const Scalar& angle, const Axis& axis);angle 是旋转的角度&#xff0c;通常以弧度表示。axis 是旋…

element-ui el-select选择器组件下拉框增加自定义按钮

element-ui el-select选择器组件下拉框增加自定义按钮 先看效果 原理&#xff1a;在el-select下添加禁用的el-option&#xff0c;将其value绑定为undefined&#xff0c;然后覆盖el-option禁用状态下的默认样式即可 示例代码如下&#xff1a; <template><div class…

【 VIPKID-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …

基于Istio的多网关运行时:配置、部署和应用

1. 引言 Istio是一个开源的服务网格&#xff0c;主要应用于简化微服务架构中的服务间通信、提供强大的监控能力以及加强服务的安全管理。通过利用Sidecar模式部署的Envoy代理&#xff0c;Istio能够在几乎无需修改服务代码的情况下&#xff0c;实现服务发现、负载均衡、加密通信…

WRF学习——使用CMIP6数据驱动WRF/基于ncl与vdo的CMIP6数据处理

动力降尺度 国际耦合模式比较计划&#xff08;CMIP&#xff09;为研究不同情景下的气候变化提供了大量的模拟数据&#xff0c;而在实际研究中&#xff0c;全球气候模式输出的数据空间分辨率往往较低&#xff08;>100Km&#xff0c;缺乏区域气候特征&#xff0c;为了更好地研…

【pytorch14】感知机

单层感知机模型 对于单层的感知机&#xff0c;它的激活函数是一个sigmoid 对于符号的定义做一个规范化&#xff0c;输入层每一层进行一个编号 输入是第0层&#xff0c;上标0表示属于输入层&#xff0c;下标0到n表示一共有n个节点(这里严格来说应该是0~n-1&#xff0c;为了书写…

一站式广告监测新体验,Xinstall助你广告投放更精准

在这个移动互联网飞速发展的时代&#xff0c;App推广与运营成为了每个开发者与广告主关注的焦点。然而&#xff0c;面对琳琅满目的广告平台和复杂的投放环境&#xff0c;如何精准评估广告效果、优化投放策略&#xff0c;成为了摆在面前的一道难题。今天&#xff0c;我们就来聊聊…

Jemeter--关联接口压测

Jemeter–独立不变参接口压测 Jemeter–独立变参接口压测 Jemeter–关联接口压测 案例分析 比如&#xff1a;有个波次复核接口很慢&#xff0c;优化后需要压测。但是波次复核接口数据是由另外两个接口&#xff08;配单详情、内盒信息&#xff09;的数据组合而来&#xff0c;而…

fastadmin最新版导出数据时 表格中会有 html标签的解决办法

fastadmin 自带的导出方法&#xff0c; 是一个纯前端的导出&#xff0c; 没有请求后台的接口 当我们使用导出功能时&#xff0c; 有些数据&#xff0c; 我们在设计的时候&#xff0c;配置的是 枚举类型的 但是当我们导出数据的时候&#xff0c; 居然导出的数据中带有 html 的…

k8s-第十节-Ingress

Ingress 介绍 Ingress 为外部访问集群提供了一个 统一 入口&#xff0c;避免了对外暴露集群端口&#xff1b;功能类似 Nginx&#xff0c;可以根据域名、路径把请求转发到不同的 Service。可以配置 https 跟 LoadBalancer 有什么区别&#xff1f; LoadBalancer 需要对外暴露…

【12321骚扰电话举报受理中心-短信验证安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…