Javaweb之Mybatis的动态SQL的详细解析

3. Mybatis动态SQL

3.1 什么是动态SQL

在页面原型中,列表上方的条件是动态的,是可以不传递的,也可以只传递其中的1个或者2个或者全部。

而在我们刚才编写的SQL语句中,我们会看到,我们将三个条件直接写死了。 如果页面只传递了参数姓名name 字段,其他两个字段 性别 和 入职时间没有传递,那么这两个参数的值就是null。

此时,执行的SQL语句为:

这个查询结果是不正确的。正确的做法应该是:传递了参数,再组装这个查询条件;如果没有传递参数,就不应该组装这个查询条件。

比如:如果姓名输入了"张", 对应的SQL为:

select *  from emp where name like '%张%' order by update_time desc;

如果姓名输入了"张",,性别选择了"男",则对应的SQL为:

select *  from emp where name like '%张%' and gender = 1 order by update_time desc;

SQL语句会随着用户的输入或外部条件的变化而变化,我们称为:动态SQL

在Mybatis中提供了很多实现动态SQL的标签,我们学习Mybatis中的动态SQL就是掌握这些动态SQL标签。

3.2 动态SQL-if

<if>:用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SQL。

<if test="条件表达式">要拼接的sql语句
</if>

接下来,我们就通过<if>标签来改造之前条件查询的案例。

3.2.1 条件查询

示例:把SQL语句改造为动态SQL方式

  • 原有的SQL语句

