您的位置:首页 > 财经 > 金融 > 大学生网站建设实训报告_市场营销方案500字_今日新闻事件_产品推广网站哪个好

大学生网站建设实训报告_市场营销方案500字_今日新闻事件_产品推广网站哪个好

2025/4/19 15:18:15 来源:https://blog.csdn.net/weixin_44435110/article/details/147273089  浏览:    关键词:大学生网站建设实训报告_市场营销方案500字_今日新闻事件_产品推广网站哪个好
大学生网站建设实训报告_市场营销方案500字_今日新闻事件_产品推广网站哪个好

文章目录

    • 一、概述
    • 二、`#{}` 和 `${}` 的核心区别
      • 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 协议文档深入理解。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com