news 2026/2/27 20:03:45

《#{} vs ${}:MyBatis 里这俩符号,藏着性能与安全的 “生死局”》

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
《#{} vs ${}:MyBatis 里这俩符号,藏着性能与安全的 “生死局”》

1.多表查询

多表查询和单表查询类似,只是SQL不同⽽已

数据准备:

对应Model:

数据查询

SQL:

补充实体类:

接⼝定义:

  1. 字段与实体类属性不一致的解决方式:当数据库字段名与实体类属性名不匹配时,可通过ResultMap(自定义映射关系)或 SQL 别名(如SELECT user_name AS userName)来对齐,这一规则同时适用于单表和多表查询。

  2. MyBatis 的核心组成:MyBatis 处理查询(无论单表 / 多表)的核心逻辑由三部分构成:

    • SQL:执行数据查询的语句;
    • 映射关系:关联数据库结果与实体类的规则(如字段 - 属性的对应);
    • 实体类:承载查询结果的数据对象。
  3. 映射关系的作用:通过定义映射规则,将 SQL 执行后的结果集(数据库字段)与实体类的属性关联,实现数据的自动填充。

2.#{}和${}

2.1#{}和${}使⽤

Integer 类型参数:#{} vs ${}

1.#{}的执行(预编译,安全)

代码

执行逻辑:MyBatis 将#{id}替换为?占位符,生成预编译 SQL

  • 参数(如id=1)通过PreparedStatement传入?,日志中体现为Parameters: 1(Integer),最终安全执行。
2.${}的执行(直接拼接,无语法错误但有风险)

代码

执行逻辑:参数直接拼入 SQL,生成即时 SQL

  • 因为id是 Integer 类型,拼接后 SQL 语法合法,能正常执行,但存在 SQL 注入风险(比如参数传入1 or 1=1,会查询全表)。

String 类型参数:#{} vs ${}(差异更明显)

1.#{}的执行(自动加引号,安全)

代码

执行逻辑:生成预编译 SQL

  • 参数(如name="zhangsan")传入时,MyBatis 会自动添加单引号,最终执行的 SQL 等价于:

语法合法,且安全。

2.${}的执行(需手动加引号,否则报错)

未加引号的错误情况

代码:

拼接后 SQL:

数据库会把zhangsan当作字段名(而非字符串值),导致 “Unknown column 'zhangsan'” 语法错误。

手动加引号的正确(但仍有风险)情况

代码(补充单引号):

拼接后 SQL:

语法合法,但仍存在 SQL 注入风险(比如参数传入zhangsan' or '1'='1,会拼接出username = 'zhangsan' or '1'='1',查询全表)。

核心总结:#{}和${}的本质差异

