MySQL 中 `${}` 和 `#{}` 占位符详解及面试高频考点

news2025/4/19 3:15:40

文章目录

    • 一、概述
    • 二、`#{}` 和 `${}` 的核心区别
      • 1. 底层机制
        • 代码示例
      • 2. 核心区别总结
    • 三、为什么表名只能用 `${}`?
      • 1. 预编译机制的限制
      • 2. 动态表名的实现
    • 四、安全性注意事项
      • 1. `${}` 的风险场景
      • 2. 安全实践
    • 五、面试高频考点
      • 1. 基础原理类问题
        • **问题 1**:
        • **问题 2**:
      • 2. 安全与设计类问题
        • **问题 3**:
        • **问题 4**:
      • 3. 扩展实战类问题
        • **问题 5**:
    • 六、总结与最佳实践
      • 1. 使用场景对比
      • 2. 最佳实践
    • 七、附录:MyBatis 预编译原理图示

一、概述

在 MySQL 和 MyBatis 等框架中,${}#{} 是动态 SQL 中常用的占位符。它们的核心差异在于 预编译机制安全性,正确使用二者是后端开发的基本功,也是面试中的高频考点。本文将从原理、场景、安全性及面试题四方面深入解析。


二、#{}${} 的核心区别

1. 底层机制

占位符预编译替换方式安全性
#{}参数化绑定 (?)
${}字符串直接拼接
代码示例
-- #{}
SELECT * FROM users WHERE name = #{name};
-- 预编译后:SELECT * FROM users WHERE name = ?;

-- ${}
SELECT * FROM ${table} WHERE id = 1;
-- 替换后:SELECT * FROM users_2023 WHERE id = 1;

2. 核心区别总结

  • #{}
    用于替换 值类型(如 WHERE 条件值、INSERT 字段值),通过 PreparedStatement 预编译,防止 SQL 注入。
  • ${}
    用于替换 标识符(如表名、列名、ORDER BY 子句),直接拼接字符串,需手动校验安全性。

三、为什么表名只能用 ${}

1. 预编译机制的限制

  • 数据库协议限制:预编译占位符 ? 仅支持替换值类型(字符串、数字等),不能替换表名、列名等标识符。
  • 语法合法性:以下写法直接报错:
    -- 错误!表名无法预编译
    SELECT * FROM ? WHERE id = 1;
    

2. 动态表名的实现

若需根据业务逻辑动态切换表(如分表场景),只能通过字符串拼接:

<!-- MyBatis 示例 -->
<select id="selectLogs" resultType="Log">
  SELECT * FROM logs_${month}
</select>

四、安全性注意事项

1. ${} 的风险场景

// 恶意输入导致 SQL 注入
String userInput = "users; DROP TABLE users; --";
String sql = "SELECT * FROM " + userInput; 
// 执行结果:SELECT * FROM users; DROP TABLE users; --

2. 安全实践

  1. 禁止用户控制表名:表名应在代码层生成(如根据时间分表),而非直接传递用户输入。
  2. 白名单校验:若必须动态传参,需校验参数格式(如正则匹配 ^[a-zA-Z0-9_]+$)。
  3. SQL 审计:拦截非常规表名操作(如 information_schema)。

五、面试高频考点

1. 基础原理类问题

问题 1

“MyBatis 中 #{}${} 的底层实现有什么区别?”

  • #{} 使用 PreparedStatement 预编译,参数替换为 ?,防止 SQL 注入。
  • ${} 直接拼接字符串,无预编译,需手动处理安全性。

场景
面试官考察候选人对 MyBatis 执行过程的理解,是否清楚预编译机制。


问题 2

“为什么表名必须用 ${}?能否用 #{}?”

数据库协议规定预编译占位符 ? 只能替换值类型,不能替换表名、列名等标识符。若强行使用 #{},最终生成的 SQL 会因语法错误无法执行。

场景
面试中常见于考察 SQL 预编译机制的底层知识。


2. 安全与设计类问题

问题 3

“如何安全地使用 ${} 动态指定表名?”

  • 代码层控制:表名由系统生成(如 user_2023),而非用户传入。
  • 白名单校验:若需外部传入,校验参数是否符合命名规范(如正则匹配)。
  • 日志监控:记录所有动态表名操作,便于审计。

场景
考察安全意识和实际工程经验,常见于金融、数据安全相关岗位。


问题 4

“除了表名,还有哪些场景必须用 ${}?”

  • 动态列名:SELECT ${column} FROM table
  • 排序字段:ORDER BY ${sortField}
  • 动态 SQL 片段:<if test="condition">${sqlSegment}</if>

场景
面试官可能延伸考察动态 SQL 的灵活应用能力。


3. 扩展实战类问题

问题 5

