MyBatis中#和$符的区别,sql注入问题,动态sql语句

news2024/11/24 19:32:52

MyBatis中#{}和${}的区别

  1. #{}和${}都是MyBatis提供的sql参数替换。区别是:
  2. #{}是预编译处理,${}是字符串直接替换。
  3. #{}可以防止SQL注入,${}存在SQL注入的风险,例如  “' or 1='1”
  4. 虽然存在SQL注入风险,但也有自己的适用场景,比如排序功能,表名,字段名等作为参数传入时。
  5. #{}模糊查询要搭配使用mysql内置的拼接函数concat,安全性高。模糊查询虽然${}可以完成,但是存在SQL注入,不安全。

直接替换是指:是MyBatis 在处理 ${} 时,就是把 ${} 替换成变量的值。

预编译处理是指:MyBatis 在处理#{}时,会将 SQL 中的 #{} 替换为?号,使⽤ PreparedStatement 的 set ⽅法来赋值。

$是直接替换,传入的SQL参数若遇到String类型时,不会自动加单/双引号,就会报错,必须加单/双引号才不出错。并且还有sql注入问题。不过$也有自己的使用场景,比如排序,传入desc,asc字符串时,是不需要加单/双引号的。此时就可以用$,并且这两个字符串不让用户自己传,直接给升序,降序按钮,也就避免了sql注入风险。能发生SQL注入主要还是为用户提供了输入框,用户能传参。

而#无论是Integer类型,还是String类型,都会提前预编译,预编译SQL,而且预编译SQL的性能更高。遇到String类型会自动加单/双引号。

以模糊查询为例,${}和#{}的使用区别

  • 使用${},但存在SQL注入风险。
<select id="getBookByNname" resultType="com.example.demo.entity.BookInfo">
    select * from book_info where book_name like '${bookName}';
</select>
  • 使用#{},更安全,更高效。
<select id="getBookByName" resultType="com.example.demo.entity.BookInfo">
    select * from book_info where book_name like concat('%',#{bookName},'%');
</select>

SQL注入问题${}

代码演示,所传参数后跟  ' or '1=1 。就会查出全结果集。

bookMapper.getBookByN("平凡的世界' or '1=1");  //传入参数
select * from book_info where book_name = '${bookName}'; //SQL语句

SQL日志打印:


动态 SQL 语法

1.<if>标签
  • 使用场景:当我们在输入个人信息的时候,不一定都得填写(必填项+非必填项),这时候有的参数就为空。所以在插入时就得判空。
    <insert id="insert" useGeneratedKeys="true" keyProperty="id">
            insert into userinfo {
                username,
                password,
                nickname,
                <if test="sex != null"> //test中的sex是属性,不是字段
                    sex,
                </if>
                }
                birthday
            )values (
                #{username},
                #{password},
                #{nickname},
                <if test="sex !=null"> //test中的这里的sex是属性
                   #{sex},
                </if>
                #{birthday}
            )
    </insert>

注意 test 中的 sex,是传⼊对象中的属性,不是数据库字段。


2.<trim>标签

prefix:表示整个语句块,以prefix的值作为前缀

suffix:表示整个语句块,以suffix的值作为后缀

prefixOverrides:表示整个语句块要去除掉的前缀

suffixOverrides:表示整个语句块要去除掉的后缀

  • 如果输入参数全是非必填项。就需要if标签和trim标签相结合。
     <insert id="ss" useGeneratedKeys="true" keyProperty="id">
            insert into userinfo
            <trim prefix="(" suffix=")" suffixOverrides=",">
                <if test="username != null">username,</if> //别忘记逗号
                <if test="password != null">password,</if> //test中的是属性,不是字段
                <if test="nickname != null">nickname,</if>
                <if test="sex != null">sex,</if>
                <if test="birthday != null">birthday,</if>
            </trim>
            <trim prefix="values (" suffix=")" suffixOverrides=",">
                <if test="username != null">#{username},</if>
                <if test="nickname != null">#{nickname},</if>
                <if test="sex != null">#{sex},</if>
                <if test="birthday != null">#{birthday},</if>
            </trim>
      </insert>

3.<where>标签
  • 对于where后跟的参数是否为空,不清楚时。
    <select id="select" parameterType="com.example.demo.entity.UserInfo"> //parameterType为 
                                                                            传入的参数类型
        select * from usrinfo
        <where>
            <if test="username != null">and username = #{username}</if>
            <if test="userId != null">and userId = #{userId}</if>
            <if test="sex != null">and sex = #{sex}</if>
        </where>
    </select>

