【MyBatis】MyBatis操作数据库(二):动态SQL、#{}与${}的区别

2024-06-18 1081阅读

目录

  • 一、 动态SQL
      • 1.1 \标签
      • 1.2 \标签
      • 1.3 \标签
      • 1.4 \标签
      • 1.5 \标签
      • 1.6 \标签
      • 二、 #{}与${}的区别
          • 2.1 #{}是预编译sql,${}是即时sql
          • 2.2 SQL注入
          • 2.3 #{}性能高于${}
          • 2.4 ${}用于排序功能

            一、 动态SQL

            什么是动态SQL,简单来说就是为了满足我们的条件可以将不同是SQL语句进行拼接,来使用.

            1.1 标签

            在我们编程SQL语句中,时常有些参数不知道是否传参,在以往的编程中我们是使用if语句进行判读,在这里也同样如此,只是换成了标签进行判断。

            标签的代码如下:

            gender,
            
            

            使用标签将我们要判断的内容包裹起来即可。

            1.2 标签

            在我们判断的时候,有时会有多余的标点符号或是我们想要在sql语句前添加一下其它关键词,这时候就该标签派上用场了。

            标签一共有四个属性,记住了属性是添加在中的,记住添加的位置.

            有以下四个属性:

            • prefix:表⽰整个语句块,以prefix的值作为前缀
            • suffix:表⽰整个语句块,以suffix的值作为后缀
            • prefixOverrides:表⽰整个语句块要去除掉的前缀
            • suffixOverrides:表⽰整个语句块要去除掉的后缀

              举例代码如下:

              	
              		username,
              	
              	
              	
              		`password`,
              	
              	
              	
              		age,
              	
              	
              	
              		gender,
              	
              	
              	
              		phone,
              	
              	
              
              

              可以看到动态SQL是可以一起进行拼接使用的,在举例的该段代码中用到了,prefix用来在前缀添加、suffix用来后缀添加、suffixOverrides用来删除后缀标点,相信举了这个例子另外的的一个predixOverrides也会用了吧!

              1.3 标签

              在SQL语句中,where关键字一般是用来进行条件判断的,在动态SQL中也是如此,只是我们给它换成的标签形式会更加合理方便

              代码如下:

              	
              		and age = #{age}
              	
              	
              	
              		and gender = #{gender}
              	
              	
              	
              		and delete_flag = #{deleteFlag}
              	
              	
              
              

              在动态SQL中使用标签能够在⼦元素有内容的情况下才插⼊where⼦句,⽽且会⾃动去除⼦句的开头的AND或OR

              1.4 标签

              标签标签一般用在修改数据库的SQL语句中,可以使⽤标签来指定动态内容.

              代码如下:

              	
              		username = #{username},
              	
              	
              	
              		delete_flag = #{deleteFlag},
              	
              
              

              :动态的在SQL语句中插⼊set关键字,并会删掉额外的逗号.(⽤于update语句中)

              1.5 标签

              对集合进⾏遍历时可以使⽤该标签。标签有如下属性:

              • collection:绑定⽅法参数中的集合,如List,Set,Map或数组对象

              • item:遍历时的每⼀个对象

              •open:语句块开头的字符串

              • close:语句块结束的字符串

              • separator:每次遍历之间间隔的字符串

              代码如下:

              	#{id}
              
              

              使用标签就跟使用常见代码中的foreach用法一样,都是用来遍历数组等结构里的每一个元素.

              1.6 标签

              在xml映射⽂件中配置的SQL,有时可能会存在很多重复的⽚段,此时就会存在很多冗余的代码,而就是将重复的代码提取出来,在后面使用该重复代码中直接拿出来就行了,这里与resultMapper倒是有点相似.

              我们可以对重复的代码⽚段进⾏抽取,将其通过 标签封装到⼀个SQL⽚段,然后再通过

              标签进⾏引⽤。

              :定义可重⽤的SQL⽚段

              :通过属性refid,指定包含的SQL⽚段

              展示定义重复的代码-标签如下:

              	id, username, age, gender, phone, 
              	delete_flag, create_time,update_time
              
              

              使用标签调用已经定义好的代码块如下:

               
              

              通过标签定义的属性名进行调用.

              二、 #{}与${}的区别

              MyBatis参数赋值有两种⽅式,咱们前⾯使⽤了 #{} 进⾏赋值,接下来我们看下⼆者的区别

              #{}和${}都是在MyBatis操作数据库时进行取值的操作,且两者有以下三点区别,可能平时#{}是用的最多的,但既然${}存在便有其存在的价值和用处。

              #{}和${}的区别:

              1. #{}是预编译sql,${}是即时sql

              2. #{}防止了sql注入,而${}可能被sql注入

              3. #{}的缓存性能比${}强大

              4. ${}特殊用处:数据库进行排序…等操作时

              2.1 #{}是预编译sql,${}是即时sql

              #{}是预编译sql,简单来说就是在程序编译时,用?来作占位符,然后根据传入的参数类型进行填充,如果传入的参数是String类型,则在填充时会自动给数据添加双引号"",来表示该字符串。

              sql代码如下:

              select username, `password`, age, gender, phone from userinfo where id= ?
              

              【MyBatis】MyBatis操作数据库(二):动态SQL、#{}与${}的区别

              我们输⼊的参数并没有在后⾯拼接,id的值是使⽤ ? 进⾏占位.这种SQL我们称之为"预编译SQL"

              然而${}是即时SQL简单来说就是没有占位符,不管你输入的数据是啥,它直接给你填充到参数的位置上去,即使是字符串类型也没有特殊处理,这时为了保证SQL正确,我们要自己手动添加""。

              下面是使用${}时的SQL代码:

              @Select("select username, `password`, age, gender, phone from userinfo where
              id= ${id} ")
              UserInfo queryById(Integer id);
              

              代码运行的结果是:

              【MyBatis】MyBatis操作数据库(二):动态SQL、#{}与${}的区别

              可以看到,我们输入的参数直接添加到了SQL语句中了,这就是即时SQL-${}

              小总结:

              从上⾯例⼦可以看出:

              #{} 使⽤的是预编译SQL,通过 ? 占位的⽅式,提前对SQL进⾏编译,然后把参数填充到SQL语句中.

              #{} 会根据参数类型,⾃动拼接引号"‘’ . ${} 会直接进⾏字符替换,⼀起对SQL进⾏编译.如果参数为字符串,需要加上引号 ‘’ .

              2.2 SQL注入

              首先来了解一下什么是SQL注入,SQL注入是由于前后端的漏洞而导致的Bug,黑客攻击人员可以通过前端的登录页面将数据输入到数据库,以达到修改甚至是删除数据库的目的。

              通过上面学习我们可知,#{}是预编译SQL,而${}是即时SQL,当黑客在前端输入的数据是字符型sql“delete 数据库 ”,如果我们后端是用预编译SQL-#{}来取值的话,系统会看它是字符类型而添加"",进而导致SQL语句错误无法执行。

              而使用即时SQL的话,是直接进行SQL拼接,会把delete database数据库直接拼接上去不带引号,这时数据库执行就会成功,把该公司的数据库删除掉。

              小总结:

              #{}会根据数据类型进行判断是否添加双引号""

              而KaTeX parse error: Expected 'EOF', got '#' at position 21: …拼接上去,使数据库被黑客攻击 #̲{}能够防止SQL注入,而{}会被SQL注入攻击

              2.3 #{}性能高于${}

              绝⼤多数情况下,某⼀条SQL语句可能会被反复调⽤执⾏,或者每次执⾏的时候只有个别的值不同(⽐如select的where⼦句值不同,update的set⼦句值不同,insert的values值不同).

              如果每次都需要经过上⾯的语法解析,SQL优化、SQL编译等,则效率就明显不⾏了.

              【MyBatis】MyBatis操作数据库(二):动态SQL、#{}与${}的区别

              预编译SQL,编译⼀次之后会将编译后的SQL语句缓存起来,后⾯再次执⾏这条语句时,不会再次编译(只是输⼊的参数不同),省去了解析优化等过程,以此来提⾼效率

              2.4 ${}用于排序功能

              ${}会有SQL注⼊的⻛险,所以我们尽量使⽤#{}完成查询,所谓它的存在就有一定的道理,如下在排序时就要用到即时SQL了。

              @Select("select id, username, age, gender, phone, delete_flag, create_time,
              update_time " +
              "from userinfo order by id ${sort} ")
              List queryAllUserBySort(String sort);
              

              使⽤${sort} 可以实现排序查询,⽽使⽤#{sort} 就不能实现排序查询了.

              注意:此处sort参数为String类型,但是SQL语句中排序规则是不需要加引号 ‘’ 的,所以此时的${sort} 也不加引号,而使用#{}则会自动添加双引号"",就无法实现排序的功能了。

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]