“如果必须让用户传入表名,如何设计安全方案?”

  1. 前端传递表名编码(如 1=users, 2=products),后端映射为真实表名。
  2. 参数加密:用户传入加密参数,后端解密后匹配预定义表名。
  3. 数据库权限隔离:动态表操作使用只读低权限账号。

场景
高级岗位考察系统设计能力,尤其是安全与灵活性平衡的方案。


六、总结与最佳实践

1. 使用场景对比

场景占位符示例
WHERE 条件值#{}WHERE id = #{id}
动态表名/列名${}SELECT * FROM ${table}
排序字段${}ORDER BY ${sort}

2. 最佳实践

  • 默认使用 #{}:除非必须使用 ${}
  • 最小化 ${} 暴露:禁止用户传入未经验证的参数。
  • 日志 + 监控:记录所有动态 SQL 操作,及时预警异常行为。

七、附录:MyBatis 预编译原理图示

MyBatis 执行流程:
1. 解析 XML SQL → 2. 替换 `#{}` 为 `?` → 3. 预编译 SQL → 4. 绑定参数值 → 5. 执行

文档说明:本文适用于初中级后端开发者巩固知识点,以及资深开发者面试复习。建议结合 MyBatis 源码和 MySQL 协议文档深入理解。

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

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

相关文章

AI应用开发平台 和 通用自动化工作流工具 的详细对比,涵盖定义、核心功能、典型工具、适用场景及优缺点分析

以下是 AI应用开发平台 和 通用自动化工作流工具 的详细对比&#xff0c;涵盖定义、核心功能、典型工具、适用场景及优缺点分析&#xff1a; 1. AI应用开发平台 vs 通用自动化工作流工具 (1) 定义与目标 类型AI应用开发平台通用自动化工作流工具定义用于快速构建、训练、部署…

智慧社区数据可视化中枢平台——Axure全场景交互式大屏解决方案

在数字化治理的时代浪潮中&#xff0c;社区管理正面临数据碎片化、响应滞后、决策盲区等核心挑战。如何将分散的安防、环境、能源、民生服务等数据整合为可操作的智慧洞察&#xff1f;如何让冰冷的数字转化为社区管理者手中的决策利器&#xff1f;Axure智慧社区可视化大屏原型模…

Axure高保真AI算法训练平台

点击下载《Axure高保真AI算法训练平台(.rp) 》 原型效果&#xff1a;https://axhub.im/ax9/69fdf8f2b10b59c3/#g1 摘要 本文介绍了一款功能全面且高效的AI算法训练平台&#xff0c;旨在为数据科学家、研究人员和工程师提供从数据准备到模型部署的一站式解决方案。该平台由四大…

C++ Json-Rpc框架-3项目实现(2)

一.消息分发Dispatcher实现 Dispatcher 就是“消息分发中枢”&#xff1a;根据消息类型 MType&#xff0c;把消息派发给对应的处理函数&#xff08;Handler&#xff09;执行。 初版&#xff1a; #pragma once #include "net.hpp" #include "message.hpp"n…

OpenAI发布GPT-4.1系列模型——开发者可免费使用

OpenAI刚刚推出GPT-4.1模型家族&#xff0c;包含GPT-4.1、GPT-4.1 Mini和GPT-4.1 Nano三款模型。重点是——现在全部免费开放&#xff01; 虽然技术升级值得关注&#xff0c;但真正具有变革意义的是开发者能通过Cursor、Windsurf和GitHub Copilot等平台立即免费调用这些模型。…

各地物价和生活成本 东欧篇

东欧地区的物价差异相对较大&#xff0c;一些国家的物价较高&#xff0c;而另一些国家则相对便宜。这些差异主要受当地经济发展水平、工资水平、旅游业发展以及国际关系等因素影响。以下是一些典型的东欧国家&#xff0c;按物价高低进行分类&#xff1a; &#x1f30d; 物价较高…

flex布局(笔记)

弹性布局&#xff08;Flex布局&#xff09;是一种现代的CSS布局方式&#xff0c;通过使用display: flex属性来创建一个弹性容器&#xff0c;并在其中使用灵活的盒子模型来进行元素的排列和定位。 主轴与交叉轴&#xff1a;弹性容器具有主轴&#xff08;main axis&#xff09;和…

云函数采集架构:Serverless模式下的动态IP与冷启动优化

在 Serverless 架构中使用云函数进行网页数据采集&#xff0c;不仅能大幅降低运维成本&#xff0c;还能根据任务负载动态扩展。然而&#xff0c;由于云函数的无状态特性及冷启动问题&#xff0c;加上目标网站对采集行为的反制措施&#xff08;如 IP 限制、Cookie 校验等&#x…

Linux笔记---动静态库(原理篇)

1. ELF文件格式 动静态库文件的构成是什么样的呢&#xff1f;或者说二者的内容是什么&#xff1f; 实际上&#xff0c;可执行文件&#xff0c;目标文件&#xff0c;静态库文件&#xff0c;动态库文件都是使用ELF文件格式进行组织的。 ELF&#xff08;Executable and Linkable…

