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

MyBatis的#和$符号详解(Java面试)

🤟致敬读者

  • 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉

📘博主相关

  • 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息

文章目录

  • Java面试中MyBatis的#和$符号详解
      • 1. **`#{}`(预编译占位符)**
      • 2. **`${}`(字符串直接替换)**
      • ⚠️ 关键对比总结
      • 🛡️ 使用建议
      • 🔍 面试回答要点


📃文章前言

  • 🔷文章均为学习工作中整理的笔记。
  • 🔶如有错误请指正,共同学习进步。

Java面试中MyBatis的#和$符号详解

在Java的MyBatis框架中,#{}${}是处理SQL参数的两种关键符号,它们在底层实现、安全性和使用场景上有显著区别:

1. #{}(预编译占位符)

  • 实现原理
    转换为JDBC的PreparedStatement参数占位符?,执行时通过setXxx()方法安全传参。
    SELECT * FROM user WHERE id = #{userId}
    → 实际执行:SELECT * FROM user WHERE id = ?   (参数值安全注入)
    
  • 安全性
    天然防止SQL注入(参数值不会作为SQL片段解析)。
  • 数据类型处理
    自动处理类型转换(如字符串添加引号、日期格式化)。
  • 适用场景
    所有数据值场景(WHERE条件值、INSERT/UPDATE值等)。

2. ${}(字符串直接替换)

  • 实现原理
    直接替换为参数值的字符串(不做预编译处理)。
    SELECT * FROM ${tableName} ORDER BY ${column}
    → 可能生成:SELECT * FROM orders ORDER BY create_time
    
  • 安全性
    有SQL注入风险(若参数值来自用户输入且未过滤)。
    ORDER BY ${input}   // 若input="1; DROP TABLE user--" 会导致灾难!
    
  • 数据类型处理
    需手动处理类型(如字符串需自行添加引号)。
  • 适用场景
    动态SQL关键字/结构(表名、列名、ORDER BY子句等无法预编译的位置)。

⚠️ 关键对比总结

特性#{}${}
底层机制预编译占位符 (?)字符串直接替换
SQL注入风险✅ 安全❌ 高风险(需严格校验参数)
处理数据类型自动添加引号/格式转换需手动处理(如字符串加' '
性能通常更优(数据库可缓存执行计划)每次生成新SQL
适用场景数据值(用户输入、条件值等)SQL结构(表名、列名、动态SQL片段)

🛡️ 使用建议

  1. 默认首选 #{}
    只要涉及数据值(特别是用户输入),强制使用#{}确保安全。

    <!-- 安全示例 -->
    <select id="findUser">SELECT * FROM user WHERE name = #{name} AND age > #{minAge} <!-- 正确做法 -->
    </select>
    
  2. 谨慎使用 ${}
    仅用于动态标识符(非数据),且必须做参数校验:

    <!-- 动态表名示例(需校验tableName合法性) -->
    <select id="selectFromTable">SELECT * FROM ${tableName} WHERE role = #{role}  <!-- 值仍用#{} -->
    </select>
    
  3. 禁止将用户输入直接用于 ${}
    若不可避免(如动态排序字段),应在代码层白名单校验

    // Java层校验示例
    public String safeOrderColumn(String input) {Set<String> validColumns = Set.of("name", "age", "create_time");return validColumns.contains(input) ? input : "id"; // 默认安全值
    }
    

🔍 面试回答要点

  • 根本区别
    #{}是参数化查询(安全),${}是字符串拼接(危险)。
  • 安全原则
    “数据值必用#{},动态结构慎用${},用户输入绝不用${}”。
  • 漏洞案例
    ${}未过滤导致"1; DELETE FROM user"会执行恶意SQL。
  • 动态表名解决方案
    ${}但需在业务层校验表名合法性(如映射预定义表名)。

📌 总结:MyBatis中SQL安全的核心在于——所有数据值必须通过#{}传递,仅在必要时(如动态表结构)对${}进行严格受控的使用。


📜文末寄语

  • 🟠关注我,获取更多内容。
  • 🟡技术动态、实战教程、问题解决方案等内容持续更新中。
  • 🟢《全栈知识库》技术交流和分享社区,集结全栈各领域开发者,期待你的加入。
  • 🔵​加入开发者的《专属社群》,分享交流,技术之路不再孤独,一起变强。
  • 🟣点击下方名片获取更多内容🍭🍭🍭👇

http://www.xdnf.cn/news/965071.html

相关文章:

  • 企业产品网络安全日志6月10日-WAF资费消耗排查
  • 【大模型01---Flash Attention】
  • 常见的http状态码
  • MySQL主从复制实现指南
  • AWS Lambda Python + AWS Secrets Manager + AWS Aurora Mysql
  • AI+预测3D新模型百十个定位预测+胆码预测+去和尾2025年6月10日第104弹
  • 深度学习聊天机器人 需要考虑
  • Linux简单的操作
  • 基于算法竞赛的c++编程(29)类的概念和简单应用
  • v-bind 与 v-model 的区别与联系详解
  • python第48天打卡
  • 通过 VS Code 连接 GitLab 并上传项目
  • 第十四届蓝桥杯_省赛B组(C).冶炼金属
  • 【单片机期末】汇编试卷
  • 64页|PPT|基于华为IPD与质量管理体系融合的研发质量管理:L1-L6分层架构驱动高效运营、标准化质量管理体系
  • 【解密LSTM、GRU如何解决传统RNN梯度消失问题】
  • 详解CNN
  • node+express+jwt+sequelize+mysql+本地服务器部署前端+云服务器公网部署:入门教程
  • 线程与进程(java)
  • 解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
  • 数据库——MongoDB
  • 定时器任务——若依源码分析
  • Python包(Package)详解:模块的高级组织方式
  • DeviceNet转Modbus RTU,为纺织厂生产线赋能
  • uniapp的请求封装,如何避免重复提交请求
  • mysql-innoDB存储引擎事务的原理
  • ​​​​​​​未来已来:深度解读 BLE 6.0 的革命性特性与实战应用
  • SkyReels-V1:开启多模态视频生成的新纪元
  • SpringDoc集成到Springboot
  • 第1章信息化知识归纳总结补充内容