当前位置: 首页 > news >正文

被拷打已老实!面试官问我 #{} 和 ${} 的区别是什么?

引言:在使用 MyBatis 进行数据库操作时,#{}${} 的区别是面试中常见的问题,对理解如何在 MyBatis 中安全有效地处理 SQL 语句至关重要。正确使用这两种占位符不仅影响应用的安全性,还涉及到性能优化。

题目

被拷打已老实!面试官问我 #{} 和 ${} 的区别是什么?

推荐解析

预编译与直接替换

面试官问了我这个问题,直接把我问老实了,求放过,赶忙来写下以下思考:

1)#{}:使用 #{} 时,MyBatis 为 SQL 语句的参数生成一个预编译语句,并通过参数占位符(?)来代替实际的参数值。这种方式是安全的,因为它防止了 SQL 注入攻击,参数值在发送到数据库之前不会被解析为 SQL 的一部分。

如果你有一个查询用户的操作,你可以这样写:

SELECT * FROM users WHERE id = #{userId}

2)${}:相反,使用 ${} 时,参数值被直接替换到 SQL 语句中。这种方式虽然灵活,可以动态替换表名、列名等 SQL 语句的组成部分,但却可能导致 SQL 注入问题,因为参数值如果包含恶意的 SQL 代码也会被执行。

如果你需要动态地选择表名或列名,可以这样使用:

SELECT * FROM ${tableName}

性能考虑

对于性能我得出以下思考:

1)#{} 性能优势:由于使用预编译的 SQL 语句,数据库可以重用相同结构的 SQL 语句,减少编译次数,提高执行效率。

2)${} 性能问题:可能导致每次都要编译新的 SQL 语句,因为 SQL 结构可能因为参数的不同而改变。

类型处理

琢磨琢磨我又发现了新大陆!类型处理~

1)#{} 类型处理:MyBatis 可以根据参数的 Java 类型自动推断数据库类型,处理日期、枚举等复杂类型的转换。

2)${} 类型处理:不进行类型转换,将参数视为纯文本,直接嵌入到 SQL 语句中。

鱼聪明 AI 的回答:

鱼聪明 AI 地址:https://www.yucongming.com/

#{}(参数占位符)

  • 预编译#{} 表达式使得参数在 SQL 语句中以占位符 ? 的形式出现。这意味着 SQL 语句会被预编译并多次执行,参数值在运行时绑定。这种方式对于数据库性能优化至关重要,因为预编译可以减少数据库编译SQL的次数,提高执行效率。
  • 防止 SQL 注入:由于参数不是直接拼接到 SQL 语句中,而是作为一个绑定的值传递给预编译的 SQL 语句,因此 #{} 防止了 SQL 注入的风险。用户输入被当作字符串处理,不会被执行为 SQL 代码的一部分。
  • 类型安全:MyBatis 能够根据 Java 类型自动推断出相应的 SQL 类型。例如,如果你传递一个 Java Date 对象,MyBatis 会适当地处理它与 SQL 日期类型之间的转换。

${}(SQL 字符串拼接)

  • 直接替换:使用 ${} 时,参数值会在解析 SQL 语句之前直接替换到 SQL 字符串中。这意味着你可以通过 ${} 插入动态表名、列名或者其他 SQL 片段,如动态排序条件。
  • 高风险${} 由于是直接将参数内容拼接到 SQL 语句中,所以存在 SQL 注入的风险。如果参数值来自不可控的用户输入,那么可能被注入恶意的 SQL 代码。
  • 灵活性:尽管风险较高,${} 在某些场景下是必要的。特别是在 SQL 语句的某些部分无法通过预编译实现,如动态改变表名或某些数据库函数和命令,${} 提供了必要的灵活性。

推荐文章和书籍

文章:https://zhuanlan.zhihu.com/p/86293659

书籍:《 Java 核心技术卷 I 》

欢迎交流

当讨论 MyBatis 中的 #{}${} 占位符时,我们可以从以下几个角度深入探讨它们的概念、区别和实际应用,以便更好地理解它们在数据库操作中的作用:

1)什么是 #{}${}?它们在 MyBatis 中有什么应用?

2)#{}${} 的工作原理是什么?

3)#{}${} 在实际应用中的选择标准是什么?

相关文章:

  • 算法金 | 再见!!!梯度下降(多图)
  • 力扣469A
  • C++ 50 之 继承中的对象模型
  • 就因为没在大屏项目加全屏按钮,早上在地铁挨了领导一顿骂
  • javaweb 期末复习
  • 分页插件结合collection标签后分页数量不准确的问题
  • 小知识点快速总结:Batch Normalization Layer(BN层)的作用
  • phpcms仿蚁乐购淘宝客网站模板
  • android的surface
  • Sui主网升级至V1.27.2版本
  • Z世代职场价值观的重塑:从“班味”心态到个人成长的追求
  • vue实现全屏screenfull-封装组件
  • 【尝鲜】SpringCloudAlibaba AI 配置使用教程
  • docker封禁对外端口映射
  • xcode报错合集,你都遇到过哪些跳不过的坑
  • ----------
  • (ckeditor+ckfinder用法)Jquery,js获取ckeditor值
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • CSS中外联样式表代表的含义
  • C语言笔记(第一章:C语言编程)
  • javascript 总结(常用工具类的封装)
  • js
  • Linux gpio口使用方法
  • MobX
  • MYSQL 的 IF 函数
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • node学习系列之简单文件上传
  • php面试题 汇集2
  • QQ浏览器x5内核的兼容性问题
  • quasar-framework cnodejs社区
  • uva 10370 Above Average
  • Vue.js 移动端适配之 vw 解决方案
  • 简单易用的leetcode开发测试工具(npm)
  • 每天10道Java面试题,跟我走,offer有!
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 系统认识JavaScript正则表达式
  • 在weex里面使用chart图表
  • 你对linux中grep命令知道多少?
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • ​学习笔记——动态路由——IS-IS中间系统到中间系统(报文/TLV)​
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • #pragma预处理命令
  • (02)Hive SQL编译成MapReduce任务的过程
  • (7)svelte 教程: Props(属性)
  • (c语言版)滑动窗口 给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度
  • (solr系列:一)使用tomcat部署solr服务
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (三十五)大数据实战——Superset可视化平台搭建
  • (深度全面解析)ChatGPT的重大更新给创业者带来了哪些红利机会
  • (十六)串口UART
  • (数据结构)顺序表的定义