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

MyBatis增删改查:静态与动态SQL语句拼接及SQL注入问题解析

MyBatis 是一个优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的工作。本文将深入探讨 MyBatis 中的增删改查操作,重点讲解静态与动态 SQL 语句的拼接,并分析 SQL 注入问题及其防范措施。

1. MyBatis 基础配置

在开始之前,我们需要配置 MyBatis 的基本环境。以下是一个简单的 pom.xml 配置文件,包含了 MyBatis 的核心依赖和 MySQL 驱动依赖:

<dependencies><!-- MyBatis 核心包 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.5</version></dependency><!-- MySQL 驱动包 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.6</version></dependency><!-- 单元测试 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.10</version></dependency><!-- 日志 --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency>
</dependencies>

2. 静态 SQL 语句

静态 SQL 语句是指在编写 SQL 时,SQL 语句的结构和内容是固定的,不会根据条件的变化而变化。以下是一个简单的静态 SQL 查询示例:

<!--id:方法名--><!--resultType:定义数据的返回-->
<!--    <select id="findAll" resultType="com.qcby.entity.User">-->
<!--        select *from user;-->
<!--    </select>--><!--    <select id="findById" resultType="com.qcby.entity.User" parameterType="java.lang.Integer">-->
<!--        select * from user where id=#{id}-->
<!--    </select>--><!--    <select id="selectByUserName" resultType="com.qcby.entity.User" parameterType="java.lang.String">-->
<!--        select *from user where username=#{username}-->
<!--    </select>--><!--    <insert id="insert" parameterType="com.qcby.entity.User">-->
<!--        insert into user (username,birthday,sex,address) value (#{username},#{birthday},#{sex},#{address});-->
<!--    </insert>--><!--    <update id="update" parameterType="com.qcby.entity.User">-->
<!--        update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}-->
<!--            where id=#{id}-->
<!--    </update>--><!--    <delete id="delete" parameterType="java.lang.Integer">-->
<!--        delete from user where id=#{id}-->
<!--    </delete>-->
<!--    <select id="likeByName" resultType="com.qcby.entity.User" parameterType="java.lang.String">-->
<!--        select * from user where username like '%${value}%';-->
<!--    </select>-->
<!--    <select id="likeByName1" resultType="com.qcby.entity.User" parameterType="java.lang.String">-->
<!--        select * from user where username like #{username};-->
<!--    </select>-->

在这个例子中,findAll 方法会返回 user 表中的所有记录。静态 SQL 语句适用于简单的查询场景,但在复杂的业务逻辑中,静态 SQL 往往无法满足需求。

3. 动态 SQL 语句

动态 SQL 是 MyBatis 的强大特性之一,它允许我们根据不同的条件动态生成 SQL 语句。MyBatis 提供了多种标签来实现动态 SQL,如 <if><choose><when><otherwise><trim><where><set> 和 <foreach>

3.1 <if> 标签

<if> 标签用于根据条件判断是否包含某段 SQL 语句。以下是一个使用 <if> 标签的动态 SQL 示例:

 <!--动态sql:能够在不同的条件下拼接出不同的sql语句--><!--where 标签的功能:能够去掉where 后边的 and 或 or--><select id="selectUser" parameterType="com.qcby.entity.User" resultType="com.qcby.entity.User">select * from user<where><if test="username!=null and username!=''">username=#{username}</if><if test="birthday!=null">and birthday=#{birthday}</if><if test="sex!=null and sex!=''">and sex=#{sex}</if><if test="address!=null and address!=''">and address=#{address}</if></where></select>

在这个例子中,selectUser 方法会根据传入的 User 对象的 username 和 sex 属性动态生成 SQL 语句。如果 username 或 sex 为空,则不会包含对应的条件。

3.2 <choose><when> 和 <otherwise> 标签

<choose> 标签类似于 Java 中的 switch 语句,它可以根据不同的条件选择不同的 SQL 片段。以下是一个使用 <choose> 标签的示例:

<select id="selectUserByChoose" resultType="com.qcby.entity.User" parameterType="com.qcby.entity.User">SELECT * FROM user<where><choose><when test="username != null and username != ''">username = #{username}</when><when test="sex != null and sex != ''">sex = #{sex}</when><otherwise>id = #{id}</otherwise></choose></where>
</select>

在这个例子中,selectUserByChoose 方法会根据 usernamesex 和 id 的不同值动态生成 SQL 语句。

3.3 <foreach> 标签

<foreach> 标签用于遍历集合或数组,并生成相应的 SQL 语句。以下是一个使用 <foreach> 标签的批量删除示例:

<!--foreach循环--><!--批量删除--><!-- 批量删除的sql语句:delete from user where id in (6,7,8);   --><delete id="deleteMoreByArray" >delete from user where id in<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach></delete><!-- collection:当前要循环的数组或者集合   --><!--  item: 我们指定要循环的数组的每一个元素  --><!-- separator:每一个元素应该用什么来做分割   --><!-- open:当前循环是以什么开始   --><!-- close:当前循环是以什么结束   --><!--批量添加--><!--insert into user(username,birthday,sex,address) values (#{user.username},#{user.birthday},#{user.sex},#{user.address}), (#{user.username},#{user.birthday},#{user.sex},#{user.address}), (#{user.username},#{user.birthday},#{user.sex},#{user.address}), (#{user.username},#{user.birthday},#{user.sex},#{user.address})   --><update id="insertMoreByList" parameterType="com.qcby.entity.User">insert into user(username,birthday,sex,address) values<foreach collection="users" item="user" separator=",">(#{user.username},#{user.birthday},#{user.sex},#{user.address})</foreach></update>

在这个例子中,deleteMoreByArray 方法会根据传入的 ids 数组动态生成批量删除的 SQL 语句。

4. SQL 注入问题及防范

SQL 注入是一种常见的安全漏洞,攻击者可以通过在输入中插入恶意 SQL 代码来操纵数据库查询。MyBatis 通过使用 #{} 占位符来防止 SQL 注入。

4.1 #{} 与 ${} 的区别

  • #{}:MyBatis 会使用预编译语句(PreparedStatement)来处理参数,参数会被安全地转义,从而防止 SQL 注入。

  • ${}:MyBatis 会直接将参数拼接到 SQL 语句中,存在 SQL 注入的风险。

以下是一个使用 #{} 的示例:

<select id="findById" resultType="com.qcby.entity.User" parameterType="java.lang.Integer">SELECT * FROM user WHERE id = #{id}
</select>

在这个例子中,#{} 会确保 id 参数被安全地处理,防止 SQL 注入。

4.2 防范 SQL 注入的最佳实践

  • 始终使用 #{}:在大多数情况下,应使用 #{} 来处理参数,避免使用 ${}

  • 避免动态拼接 SQL:尽量避免在 SQL 语句中动态拼接用户输入的内容。

  • 使用 MyBatis 的动态 SQL 标签:通过使用 <if><choose> 等标签,可以安全地构建动态 SQL 语句。

5. 总结

MyBatis 提供了强大的动态 SQL 功能,使得我们可以根据不同的条件灵活地生成 SQL 语句。同时,MyBatis 通过 #{} 占位符有效地防止了 SQL 注入问题。在实际开发中,我们应充分利用 MyBatis 的动态 SQL 特性,并遵循最佳实践来确保应用的安全性。

通过本文,你应该对 MyBatis 的增删改查操作、动态 SQL 语句拼接以及 SQL 注入问题有了更深入的理解。希望这些内容能帮助你在实际项目中更好地使用 MyBatis。

 

 


参考文献:

  • MyBatis 官方文档

  • SQL 注入攻击与防御

相关文章:

MyBatis增删改查:静态与动态SQL语句拼接及SQL注入问题解析

MyBatis 是一个优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的工作。本文将深入探讨 MyBatis 中的增删改查操作&#xff0c;重点讲解静态与动态 SQL 语句的拼接&#xff0c;并分析 S…...

在运维工作中,Lvs、nginx、haproxy工作原理分别是什么?

在运维工作中&#xff0c;LVS、NGINX和HAProxy都是常用的负载均衡和反向代理工具&#xff0c;它们在高可用性和负载均衡场景中发挥重要作用。以下是其原理和应用场景详解&#xff1a; LVS&#xff08;Linux Virtual Server&#xff09; 工作原理 LVS是基于Linux内核的负载均…...

linux学习(五)(服务器审查,正常运行时间负载,身份验证日志,正在运行的服务,评估可用内存)

服务器审查 在 Linux 中审查服务器的过程包括评估服务器的性能、安全性和配置&#xff0c;以确定需要改进的领域或任何潜在问题。审查的范围可以包括检查安全增强功能、检查日志文件、审查用户帐户、分析服务器的网络配置以及检查其软件版本。 Linux 以其稳定性和安全性而闻名…...

Java在小米SU7 Ultra汽车中的技术赋能

目录 一、智能驾驶“大脑”与实时数据 场景一&#xff1a;海量数据的分布式计算 场景二&#xff1a;实时决策的毫秒级响应 场景三&#xff1a;弹性扩展与容错机制 技术隐喻&#xff1a; 二、车载信息系统&#xff08;IVI&#xff09;的交互 场景一&#xff1a;Android Automo…...

开发环境搭建-02.后端环境搭建-熟悉项目结构

一.后端环境搭建...

js实现pdf文件路径预览和下载

预览 直接浏览器窗口打开默认就是预览 window.open(文件路径)下载 function downloadPDF(url, filename) {fetch(url).then(response > response.blob()).then(blob > {const link document.createElement(a);link.href URL.createObjectURL(blob);link.download fi…...

【RAG】基于向量检索的 RAG (BGE示例)

RAG机器人 结构体 文本向量化: 使用 BGE 模型将文档和查询编码为向量。 &#xff08;BGE 是专为检索任务优化的开源 Embedding 模型&#xff0c;除了本文API调用&#xff0c;也可以通过Hugging Face 本地部署BGE 开源模型&#xff09; 向量检索: 从数据库中找到与查询相关的文…...

Vue源码解析之mustache模板引擎

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…...

python: DDD using postgeSQL and SQL Server

postgreSQL 注意&#xff1a; # psycopg 2 驱动的连接字符串 #engine create_engine(postgresql://post:geovindulocalhost:5433/TechnologyGame) #Session sessionmaker(bindengine)# 使用 psycopg3 驱动的连接字符串 #engine create_engine(postgresqlpsycopg://user:g…...

Python实例:PyMuPDF实现PDF翻译,英文翻译为中文,并按段落创建中文PDF

基于PyMuPDF与百度翻译的PDF翻译处理系统开发:中文乱码解决方案与自动化排版实践 一 、功能预览:将英文翻译为中文后创建的PDF 二、完整代码 from reportlab.lib.pagesizes import letter from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle...

IntelliJ IDEA 2021版创建springboot项目的五种方式

第一种方式&#xff0c;通过https://start.spring.io作为spring Initializr的url来创建项目。 第二种方式&#xff0c;通过https://start.spring.io官网来直接创建springboot项目压缩包&#xff0c;然后导入至我们的idea中。 点击generate后&#xff0c;即可生成压缩包&#xf…...

c#面试题整理6

1.String类能否被继承&#xff0c;为什么 可以看到String类的修饰符是sealed&#xff0c;即是密封类&#xff0c;故不可被继承 2.一个对象的方法是否只能由一个线程访问 不是&#xff0c;但是可通过同步机制&#xff0c;确保同一个时间只有一个线程访问 3.计算2*8&#xff…...

跟着 Lua 5.1 官方参考文档学习 Lua (12)

文章目录 5.7 – Input and Output Facilities补充内容io.input ([file])io.read ()io.write ()io.output ([file])io.lines ([filename])io.flush ()io.close ([file])io.open (filename [, mode])io.popen (prog [, mode])io.tmpfile ()io.type (ob)file:read ()file:lines (…...

大语言模型中的归一化技术:LayerNorm与RMSNorm的深入研究

在LLama等大规模Transformer架构的语言模型中&#xff0c;归一化模块是构建网络稳定性的关键组件。本文将系统分析归一化技术的必要性&#xff0c;并详细阐述为何原始Transformer架构中的LayerNorm在LLama模型中被RMSNorm所替代的技术原理。 归一化技术的基础原理 归一化的核…...

nodejs使用WebSocket实现聊天效果

在nodejs中使用WebSocket实现聊天效果&#xff08;简易实现&#xff09; 安装 npm i ws 实现 创建 server.js /*** 创建一个 WebSocket 服务器&#xff0c;监听指定端口&#xff0c;并处理客户端连接和消息。** param {Object} WebSocket - 引入的 WebSocket 模块&#xff0c…...

【仿muduo库one thread one loop式并发服务器实现】

文章目录 一、项目介绍1-1、项目总体简介1-2、项目开发环境1-3、项目核心技术1-4、项目开发流程1-5、项目如何使用 二、框架设计2-1、功能模块划分2-1-1、SERVER模块2-1-2、协议模块 2-2、项目蓝图2-2-1、整体图2-2-2、模块关系图2-2-2-1、Connection 模块关系图2-2-2-2、Accep…...

10.2 继承与多态

文章目录 继承多态 继承 继承的作用是代码复用。派生类自动获得基类的除私有成员外的一切。基类描述一般特性&#xff0c;派生类提供更丰富的属性和行为。在构造派生类时&#xff0c;其基类构造函数先被调用&#xff0c;然后是派生类构造函数。在析构时顺序刚好相反。 // 基类…...

Go红队开发—格式导出

文章目录 输出功能CSV输出CSV 转 结构体结构体 转 CSV端口扫描结果使用CSV格式导出 HTML输出Sqlite输出nmap扫描 JSONmap转json结构体转jsonjson写入文件json编解码json转结构体json转mapjson转string练习&#xff1a;nmap扫描结果导出json格式 输出功能 在我们使用安全工具的…...

线性代数之矩阵特征值与特征向量的数值求解方法

文章目录 前言1. 幂迭代法&#xff08;Power Iteration&#xff09;幂法与反幂法求解矩阵特征值幂法求最大特征值编程实现补充说明 2. 逆幂迭代法&#xff08;Inverse Iteration&#xff09;移位反幂法 3. QR 算法&#xff08;QR Algorithm&#xff09;——稠密矩阵理论推导编程…...

Spring MVC源码分析のinit流程

文章目录 前言一、 init1.1、createWebApplicationContext1.2、onRefresh 二、请求处理器2.1、RequestMapping2.2、Controller接口2.3、HttpRequestHandler接口2.4、HandlerFunction 三、initHandlerMappings3.1、getDefaultStrategies3.1.1、RequestMappingHandlerMapping3.1.…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...