以上标签也可以使⽤ <trim prefix="where" suffixOverrides="and"> 替换。


4.<set>标签
  • 动态update操作
    //parameterType 为传入参数的类型
    <update id="update" parameterType="com.example.demo.entity.UserInfo">
        update userinfo
        <set>
            <if test="username != null">username = #{username},</if>
            <if test="password != null">password = #{password},</if>
            <if test="nickname != null">nickname = #{nickname},</if>
            <if test="sex != null">sex = #{sex},</if>
            <if test="birthday != null">birthday = #{birthday},</if>
        </set>
        where = #{id}
    </update>

以上标签也可以使⽤ <trim prefix="set suffixOverrides=","> 替换。


5.<foreach>标签
  • 遍历集合(如List)时,可以使用,例如批量删除等操作。
    // collection 集合类型  item集合名
    <delete id="deleteByIds">
        delete from userinfo where id in
        <foreach collection="list" item="item" open="(" close=")" separator=",">
            #{list}
        </foreach>
    </delete>

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

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

相关文章

CSS Selector—选择方法,和html自动——异步社区的爬取(动态网页)——爬虫(get和post的区别)

这里先说一下GET请求和POST请求&#xff1a; post我们平时是要加data的也就是信息&#xff0c;你会发现我们平时百度之类的 搜索都是post请求 get我们带的是params&#xff0c;是发送我们指定的内容。 要注意是get和post请求&#xff01;&#xff01;&#xff01; 先说一下异…

python基于flask的网上订餐系统769b9-django+vue

课题主要分为两大模块&#xff1a;即管理员模块和用户模块&#xff0c;主要功能包括个人中心、用户管理、菜品类型管理、菜品信息管理、留言反馈、在线交流、系统管理、订单管理等&#xff1b; 如果用户想要交换信息&#xff0c;他们需要满足双方交换信息的需要。由于时间有限…

2.10日学习打卡----初学RocketMQ(一)

2.10日学习打卡 对于MQ(Message queue)消息队列的一些解释可以看我原来写的文章 初学RabbitMQ 各大MQ产品比较 一.RocketMQ概述 发展历程 RocketMQ概念术语 生产者和消费者 生产者负责生产消息&#xff0c;一般由业务系统负责生产消息&#xff0c;消费者即后台系统&…

算法-3-基本的数据结构

