在MyBatis中$和#有什么区别

在 MyBatis 中,${}#{} 是两种处理 SQL 参数的占位符,它们在实现机制、安全性、使用场景上存在显著差异。以下是详细对比:

核心区别对比

特性#{}${}
底层机制预编译占位符(PreparedStatement字符串直接替换
安全性✅ 防止 SQL 注入❌ 存在 SQL 注入风险
参数处理自动添加引号(字符串/日期类型)需手动添加引号(否则语法错误)
性能较低(预编译开销)较高(直接拼接 SQL)
适用场景动态参数值(如 WHERE id = ?动态 SQL 片段(如表名、排序字段)

机制详解

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

    • MyBatis 会将其解析为 JDBC 的?占位符,通过PreparedStatement预编译 SQL。

    • 参数值会被安全转义,例如:

      SELECT * FROM users WHERE name = #{name}  -- 转换为:SELECT * FROM users WHERE name = ?

      若name = "John",实际执行时参数值会被安全绑定为'John'。

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

    • 直接替换为参数值的字面量,无预编译或转义。

    • 例如:

      SELECT * FROM users WHERE id = ${id}  -- 若 id=1,替换为:SELECT * FROM users WHERE id = 1

      若id = "1 OR 1=1",则 SQL 会变为:

      SELECT * FROM users WHERE id = 1 OR 1=1  -- 查询所有数据,存在 SQL 注入风险[1,5](@ref)

安全性问题

  • #{}:天然防 SQL 注入,适用于用户输入或外部参数。

  • ${}:高风险!仅适用于完全可控的静态值(如内部生成的表名、列名)。

    错误示例(模糊查询):

    SELECT * FROM products WHERE name LIKE '%${keyword}%' -- 若 keyword="' OR 1=1 --",导致数据泄露!

使用场景对比

#{} 的适用场景
  • 普通条件查询(值动态传递):

    SELECT * FROM orders WHERE user_id = #{userId} [1,4](@ref)
  • 日期/字符串参数(自动添加引号):

    INSERT INTO logs (content) VALUES (#{logContent})  -- 自动转为 'xxx' [7,8](@ref)
  • 模糊查询(安全写法):

    SELECT * FROM products WHERE name LIKE CONCAT('%', #{keyword}, '%') [2,3](@ref)
⚠️ ${} 的适用场景
  • 动态表名/列名(SQL 片段不可预编译):

    SELECT * FROM ${tableName} WHERE ${column} = 1 [3,5,7](@ref)
  • 排序字段(如ORDER BY ${sortField}):

    SELECT * FROM users ORDER BY ${orderBy} DESC [3,7](@ref)
  • 批量操作(如IN子句):

    DELETE FROM cart WHERE id IN (${ids})  -- ids="1,2,3" [7](@ref)

最佳实践与避坑指南

  1. 默认使用 #{}:除非必须动态拼接 SQL 片段,否则一律用#{}确保安全。

  2. ${} 的防御措施:

    • 仅允许传入白名单值(如预定义表名列表)。

    • 手动过滤危险字符(如空格、分号)。

  3. 模糊查询的替代方案:

    • 用CONCAT函数(推荐):

      SELECT * FROM table WHERE name LIKE CONCAT('%', #{text}, '%')
    • 程序层拼接(Java 中生成"%text%"再传入)。


💎 总结

  • #{} = 安全优先:处理动态值(用户输入、条件参数),预编译防注入

  • ${} = 谨慎使用:处理动态 SQL 片段(表名、排序),需严格校验输入

关键口诀:**“值用井号(#),结构用刀($)”——值动态用 #{},SQL 结构动态用 ${}。实际开发中,95% 的场景应使用#{},仅在必要时(如分表)谨慎使用${}。

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

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

相关文章

湖北理元理律师事务所债务优化方案:平衡还款与生活的法律实践

在个人债务问题日益突出的当下,如何科学规划还款路径成为社会性难题。湖北理元理律师事务所基于多年实务经验,提出“可持续债务优化”模型,其核心在于通过法律工具实现三重平衡: 债权债务的法律平衡:严格依据《民法典…

使用 Isaac Sim 模拟机器人

前言 将 2D 激光雷达数据从 Isaac Sim 流式传输至 ROS 2,并通过 RViz 进行可视化。通过激光雷达数据监控机器人与环境的交互,从而在仿真环境中提升机器人的感知能力。 概览 欢迎来到 入门指南:在 Isaac Sim 中模拟您的第一个机器人 课程。我…

quartz 表达式最近10次执行时间接口编写

Nuget安装 <PackageReference Include"CronExpressionDescriptor" Version"2.41.0" /> <PackageReference Include"CronExpressionDescriptor-zh-CN" Version"2.32.0" /> <PackageReference Include"Quartz"…

解锁数据宝藏:数据挖掘之数据预处理全解析

目录 一、引言&#xff1a;数据预处理 —— 数据挖掘的基石二、数据预处理的重要性2.1 现实数据的问题剖析2.2 数据预处理的关键作用 三、数据预处理的核心方法3.1 数据清洗3.1.1 缺失值处理3.1.2 离群点处理3.1.3 噪声处理 3.2 数据集成3.2.1 实体识别3.2.2 冗余处理3.2.3 数据…

React+Taro创建小程序

第一步&#xff1a;首先确认是否安装Node.js和npm 如果已安装Node.js和npm,以下可以查询 node -v npm -v 第二步&#xff1a;安装Taro CLI npm install -g tarojs/cli 第三步&#xff1a;创建项目 taro init my-react-taro-app 然后可以看到&#xff0c;下图 第四步&…

佳能Canon TS3100 Series打印机信息

打印功能 打印速度&#xff1a;黑白约 7.7 页 / 分钟&#xff0c;彩色约 4 页 / 分钟。打印分辨率&#xff1a;最高可达 48001200dpi&#xff0c;墨滴最小间距为 1/4800 英寸&#xff0c;能够保证高质量的输出&#xff0c;使文字清晰、色彩鲜艳。打印宽度&#xff1a;203.2 毫米…

家用电脑搭建可外网访问的网站服务器操作流程

在互联网时代&#xff0c;拥有一个属于自己的网站是展示个人风采、分享知识经验、开展线上业务的绝佳方式。你是否想过&#xff0c;利用家中闲置的电脑&#xff0c;就能搭建出一个可以被外网访问的网站服务器&#xff1f;这不仅能满足个性化需求&#xff0c;还能节省租用专业服…

CSS知识补充 --- 控制继承

每天学习一点点&#xff01;&#xff01;&#xff01; 总所周知&#xff0c;CSS某些属性可以继承&#xff0c;然后今天看到MDN的时候看到了CSS也可以控制继承&#xff0c;感觉很有意思&#xff0c;所以记录一下&#xff1a; 控制继承有5个属性值&#xff0c;分别&#xff1a;in…

如何使用Ant Design Blazor组件在列表页弹窗增加修改数据

在winform中首次使用net8做页面。列表页想使用Ant Design组件的弹窗组件实现。但第一次在winform项目中使用ant design组件&#xff0c;列表页面&#xff0c;点击新增&#xff0c;或者编辑操作实现弹窗页面&#xff0c;弹窗页面想使用模板页razor页来实现&#xff0c;而不是用m…

嵌入式学习 51单片机01

一、框架 1、CPU&#xff08;Central Processing Unit&#xff0c;中央处理单元&#xff09;‌是计算机的核心部件&#xff0c;负责执行计算机指令和处理数据。 2、MCU&#xff08;Microcontroller Unit&#xff0c;微控制单元&#xff09;‌是一种将中央处理器、内存、输入输出…

C语言之内存对齐

一、为什么要内存对齐 Arm对内存的访问支持字&#xff08;4byte&#xff09;、半字&#xff08;2byte&#xff09;、字节&#xff08;1byte&#xff09;的直接访问&#xff0c;但是呢他们是有一定的要求的&#xff1a; 存取字时要求地址按字对齐&#xff0c;也就是地址要是4的…

Python 基础语法 -----函数

一、函数 1、函数是什么 编程中的函数和数学中的函数有一定的相似之处。 数学上的函数&#xff0c;比如 y sin x&#xff0c;x 取不同的值&#xff0c;y 就会得到不同的结果。 编程中的函数是一段可以被重复使用的代码片段。 &#xff08;1&#xff09;求数列的和&#x…

Windows/Linux系统 Ollama部署deepseek 大模型

Ollama 是一个开源工具&#xff0c;专门用于在本地计算机上运行和操作大型语言模型&#xff08;LLM&#xff09; 官方下载网站&#xff08;https://ollama.ai/&#xff09; Windows系统安装方法 建议命令行安装&#xff08;默认安装会直接安装到C盘&#xff09; OllamaSetu…

用Tensorflow进行线性回归和逻辑回归(一)

这一章告诉你如何用TensorFlow构建简单的机器学习系统。第一部分回顾构建机器学习系统的基础特别是讲函数&#xff0c;连续性&#xff0c;可微性。接着我们介绍损失函数&#xff0c;然后讨论机器学习归根于找到复杂的损失函数最小化的点的能力。我们然后讲梯度下降&#xff0c;…

java/.net跨平台UI浏览器SDK,浏览器控件开发包分析

在 Linux 系统中&#xff0c;虽然没有完全等同于安卓 WebView 的内置浏览器 SDK&#xff0c;但存在多种基于开源浏览器引擎的解决方案&#xff0c;支持通过 Java 代码控制网页加载和执行 JavaScript。以下是具体实现方案和技术细节&#xff1a; 一、核心技术方案对比 方案名称…

Taro 状态管理全面指南:从本地状态到全局方案

在跨端应用开发中&#xff0c;状态管理是构建可维护、可扩展应用的核心环节。作为京东凹凸实验室推出的多端统一开发框架&#xff0c;Taro 支持 React/Vue 等主流前端框架&#xff0c;自然也继承了丰富的状态管理生态。本文将全面剖析 Taro 中的各种状态管理方案&#xff0c;从…

记录一下jar做成windows服务问题

1、打包好jar 2、把jdk防止到和jar同一目录下 3、下载winsw-x64.exe 和 sample-minimal.xml https://github.com/winsw/winsw/releases/download/v2.12.0/WinSW-x64.exehttps://github.com/winsw/winsw/releases/download/v2.12.0/WinSW-x64.exe sample-minimal.xmlhttps://…

【Dify 案例】【MCP实战】【二】【超级助理】

我们创建一个工作流。你是一个超级助理,能够根据输入的指令,进行推理和自主调用工具,完成并输出结果。 注意,需要判断是否调用高德MCP来获取对应工具协助你完成任务。 1.开始 2.策略大脑 2.1 AEGNT策略 2.2 工具列表 2.3 指令

Qt Quick 与 QML(二)qml中的顶级窗口

一、前言 在QML中&#xff0c;‌顶级窗口不是绝对必需的‌&#xff0c;但它在大多数应用场景中扮演着关键角色。 需要顶级窗口的典型场景&#xff1a; 1.独立桌面/移动应用‌ 必须使用Window或ApplicationWindow作为根元素。 2.多窗口应用 每个独立窗口都需要一个顶级窗口实例…

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 免费服务开通全流程与Rest API和OpenAI SDK调用详解

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 免费服务开通全流程与Rest API和OpenAI SDK调用详解 前言 本文将详细介绍DeepSeek-V3/R1 免费服务开通全流程&#xff0c;并且详细讲解通过本地方式Rest API和OpenAI SDK两种方式调用DeepSeek-V3/R1 前提准备 1、访问 Mod…