维度#{}${}
参数处理方式预编译占位符(?),自动适配类型(加引号)字符串直接拼接,需手动处理类型(如String 加引号
安全特性防 SQL 注入易被 SQL 注入
语法兼容性自动适配所有参数类型需手动处理类型,否则报错
推荐场景所有普通参数传递仅动态表名 / 字段名(需严格校验参数)

2.2#{}和${}区别

区别就是预编译SQL和即时SQL的区别.

1.SQL 执行流程:即时 SQL vs 预编译 SQL

1.1 即时 SQL(对应${})的执行流程

当客户端发送 SQL 到服务器,需经历 3 个完整步骤:

  1. 语法 / 语义解析:校验 SQL 语句是否合法;
  2. SQL 优化:数据库生成最优执行计划;
  3. 执行并返回结果。每次执行都要重复上述流程,效率较低
1.2 预编译 SQL(对应#{})的执行流程

预编译 SQL 会将SQL 结构(如select * from userinfo where id=?先编译一次,编译后的结果会被缓存;后续执行时,仅需传入参数(替换?),跳过 “解析、优化” 步骤,直接执行,效率更高。

2.#{}的核心优势 1:性能更高

实际业务中,同一条 SQL(仅参数不同)会被反复执行(比如多次根据不同id查询用户):

  • 若用${}(即时 SQL):每次都要重新解析、优化,性能损耗大;
  • 若用#{}(预编译 SQL):仅首次编译,后续复用缓存,大幅提升效率。

3.#{}的核心优势 2:防止 SQL 注入

3.1.SQL 注入的定义

通过构造恶意参数,修改原有 SQL 的逻辑,达到非法操作数据库的目的(比如越权查询、删除数据)。

3.2${}引发 SQL 注入的案例

以 “根据用户名查询” 为例:

代码(用${}

正常参数:传入"admin",拼接后 SQL 为:

仅查询admin的信息,符合预期。

恶意参数:传入"' or 1=1'",拼接后 SQL 为:

1=1是恒成立的条件,最终会查询全表用户信息,造成数据泄露。

3.3#{}避免 SQL 注入的原理

#{}会将参数作为 “值” 传入预编译 SQL 的?占位符,即使传入恶意参数(如"' or 1=1'"),也会被当作普通字符串值处理,最终执行的 SQL 等价于:

数据库会去查询username等于' or 1=1的用户(实际不存在),不会修改 SQL 逻辑,从而避免注入。

4.SQL 注入的风险场景拓展

若用${}处理登录场景的用户名 / 密码:

代码:

恶意参数:密码传入"' or 1=1'",拼接后 SQL 为:

条件恒成立,无需正确密码即可登录成功,造成账号被盗。

核心结论
特性#{}${}
字符串参数处理自动加单引号,无需手动加无自动加引号,String 类型需手动加单引号
SQL 注入防护注入语句被包裹在单引号中,成普通字符串注入语句直接拼接,修改 SQL 逻辑
典型坑点手动加引号会导致''注入内容'',查不到值忘加引号会报 “未知字段”,加了仍有注入风险
  1. #{}:啥都不用加,MyBatis 帮你搞定类型 + 引号,安全又省心;
  2. ${}:String 类型手动加单引号,但仅用于动态表名 / 字段名,且必须校验参数;
  3. 避坑:#{}别加引号,${}非必要不用。
补充 2 个易踩坑细节
1. 手动给#{}加引号的反例

传入zhangsan时,#{name}自动加单引号变成'zhangsan',再拼接手动引号,最终 SQL:

结果:数据库会找username等于''zhangsan''(带双单引号)的用户,实际不存在,返回空。

2. 数字类型也可能被注入

数字类型用${}仍有注入风险:

传入恶意参数1 or 1=1(注意:实际传参是字符串形式的数字表达式),拼接后 SQL:

结果:查询全表数据,数字类型也能被注入(只是 String 类型注入场景更多)。

3.#{}${}排序场景Like 查询场景中的适用

一、排序场景:必须用${},不能用#{}

(1)场景需求

实现 “按 id 升序 / 降序排序”,排序规则(asc/desc)作为参数传入。

(2)#{}的问题

代码(错误示例):

执行时,#{sort}会将 String 类型的sort参数自动加单引号,生成 SQL:

错误原因:SQL 中排序规则(asc/desc)是关键字,不能加单引号,因此会报语法错误。

(3)${}的正确用法

代码(正确示例):

执行时,${sort}直接拼接参数,生成 SQL:

  • 注意:需对sort参数做白名单校验(仅允许asc/desc),避免注入风险。

二、Like 查询场景:用#{}+concat()解决安全问题

(1)直接用#{}的问题

代码(错误示例):

执行时,#{key}自动加单引号,生成 SQL:

  • 错误原因:单引号嵌套导致语法错误。
(2)直接用${}的风险

代码(有注入风险):

  • 虽然能生成正确 SQL(like '%zhangsan%'),但${key}拼接恶意参数(如zhangsan' or 1=1 --),导致 SQL 注入。
(3) 安全解决方案:#{}+concat()函数

利用MySQL 的concat()函数拼接模糊查询的通配符,同时保留#{}的安全性:代码(正确示例):

执行时,#{key}会被替换为?concat()自动拼接通配符,生成预编译 SQL:

  • 既避免了语法错误,又防止了 SQL 注入是 Like 查询的推荐写法

三、总结:${}的合法使用场景+ 安全规范

适用场景原因安全规范
动态排序规则(asc/desc排序关键字不能加单引号对参数做白名单校验
动态表名 / 字段名表名 / 字段名是 SQL 结构的一部分对参数做白名单校验
Like 查询(禁止用${}存在注入风险#{}+concat()替代

这些场景的核心逻辑是:${}仅用于 “SQL 结构的动态部分”(如关键字、表名),且必须校验参数;数据值的传递一律用#{}

MyBatis初阶至此讲解结束

一、数据库连接池的核心概念

数据库连接池是管理数据库连接的容器,其核心逻辑是:

  • 提前创建一定数量的数据库连接,存入 “连接池” 中;
  • 应用程序需要访问数据库时,直接从池里复用已有的连接,而非重新创建;
  • 用完连接后,将其归还到池里,供其他请求使用。

二、有无连接池的对比

场景无连接池有连接池
连接方式每次请求都新建 / 销毁连接复用池中的已有连接
性能新建 / 销毁连接开销大,性能低避免重复开销,性能高
资源消耗频繁创建连接会占用大量系统资源连接数量可控,资源消耗更稳定

三、连接池的核心优势

  1. 减少网络 / 系统开销:避免了 “频繁创建 / 销毁数据库连接” 的高成本操作;
  2. 资源复用:连接可重复使用,降低资源浪费;
  3. 提升系统性能:连接获取更高效,支持更高的并发请求。

四、常用数据库连接池及 SpringBoot 中的使用

1. 主流连接池
  • C3P0/DBCP:早期常用,但性能和功能不及现代连接池,逐渐被替代;
  • Hikari:SpringBoot 默认连接池,日语意为 “光”,以极致性能为目标,轻量高效;
  • Druid:阿里巴巴开源,功能丰富(自带监控、防 SQL 注入等),是企业级场景的常用选择。
2. SpringBoot 中使用连接池
  • Hikari(默认):无需额外配置,SpringBoot 自动集成,启动日志会显示HikariDataSource
  • Druid(切换方式):需引入对应依赖(根据 SpringBoot 版本选择):

SpringBoot 3.x:

SpringBoot 2.x:

五、MySQL 开发企业规范

1. 表名、字段名命名规则
  • 规范小写字母 + 数字,单词用下划线分隔;禁止大写字母、数字开头、连续下划线。
  • 原因:MySQL 在 Linux 下区分大小写,统一小写可避免环境兼容问题;字段修改成本高,命名需谨慎。
  • 正例:aliyun_adminrdc_config
  • 反例:AliyunAdmin(大写)、level__name(连续下划线)。
2. 表必备字段

所有表需包含 3 个基础字段:

  • id:主键,类型为bigint unsigned,单表时自增(步长 1);
  • create_time:创建时间,类型datetime
  • update_time:更新时间,类型datetime。(字段名可根据同义调整,如gmt_create替代create_time
3. 查询规范:禁止用*查询
  • 风险:增加解析成本、易与 ResultMap 配置不一致、无用字段(如text)增加网络消耗;
  • 要求:明确指定需要查询的字段。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/27 19:58:38

Python积分与求导完全指南

📊 Python积分与求导完全指南 📑 目录 求导基础Python求导实战积分基础Python积分实战概率分布函数详解知识点 1. 求导基础 📐 1.1 知识点引入 想象你正在开车,速度表显示的数字就是你的瞬时速度,这个速度其实就是位…

作者头像 李华
网站建设 2026/2/27 19:53:32

SDUT Java 类和对象

6-7 sdut-oop-6-方形矩阵的运算&#xff08;类和对象&#xff09;class Matrix{int n;int[][] matrix;//带参构造方法public Matrix(int n, int[][] matrix) {this.n n;this.matrix matrix;}public Matrix add(Matrix other){int [][ ]resultnew int [n][n];for(int i0;i<…

作者头像 李华
网站建设 2026/2/27 15:50:50

LobeChatUGC内容激励方案

LobeChat UGC内容激励方案 在AI助手从实验室走向千家万户的今天&#xff0c;一个关键问题摆在开发者面前&#xff1a;如何让开源项目不只是“能用”&#xff0c;而是真正“被广泛使用”&#xff1f;答案或许不在于功能堆砌&#xff0c;而在于构建一种用户愿意参与、乐于贡献的内…

作者头像 李华
网站建设 2026/2/22 8:48:11

LobeChat会员等级晋升通知

LobeChat&#xff1a;从容器化部署到智能对话架构的深度实践 在 AI 技术加速落地的今天&#xff0c;大语言模型&#xff08;LLM&#xff09;早已不再是实验室里的概念。越来越多企业开始尝试将 GPT、Claude、Ollama 等强大模型集成进实际业务中——无论是客服系统、知识助手&am…

作者头像 李华
网站建设 2026/2/27 20:02:29

收藏!2025 AI Agent爆发元年,大模型高薪赛道入门全攻略

一句指令触发手机40余款应用自动完成点餐、订票、购物全流程&#xff0c;工厂里人形机器人精准抓取物料替代熟练工劳作&#xff0c;金融AI智能体自主处理业务并优化客户体验——如今&#xff0c;智能体&#xff08;AI Agent&#xff09;正以“对话即执行、虚拟融实体”的姿态&a…

作者头像 李华