Java课题笔记~ 动态SQL详解

一、动态 sql 是什么?

1、动态 SQL 是 MyBatis 的强大特性之一。在 JDBC 或其它类似的框架中,开发人员通常需要手动拼接 SQL 语句。根据不同的条件拼接 SQL 语句是一件极其痛苦的工作。

例如,拼接时要确保添加了必要的空格,还要注意去掉列表最后一个列名的逗号。而动态 SQL 恰好解决了这一问题,可以根据场景动态的构建查询。

2.动态SQL:code that is executed dynamically。

它一般是根据用户输入或外部条件动态组合的SQL语句块。

动态SQL能灵活的发挥SQL强大的功能、方便的解决一些其它方法难以解决的问题。 然而动态SQL有时候在执行性能 (效率)上面不如静态SQL,而且使用不恰当,往往会在安全方面存在隐患 (SQL 注入式攻击)。


二、Mybatis 动态 sql 是做什么的?

Mybatis 动态 sql 可以让我们在 Xml 映射文件内,以标签的形式编写动态 sql,完成逻辑判断和动态拼接 sql 的功能。

三、Mybatis 的 9 种 动 态 sql 标 签有哪些?

 

四、动态 sql 的执行原理?

使用 OGNL 从 sql 参数对象中计算表达式的值,根据表达式的值动态拼接 sql,以此来完成动态 sql 的功能。

五、MyBatis标签详解

1、if标签

MyBatis if 类似于 Java 中的 if 语句,是 MyBatis 中最常用的判断语句。

使用 if 标签可以节省许多拼接 SQL 的工作,把精力集中在 XML 的维护上。

1)不使用动态sql

<select id="selectUserByUsernameAndSex"resultType="user" parameterType="com.ys.po.User"><!-- 这里和普通的sql 查询语句差不多,对于只有一个参数,后面的 #{id}表示占位符,里面          不一定要写id,写啥都可以,但是不要空着,如果有多个参数则必须写pojo类里面的属性 -->select * from user where username=#{username} and sex=#{sex}
</select>

if 语句使用方法简单,常常与 test 属性联合使用。语法如下:

<if test="判断条件">    SQL语句</if>

2)使用动态sql


上面的查询语句,我们可以发现,如果 #{username} 为空,那么查询结果也是空,应该使用 if 来判断,可多个 if 语句同时使用。

以下语句表示为可以按照网站名称(name)或者网址(url)进行模糊查询。如果您不输入名称或网址,则返回所有的网站记录。但是,如果你传递了任意一个参数,它就会返回与给定参数相匹配的记录。

<select id="selectAllWebsite" resultMap="myResult">  select id,name,url from website where 1=1    <if test="name != null">        AND name like #{name}   </if>    <if test="url!= null">        AND url like #{url}    </if></select>

2、where+if标签

where、if同时使用可以进行查询、模糊查询

注意:`<if>`失败后, `<where>` 关键字只会去掉库表字段赋值前面的and,不会去掉语句后面的and关键字

`<where>` 只会去掉`<if>` 语句中的最开始的and关键字。所以下面的形式是不可取的:

