当前位置: 首页 > 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.…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

docker 部署发现spring.profiles.active 问题

报错&#xff1a; org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...