string的模拟实现 (6)

目录 1.string.h 2.string.cpp 3.test.cpp 4.一些注意点 本篇博客就学习下如何模拟实现简易版的string类&#xff0c;学好string类后面学习其他容器也会更轻松些。 代码实现如下&#xff1a; 1.string.h #define _CRT_SECURE_NO_WARNINGS 1 #pragma once #include <…

【野火模型】利用深度神经网络替代 ELMv1 野火参数化:机制、实现与性能评估

目录 一、ELMv1 野火过程表示法&#xff08;BASE-Fire&#xff09;关键机制野火模拟的核心过程 二、采用神经网络模拟野火过程三、总结参考 一、ELMv1 野火过程表示法&#xff08;BASE-Fire&#xff09; ELMv1 中的野火模型&#xff08;称为 BASE-Fire&#xff09;源自 Commun…

红宝书第四十七讲:Node.js服务器框架解析:Express vs Koa 完全指南

红宝书第四十七讲&#xff1a;Node.js服务器框架解析&#xff1a;Express vs Koa 完全指南 资料取自《JavaScript高级程序设计&#xff08;第5版&#xff09;》。 查看总目录&#xff1a;红宝书学习大纲 一、框架定位&#xff1a;HTTP服务器的工具箱 共同功能&#xff1a; 快…

嵌入式Linux设备使用Go语言快速构建Web服务,实现设备参数配置管理方案探究

本文探讨&#xff0c;利用Go语言及gin框架在嵌入式Linux设备上高效搭建Web服务器&#xff0c;以实现设备参数的网页配置。通过gin框架&#xff0c;我们可以在几分钟内创建一个功能完善的管理界面&#xff0c;方便对诸如集中器&#xff0c;集线器等没有界面的嵌入式设备的管理。…

【NLP 59、大模型应用 —— 字节对编码 bpe 算法】

目录 一、词表的构造问题 二、bpe(byte pair encoding) 压缩算法 算法步骤 示例&#xff1a; 步骤 1&#xff1a;初始化符号表和频率统计 步骤 2&#xff1a;统计相邻符号对的频率 步骤 3&#xff1a;合并最高频的符号对 步骤 4&#xff1a;重复合并直至终止条件 三、bpe在NLP中…

Python对ppt进行文本替换、插入图片、生成表格

目录 1. 安装pptx2. 文本替换和插入图片3. 生成表格 1. 安装pptx pip install python-pptx2. 文本替换和插入图片 文本通过占位符例如{{$xxx}}进行标记&#xff0c;然后进行替换&#xff1b;图片通过ppt中的图形和图片中的占位符进行标记ppt如下 具体实现 from pptx import …

AI(学习笔记第一课) 在vscode中配置continue

文章目录 AI(学习笔记第一课) 在vscode中配置continue学习内容&#xff1a;1. 使用背景2. 在vscode中配置continue2.1 vscode版本2.2 在vscode中下载continue插件2.2.1 直接进行安装2.2.2 在左下角就会有continue的按钮2.2.3 可以移动到右上角2.2.3 使用的时候需要login 2.3 配…

C++ (初始面向对象之继承,实现继承,组合,修饰权限)

初始面向对象之继承 根据面向对象的编程思路&#xff0c;我们可以把共性抽象出来封装成类&#xff0c;然后让不同的角色去继承这些类&#xff0c;从而避免大量重复代码的编写 实现继承 继承机制是面向对象程序设计中使代码可以复用的最重要的手段&#xff0c;它允许程序员在保…

每日搜索--12月

12.1 1. urlencode是一种编码方式,用于将字符串以URL编码的形式进行转换。 urlencode也称为百分号编码(Percent-encoding),是特定上下文的统一资源定位符(URL)的编码机制。它适用于统一资源标识符(URI)的编码,也用于为application/x-www-form-urlencoded MIME准备数…

一天一个java知识点----Tomcat与Servlet

认识BS架构 静态资源&#xff1a;服务器上存储的不会改变的数据&#xff0c;通常不会根据用户的请求而变化。比如&#xff1a;HTML、CSS、JS、图片、视频等(负责页面展示) 动态资源&#xff1a;服务器端根据用户请求和其他数据动态生成的&#xff0c;内容可能会在每次请求时都…

游戏报错?MFC140.dll怎么安装才能解决问题?提供多种MFC140.dll丢失修复方案

MFC140.dll 是 Microsoft Visual C 2015 运行库的重要组成部分&#xff0c;许多软件和游戏依赖它才能正常运行。如果你的电脑提示 "MFC140.dll 丢失" 或 "MFC140.dll 未找到"&#xff0c;说明系统缺少该文件&#xff0c;导致程序无法启动。本文将详细介绍 …