<select id="findQuery" resultType="Student"><include refid="selectvp"/><where><if test="sacc != null">sacc like concat('%' #{sacc} '%')</if><if test="sname != null">AND sname like concat('%' #{sname} '%')</if><if test="sex != null">AND sex=#{sex}</if><if test="phone != null">AND phone=#{phone}</if></where></select>

这个“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉。

3、set标签

set可以用来修改:

<update id="upd">update student<set><if test="sname != null">sname=#{sname},</if><if test="spwd != null">spwd=#{spwd},</if><if test="sex != null">sex=#{sex},</if><if test="phone != null">phone=#{phone}</if>sid=#{sid}</set>where sid=#{sid}</update>

4、choose(when,otherwise) 语句

有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可

使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句

<select id="selectUserByChoose" resultType="com.ys.po.User" parameterType="com.ys.po.User">select * from user<where><choose><when test="id !='' and id != null">id=#{id}</when><when test="username !='' and username != null">and username=#{username}</when><otherwise>and sex=#{sex}</otherwise></choose></where></select>

也就是说,这里我们有三个条件【id,username,sex】只能选择一个作为查询条件

如果 id 不为空,那么查询语句为:

select * from user where  id=?

如果 id 为空,那么看username 是否为空,如果不为空,那么语句为:

select * from user where username=?;

如果 username 为空,那么查询语句为:

select * from user where sex=?

5、trim标签

trim标记是一个格式化的标记,可以完成set或者是where标记的功能

① 用 trim 改写上面第二点的 if+where 语句

<select id="selectUserByUsernameAndSex" resultType="user" parameterType="com.ys.po.User">select * from user<!-- <where><if test="username != null">username=#{username}</if><if test="username != null">and sex=#{sex}</if></where>  --><trim prefix="where" prefixOverrides="and | or"><if test="username != null">and username=#{username}</if><if test="sex != null">and sex=#{sex}</if></trim></select>

prefix:前缀      

prefixoverride:去掉第一个and或者是or

② 用 trim 改写上面第三点的 if+set 语句

<!-- 根据 id 更新 user 表的数据 --><update id="updateUserById" parameterType="com.ys.po.User">update user u<!-- <set><if test="username != null and username != ''">u.username = #{username},</if><if test="sex != null and sex != ''">u.sex = #{sex}</if></set> --><trim prefix="set" suffixOverrides=","><if test="username != null and username != ''">u.username = #{username},</if><if test="sex != null and sex != ''">u.sex = #{sex},</if></trim>where id=#{id}</update>

suffix:后缀  

suffixoverride:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的and一样)

③ trim+if同时使用可以添加

<insert id="add">insert  into student<trim prefix="(" suffix=")" suffixOverrides=","><if test="sname != null">sname,</if><if test="spwd != null">spwd,</if><if test="sex != null">sex,</if><if test="phone != null">phone,</if></trim>
​<trim prefix="values (" suffix=")"  suffixOverrides=","><if test="sname != null">#{sname},</if><if test="spwd != null">#{spwd},</if><if test="sex != null">#{sex},</if><if test="phone != null">#{phone}</if></trim>
​</insert>

6、foreach标签

foreach是用来对集合的遍历,这个和Java中的功能很类似。通常处理SQL中的in语句。

foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。

它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符

你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。

当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素;当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

//批量查询
<select id="findAll" resultType="Student" parameterType="Integer"><include refid="selectvp"/> WHERE sid in<foreach item="ids" collection="array"  open="(" separator="," close=")">#{ids}</foreach>
</select>
//批量删除
<delete id="del"  parameterType="Integer">delete  from  student  where  sid in<foreach item="ids" collection="array"  open="(" separator="," close=")">#{ids}</foreach>
</delete>

7、sql语句

在实际开发中会遇到许多相同的SQL,比如根据某个条件筛选,这个筛选很多地方都能用到,我们可以将其抽取出来成为一个公用的部分,这样修改也方便,一旦出现了错误,只需要改这一处便能处处生效了,此时就用到了<sql>这个标签了。

当多种类型的查询语句的查询字段或者查询条件相同时,可以将其定义为常量,方便调用。为求 <select> 结构清晰也可将 sql 语句分解。

<sql id="selectvp">select  *  from  student
</sql>

8、include标签

这个标签和<sql>是天仙配,是共生的,include用于引用sql标签定义的常量。比如引用上面sql标签定义的常量。

refid这个属性就是指定<sql>标签中的id值(唯一标识)

<select id="findbyid"  resultType="student"><include refid="selectvp"/>WHERE 1=1<if test="sid != null">AND sid like #{sid}</if>
</select>
  • 9、bind标签

mybatis的动态SQL都是用OGNL表达式进行解析的,如果需要创建OGNL表达式以外的变量,可以用bind标签。