<select id="list" resultType="com.itheima.pojo.Emp">select * from empwhere name like concat('%',#{name},'%')and gender = #{gender}and entrydate between #{begin} and #{end}order by update_time desc
</select>
  • 动态SQL语句

<select id="list" resultType="com.itheima.pojo.Emp">select * from empwhere<if test="name != null">name like concat('%',#{name},'%')</if><if test="gender != null">and gender = #{gender}</if><if test="begin != null and end != null">and entrydate between #{begin} and #{end}</if>order by update_time desc
</select>

测试方法:

@Test
public void testList(){//性别数据为null、开始时间和结束时间也为nullList<Emp> list = empMapper.list("张", null, null, null);for(Emp emp : list){System.out.println(emp);}
}

执行的SQL语句:

下面呢,我们修改测试方法中的代码,再次进行测试,观察执行情况:

@Test
public void testList(){//姓名为nullList<Emp> list = empMapper.list(null, (short)1, null, null);for(Emp emp : list){System.out.println(emp);}
}

执行结果:

再次修改测试方法中的代码,再次进行测试:

@Test
public void testList(){//传递的数据全部为nullList<Emp> list = empMapper.list(null, null, null, null);for(Emp emp : list){System.out.println(emp);}
}

执行的SQL语句:

以上问题的解决方案:使用<where>标签代替SQL语句中的where关键字

  • <where>只会在子元素有内容的情况下才插入where子句,而且会自动去除子句的开头的AND或OR

<select id="list" resultType="com.itheima.pojo.Emp">select * from emp<where><!-- if做为where标签的子元素 --><if test="name != null">and name like concat('%',#{name},'%')</if><if test="gender != null">and gender = #{gender}</if><if test="begin != null and end != null">and entrydate between #{begin} and #{end}</if></where>order by update_time desc
</select>

测试方法:

@Test
public void testList(){//只有性别List<Emp> list = empMapper.list(null, (short)1, null, null);for(Emp emp : list){System.out.println(emp);}
}

执行的SQL语句:

3.2.2 更新员工

案例:完善更新员工功能,修改为动态更新员工数据信息

  • 动态更新员工信息,如果更新时传递有值,则更新;如果更新时没有传递值,则不更新

  • 解决方案:动态SQL

修改Mapper接口:

@Mapper
public interface EmpMapper {//删除@Update注解编写的SQL语句//update操作的SQL语句编写在Mapper映射文件中public void update(Emp emp);
}

修改Mapper映射文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
​<!--更新操作--><update id="update">update empset<if test="username != null">username=#{username},</if><if test="name != null">name=#{name},</if><if test="gender != null">gender=#{gender},</if><if test="image != null">image=#{image},</if><if test="job != null">job=#{job},</if><if test="entrydate != null">entrydate=#{entrydate},</if><if test="deptId != null">dept_id=#{deptId},</if><if test="updateTime != null">update_time=#{updateTime}</if>where id=#{id}</update>
​
</mapper>

测试方法:

@Test
public void testUpdate2(){//要修改的员工信息Emp emp = new Emp();emp.setId(20);emp.setUsername("Tom111");emp.setName("汤姆111");
​emp.setUpdateTime(LocalDateTime.now());
​//调用方法,修改员工数据empMapper.update(emp);
}

执行的SQL语句:

再次修改测试方法,观察SQL语句执行情况:

@Test
public void testUpdate2(){//要修改的员工信息Emp emp = new Emp();emp.setId(20);emp.setUsername("Tom222");//调用方法,修改员工数据empMapper.update(emp);
}

执行的SQL语句:

以上问题的解决方案:使用<set>标签代替SQL语句中的set关键字

  • <set>:动态的在SQL语句中插入set关键字,并会删掉额外的逗号。(用于update语句中)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
​<!--更新操作--><update id="update">update emp<!-- 使用set标签,代替update语句中的set关键字 --><set><if test="username != null">username=#{username},</if><if test="name != null">name=#{name},</if><if test="gender != null">gender=#{gender},</if><if test="image != null">image=#{image},</if><if test="job != null">job=#{job},</if><if test="entrydate != null">entrydate=#{entrydate},</if><if test="deptId != null">dept_id=#{deptId},</if><if test="updateTime != null">update_time=#{updateTime}</if></set>where id=#{id}</update>
</mapper>

再次执行测试方法,执行的SQL语句:

小结

  • <if>

    • 用于判断条件是否成立,如果条件为true,则拼接SQL

    • 形式:

      <if test="name != null"> … </if>
  • <where>

    • where元素只会在子元素有内容的情况下才插入where子句,而且会自动去除子句的开头的AND或OR

  • <set>

    • 动态地在行首插入 SET 关键字,并会删掉额外的逗号。(用在update语句中)

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

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

相关文章

你的策略盈利能力怎么样?谈谈伦敦金的回测交易

建立了一个交易系统后&#xff0c;投资者如何测试其有效性呢&#xff1f;有的人会提出让投资者尝试着在实盘或者模拟交易中应用&#xff0c;这个方法是好&#xff0c;但花费的时间较长。有人会就建议&#xff0c;让投资者去做回测。回测是指投资者选定一段历史行情之后&#xf…

Linux 期末复习

Linux 期末复习 计算机历史 硬件基础 1&#xff0c;计算机硬件的五大部件&#xff1a;控制器、运算器、存储器、输入输出设备 2&#xff0c;cpu分为精简指令集(RISC)和复杂指令集(CISC) 3&#xff0c;硬件只认识0和1&#xff0c;最小单位是bit&#xff0c;最小存储单位是字…

React 类组件和函数组件

组件component 一.概念 Element VS Component (元素与组件) //不成文的约定:元素小写&#xff0c;组件大写 const divReact.createElement(div,...) 这是一个React元素(小写) const Div()>React.createElement(div,...) 这是一个React组件(大写) 什么是组件? 能跟其他…

FineBI实战项目一(8):每天每小时订单笔数

1 明确数据分析目标 统计每个小时产生的订单个数 2 创建用于保存数据分析结果的表 create table app_hour_orders(id int primary key auto_increment,daystr varchar(20),hourstr varchar(20),cnt int ); 3 编写SQL语句进行数据分析 selectsubstring(createTime,1,10) as …

如何向管理层制作出优秀的经营分析报告?

在数字化时代&#xff0c;企业不管规模大小&#xff0c;不管是哪个行业&#xff0c;都会有月度、季度、年度经营分析会议&#xff0c;有些是复盘性的&#xff0c;有些是决策性的&#xff0c;面对企业管理层&#xff0c;如何制作出让领导满意且有价值的经营分析报告&#xff1f;…

希尔顿花园酒店喜迎入华十周年里程碑

【2024年1月8日&#xff0c;中国&#xff0c;上海】作为希尔顿集团旗下标志性高端精选服务酒店品牌&#xff0c;希尔顿花园酒店于今年正式迎来其在华经营十周年的里程碑。自2014年中国首家希尔顿花园酒店在深圳开业以来&#xff0c;中国市场已经成为希尔顿花园酒店全球增长的重…

服务器里面打开浏览器访问不了会是什么原因

我们在日常使用服务器的过程中&#xff0c;时常会有遇到各类情况&#xff0c;近日就有遇到用户联系到德迅云安全&#xff0c;反馈自己在服务器里面打不开浏览器&#xff0c;服务器里面没有网络无法访问的情况。那我们今天就来讲下服务器里面打不开网站可能是由哪些原因导致。 …

奇偶链表00

题目链接 奇偶链表 题目描述 注意点 在 O(1) 的额外空间复杂度和 O(n) 的时间复杂度下解决这个问题偶数组和奇数组内部的相对顺序应该与输入时保持一致 解答思路 奇数组的头节点是head&#xff0c;偶数组的头节点是head.next&#xff0c;关键是要改变每个节点的next指针及…

PPT插件-布局参考-增加便携尺寸功能

PPT自带的尺寸为很久的尺寸&#xff0c;很多尺寸不常用&#xff0c;这里增加一些画册尺寸&#xff0c;用于PPT排版设计。 软件介绍 PPT大珩助手是一款全新设计的Office PPT插件&#xff0c;它是一款功能强大且实用的PPT辅助工具&#xff0c;支持Wps Word和Office Word&#x…

众和策略:尔滨!6连板!

1月9日&#xff0c;A股首要指数早盘震动上行。到午间收盘&#xff0c;沪指涨0.34%&#xff0c;深证成指涨0.36%&#xff0c;创业板指涨0.48%&#xff0c;北向资金净买入10.65亿元。 盘面上&#xff0c;冰雪游带火A股商场相关概念股&#xff0c;抢手股大连圣亚、长白山再封涨停…

【C语言】操作符

操作符分类 算术操作符移位操作符位操作符赋值操作符单目操作符关系操作符逻辑操作符条件操作符逗号操作符下标引用、函数调用和结构成员操作符 算术操作符 除了 % 操作符之外&#xff0c;其他的几个操作符可以作用于整数和浮点数。 对于 / 操作符如果两个操作数都为整数&am…

伺服电机:编码器原理与分类

什么是编码器&#xff1f; 编码器是将旋转位置的改变转换为电气信号。 编码器是伺服系统闭环控制不可缺少的部件&#xff0c;编码器应用在轴的闭环控制和大多数的自动化控制中。编码器为闭环控制提供位置或速度的实际测量值。 一、编码器的分类 从编码器的原理和产生的信号类…

数据结构之二叉搜索树(Binary Search Tree)

数据结构可视化演示链接&#xff0c;也就是图片演示的网址 系列文章目录 数据结构之AVL Tree 数据结构之B树和B树 数据结构之Radix和Trie 文章目录 系列文章目录示例图定义二叉搜索树满足的条件应用场景 示例图 二叉 线形(顺序插入就变成了线性树&#xff0c;例如插入顺序为&…

前端八股文(网络篇)一

目录 1.Get和Post的请求的区别 2.常见的HTTP请求头和响应头 3.常见的HTTP请求方法 4.HTTP与HTTPS协议的区别 5.对keep-alive的理解 6.页面有多张图片&#xff0c;HTTP是怎样的加载表现&#xff1f; 7.HTTP请求报文是什么样的&#xff1f; 8.HTTP响应报文是什么样&#x…

[uniapp] uni-ui+vue3.2小程序评论列表组件 回复评论 点赞和删除

先看效果 下载地址 uni-app官方插件市场: cc-comment组件 环境 基于vue3.2和uni-ui开发; 依赖版本参考如下: "dependencies": {"dcloudio/uni-mp-weixin": "3.0.0-3090820231124001","dcloudio/uni-ui": "^1.4.28","…

spring boot 自动扫描Controller、Service、Component原理

项目里面为什么不加上ComponentScan("com.yym.*")注解&#xff0c;也能加载到子目录里面的Controller&#xff0c;Service&#xff0c;Component的bean呢&#xff1f; 启动类没有ComponentScan注解 SpringBootApplication public class BootStrap {public static v…

非常好用的三款图片模糊变清晰的软件

在数字时代&#xff0c;照片的清晰度对于呈现高质量的视觉效果至关重要。然而&#xff0c;由于各种原因&#xff0c;我们有时会遇到模糊的照片。这时候&#xff0c;使用适当的软件来提高照片的清晰度就显得尤为重要。本文将介绍一些可以使模糊照片变清晰的软件&#xff0c;帮助…

前端面试题集合七(ES6、ES7、ES8、ES9、ES10、ES11、ES12)

ES6&#xff08;2015&#xff09; 1. 类&#xff08;class&#xff09; class Man {constructor(name) {this.name 小豪;}console() {console.log(this.name);} } const man new Man(小豪); man.console(); // 小豪 2. 模块化(ES Module) // 模块 A 导出一个方法 export …

Redis:原理速成+项目实战——Redis实战5(互斥锁、逻辑过期解决缓存击穿问题)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;Redis&#xff1a;原理速成项目实战——Redis实战4&#xff08;解决Redis缓存穿透、雪崩、击穿&#xff09; &#x1f4da;订阅专…

Python(30):非对称加密算法RSA的使用(openssl生成RSA公私钥对)

Python(30)&#xff1a;非对称加密算法RSA的使用(openssl生成RSA公私钥对) 1、openssl生成RSA公私钥对 1.1、生成RSA公私钥对命令 [rootloaclhost ~]# openssl OpenSSL> genrsa -out rsa_private_key.pem 1024 Generating RSA private key, 1024 bit long modulus .. ...…