单双链表 1.单链表双链表如何反转 import java.util.ArrayList; import java.util.List;public class Code01_ReverseList {public static class Node {public int value;public Node next;public Node(int data) {value data;}}public static class DoubleNode {public int…

C/C++模板初阶

目录 1. 泛型编程 2. 函数模板 2.1 函数模板概念 2.1 函数模板格式 2.3 函数模板的原理 2.4 函数模板的实例化 2.5 模板参数的匹配原则 3. 类模板 3.1 类模板的定义格式 3.2 类模板的实例化 1. 泛型编程 如何实现一个通用的交换函数呢&#xff1f; void Swap(int&…

微软和苏黎世联邦理工学院开源SliceGPT创新压缩技术节省大量部署资源;OpenAI成立儿童安全团队,防AI误用

&#x1f989; AI新闻 &#x1f680; 微软和苏黎世联邦理工学院开源SliceGPT创新压缩技术节省大量部署资源 摘要&#xff1a;微软和苏黎世联邦理工学院研究人员开源了SliceGPT&#xff0c;通过对大模型的权重矩阵进行压缩切片&#xff0c;实现了模型紧缩&#xff0c;节省了部…

CSS盒子的概念

盒子模型 盒子的概念 页面中的每一个标签都可以看做是一个“盒子”&#xff0c;通过盒子的视角更方便的进行布局 浏览器在渲染&#xff08;显示&#xff09;网页时&#xff0c;会将网页中的元素看做是一个个的矩形区域&#xff0c;称之为“盒子” 盒子模型 CSS中规定每个盒…

JAVA设计模式之迭代器模式详解

迭代器模式 1 迭代器模式介绍 迭代器模式是我们学习一个设计时很少用到的、但编码实现时却经常使用到的行为型设计模式。在绝大多数编程语言中&#xff0c;迭代器已经成为一个基础的类库&#xff0c;直接用来遍历集合对象。在平时开发中&#xff0c;我们更多的是直接使用它&a…

联想thinkpad-E450双系统升级记

早期笔记本联想thinkpad-E450双系统 大约16年花4000多大洋&#xff0c;买了一台thinkpad-E450屏幕是16寸本&#xff0c;有AMD独立显卡&#xff0c;i5cpu&#xff0c;4G内存。 . 后来加了一个同型号4G内存组成双通道&#xff0c; . 加了一个三星固态500G&#xff0c; . 换了一个…

如何编写高效的可复用程序

子程序、FB 、FC等的相关内容还可以查看下面文章链接&#xff1a; https://rxxw-control.blog.csdn.net/article/details/124524693https://rxxw-control.blog.csdn.net/article/details/124524693 1、FB和FC编程的优点 待续.....

前置++与后置++

a相当于a的值在其中运算 a

02 动力云客之登陆界面

1. 前端登录界面 需求样式: 1. 自定义登录页面装配到main.js src下新建一个文件夹view, view下新建一个Vue Component , 名为LoginView.vue , 并选择options API Composition API用于复杂页面. 生成的LoginView.vue文件 <script> export default {//组件的名字nam…

【2024.02.11】定时执行专家 V6.9 龙年春节版 - 下载地址更新日志

目录 ◆ 最新版下载链接 ◆ 软件更新日志 – TimingExecutor Full Change Log ▼2024-02-11 V6.9 ▼2023-06-16 V6.8.2 ▼2023-02-27 V6.7 ▼ 2023-01-23 V6.6 ▼ 2023-01-20 V6.5 ▼ 2022-12-25 V6.4 ▼ 2022-11-15 V6.3 ▼ 2022-10-01 V6.2 ▼ 2022-07-…

苍穹外卖实操笔记六---缓存商品,购物车功能

苍穹外卖实操笔记六—缓存商品&#xff0c;购物车功能 一.缓存菜品 可以使用redis进行缓存&#xff1b;另外&#xff0c;在实现缓存套餐时可以使用spring cache提高开发效率&#xff1b;   通过缓存数据&#xff0c;降低访问数据库的次数&#xff1b; 使用的缓存逻辑&#…

uniapp微信小程序开发踩坑日记:Pinia持久化

如果你使用过Pinia&#xff0c;那你应该知道Pinia持久化插件&#xff1a;https://prazdevs.github.io/pinia-plugin-persistedstate/zh/ 但由于官方文档提供的说明并不是针对小程序开发&#xff0c;所以我们在使用这个插件实现uniapp小程序开发中Pinia持久化会出现问题 我在C…

ubuntu中尝试安装ros2

首先&#xff0c;ubuntu打开后有个机器人栏目&#xff0c;打开后&#xff0c;有好多可选的&#xff0c;看了半天 ,好像是博客&#xff0c;算了&#xff0c;没啥关系&#xff0c;再看看其他菜单 这些都不是下载链接。先不管&#xff0c;考虑了一下&#xff0c;问了ai&#xff…

Z-Stack一直卡在HAL_BOARD_INIT();

原因是Debugger没有配置好&#xff0c;因为默认是Simulator&#xff0c;不是TI的驱动&#xff0c;所以仿真出现一直卡在 HAL_BOARD_INIT(); 的情况&#xff0c;解决方法就是将Simulator改为Texas Instruments 改成下面的样子

Unity Meta Quest MR 开发(四):使用 Scene API 和 Depth API 实现深度识别和环境遮挡

文章目录 &#x1f4d5;教程说明&#x1f4d5;Scene API 实现遮挡&#x1f4d5;Scene API 实现遮挡的缺点&#x1f4d5;Depth API 实现遮挡⭐导入 Depth API⭐修改环境配置⭐添加 EnvironmentDepthOcclusion 预制体⭐给物体替换遮挡 Shader⭐取消现实手部的遮挡效果 此教程相关…

如何入门AI Agent?

随着chatgpt问世&#xff0c;大模型已经在加速各行各业的变革&#xff0c;这是我之前对AI Agent行业的粗浅判断。 下面给大家介绍一下如何制作AI Agent&#xff0c;我会用我开发的全赞AI为例子进行简要的介绍&#xff0c;下面是一种工具型AI Agent的框架图 这是一个大量使用工具…

vue中watch和computed的不同

第076个 查看专栏目录: VUE ------ element UI Vue.js 中的 watch 和 computed 都是用于监听数据变化并执行相应操作的选项&#xff0c;但它们的使用场景和优劣势有所不同。 两者区别 watch 用于监听一个或多个数据属性的变化&#xff0c;并在变化时执行相应的处理函数。 它…