<select id="selectBlogsLike" resultType="Blog">
<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}
</select>

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

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

相关文章

cnvd通用型证书获取姿势

因为技术有限&#xff0c;只能挖挖不用脑子的漏洞&#xff0c;平时工作摸鱼的时候通过谷歌引擎引擎搜索找找有没有大点的公司有sql注入漏洞&#xff0c;找的方法就很简单&#xff0c;网站结尾加上’&#xff0c;有异常就测试看看&#xff0c;没有马上下一家&#xff0c;效率至上…

Day12-1-Webpack前端工程化开发

Webpack前端工程化 1 案例-webpack打包js文件 1 在index.html中编写代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><me…

20天学会rust(二)rust的基础语法篇

在第一节&#xff08;20天学rust&#xff08;一&#xff09;和rust say hi&#xff09;我们配置好了rust的环境&#xff0c;并且运行了一个简单的demo——practice-01&#xff0c;接下来我们将从示例入手&#xff0c;学习rust的基础语法。 首先来看下项目结构&#xff1a; 项目…

QtWebApp开发https服务器,完成客户端与服务器基于ssl的双向认证,纯代码操作

引言&#xff1a;所谓http协议&#xff0c;本质上也是基于TCP/IP上服务器与客户端请求和应答的标准&#xff0c;web开发中常用的http server有apache和nginx。Qt程序作为http client可以使用QNetworkAccessManager很方便的进行http相关的操作。Qt本身并没有http server相关的库…

zabbix监控mysql容器主从同步状态并告警钉钉/企业微信

前言&#xff1a;被监控的主机已经安装和配置mysql主从同步&#xff0c;和zabbix-agent插件。 mysql创建主从同步&#xff1a;http://t.csdn.cn/P4MYq centos安装zabbix-agent2&#xff1a;http://t.csdn.cn/fx74i mysql主从同步&#xff0c;主要监控这2个参数指标&#xf…

Maven-学习笔记

文章目录 1. Maven简介2.Maven安装和基础配置3.Maven基本使用4.Maven坐标介绍 1. Maven简介 概念 Maven是专门用于管理和构建Java项目的工具 主要功能有: 提供了一套标准化的项目结构提供了一套标准化的构建流程&#xff08;编译&#xff0c;测试&#xff0c;打包&#xff0c;…

微信小程序中的全局数据共享(状态管理)使用介绍

开发工具&#xff1a;微信开发者工具Stable 1.06 一、状态管理简介 微信小程序全局状态是指可以在不同页面之间共享的数据或状态。 它可以存储用户的登录状态、个人信息、全局配置信息等。 二、安装MobX 1、安装NPM 在资源管理器的空白地方点右键&#xff0c;选择“在外部…

无涯教程-Perl - endhostent函数

描述 此函数告诉系统您不再希望使用gethostent从hosts文件读取条目。 语法 以下是此函数的简单语法- endhostent返回值 此函数不返回任何值。 例 以下是显示其基本用法的示例代码- #!/usr/bin/perlwhile( ($name, $aliases, $addrtype, $length, addrs)gethostent() ) …

5个可以创意灵感的AI绘画工具

当设计灵感耗尽&#xff0c;陷入创作瓶颈时&#xff0c;人工智能艺术生成器可能会为您提供新的启示。这些基于深度学习和发展“神经网络”的工具可以将输入的文本描述或图像转换成各种风格的艺术作品&#xff0c;并提供丰富的风格参数和材料库&#xff0c;让您可以自由调整和创…

【Linux】网络套接字知识点补足

目录 1 地址转换函数 1.1 字符串转in_addr的函数: 1.2 in_addr转字符串的函数: 1.3 关于inet_ntoa 2 TCP协议通讯流程 1 地址转换函数 本节只介绍基于IPv4的socket网络编程,sockaddr_in中的成员struct in_addr sin_addr表示32位 的IP 地址但是我们通常用点分十进制的字符串…

