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

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 注入攻击与防御


http://www.kler.cn/a/578792.html

相关文章:

  • golang dlv调试工具
  • 如何监控 Pod 的 CPU/内存使用率,prometheus+grafana
  • ②Modbus TCP转Modbus RTU/ASCII网关同步采集无需编程高速轻松组网
  • VSCode+AI编程生态实战:从环境配置到智能编码的全栈指南
  • 软考 中级软件设计师 考点知识点笔记总结 day02
  • Vite 打包后Nginx部署配置
  • QOJ9700 Ying’s Cup(拉格朗日插值优化卷积,背包,二项式反演)
  • 驱动开发系列46 - Linux 显卡KMD驱动代码分析(七)- 显存管理
  • VS Code连接服务器教程
  • 泛型、泛型上限、泛型下限、泛型通配符
  • Codeforces Round 566 (Div. 2) E. Product Oriented Recurrence 矩阵加速、欧拉降幂
  • 自然语言模型NLP :tensorflow搭建情感分析模型
  • 企业数据挖掘平台×DeepSeek强强联合,多种应用场景适用
  • 实现静态网络爬虫(入门篇)
  • 数据结构--【栈与队列】笔记
  • 计算机视觉算法实战——犯罪行为检测(主页有源码)
  • C++复试笔记(一)
  • PreTrainedModel 类代码分析:_load_pretrained_model
  • 基于Django创建一个WEB后端框架(DjangoRestFramework+MySQL)流程
  • 异常与日志简易版本