【Java split】split() 函数分割空字符串后数组长度为1的原因以及规避措施(105)

问题现象: import java.util.ArrayList; import java.util.Arrays; import java.util.List;public class test06 {public static void main(String[] args) {// Java split()函数 分割空字符串长度为1的解释&#xff1b;String s2 "";String[] arr2 s2.split(&quo…

Spring 容器原始 Bean 是如何创建的?

以下内容基于 Spring6.0.4。 这个话题其实非常庞大&#xff0c;我本来想从 getBean 方法讲起&#xff0c;但一想这样讲完估计很多小伙伴就懵了&#xff0c;所以我们还是一步一步来&#xff0c;今天我主要是想和小伙伴们讲讲 Spring 容器创建 Bean 最最核心的 createBeanInstan…

【Nginx】静态资源部署、反向代理、负载均衡

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ nginx静态资源部署、反向代理、负载均衡 &…

今年这情况,真想考研了!

眼下&#xff0c;又是一年的毕业季&#xff0c;超千万规模的毕业生大军如“丧尸围城”&#xff0c;浩浩荡荡地涌入职场。与他们一路同行的还有因疫情影响2022年离校未就业的毕业生&#xff0c;以及那些不幸“被优化”的职场人。 今年&#xff0c;1158 万毕业生&#xff0c;再加…

全面解析大语言模型的工作原理

当ChatGPT在去年秋天推出时&#xff0c;在科技行业乃至世界范围内引起了轰动。当时&#xff0c;机器学习研究人员尝试研发了多年的语言大模型&#xff08;LLM&#xff09;&#xff0c;但普通大众并未十分关注&#xff0c;也没有意识到它们变得多强大。 如今&#xff0c;几乎每个…

ASP.NET Core MVC -- 将视图添加到 ASP.NET Core MVC 应用

Index页 右键单击“视图”文件夹&#xff0c;然后单击“添加”>>“新文件夹”&#xff0c;并将文件夹命名为“HelloWorld”。 右键单击“Views/HelloWorld”文件夹&#xff0c;然后单击“添加”>“新项”。 在“添加新项 - MvcMovie”对话框中&#xff1a; 在右上…

区块链实验室(15) - 编译FISCO BCOS的过程监测

首次编译开源项目&#xff0c;一般需要下载很多依赖包&#xff0c;尤其是从github、sourceforge等下载依赖包时&#xff0c;速度很慢&#xff0c;编译进度似乎没有一点反应&#xff0c;似乎陷入死循环&#xff0c;似乎陷入一个没有结果的等待。本文提供一种监测方法&#xff0c…

ClickHouse SQL与引擎--基本使用(一)

1.查看所有的数据库 show databases; 2.创建库 CREATE DATABASE zabbix ENGINE Ordinary; ATTACH DATABASE ck_test ENGINE Ordinary;3.创建本地表 CREATE TABLE IF NOT EXISTS test01(id UInt64,name String,time UInt64,age UInt8,flag UInt8 ) ENGINE MergeTree PARTI…

Linux 中使用 verdaccio 搭建私有npm 服务器

安装 Node Linux中安装Node 安装verdaccio npm i -g verdaccio安装完成 输入verdaccio,出现下面信息代表安装成功&#xff0c;同时输入verdaccio后verdaccio已经处于运行状态&#xff0c;当然这种启动时暂时的&#xff0c;我们需要通过pm2让verdaccio服务常驻 ygiZ2zec61wsg…

探究Vue源码:mustache模板引擎(11) 递归处理循环逻辑并收尾算法处理

好 在上文 探究Vue源码:mustache模板引擎(10) 解决不能用连续点符号找到多层对象问题&#xff0c;为编译循环结构做铺垫 我们解决了js字符串没办法通过 什么点什么拿到对象中的值的问题 这个大家需要记住 因为这个方法的编写之前是当做面试题出现过的 那么 本文 我们就要去写上…