【MyBatis学习】占位符,sql注入问题,like模糊匹配等可能出现一定的问题,赶快与我一同去了解,避免入坑吧 ! ! !

news2024/12/25 10:29:37

前言:
大家好,我是良辰丫,今天还是我们的mybatis的学习,主要内容有两个占位符,sql注入问题,like模糊匹配,以及多表查询等,不断提升我们的编程能力,加油哈! ! !💌💌💌

🧑个人主页:良辰针不戳
📖所属专栏:javaEE进阶篇之框架学习
🍎励志语句:生活也许会让我们遍体鳞伤,但最终这些伤口会成为我们一辈子的财富。
💦期待大家三连,关注,点赞,收藏。
💌作者能力有限,可能也会出错,欢迎大家指正。
💞愿与君为伴,共探Java汪洋大海。

在这里插入图片描述

目录

  • 1. 参数占位符 #{} 和 ${}
  • 2. $符号处理关键字
  • 3. sql注入问题
  • 4. like模糊匹配
    • 4.1 like与%连接通过#号预处理
    • 4.2 like与%连接通过$符号处理
    • 4.3 使用sql的拼接函数concat处理like
  • 5. sql字段与java后端字段不统一
    • 5.1 使用resultMap映射
    • 5.2 通过mysql的as别名
  • 7. 多表联查

1. 参数占位符 #{} 和 ${}

  • #{}:预编译处理。
  • ${}:字符直接替换。
  • 预编译处理:MyBatis 在处理#{}时,会将 SQL 中的 #{} 替换为?号,使⽤ PreparedStatement
    的 set ⽅法来赋值。
  • 直接替换:是MyBatis 在处理 ${} 时,就是把 ${} 替换成变量的值。
  • 整型直接使用#和$都可以正常使用,但是字符串就会出现问题,那么接下来我们就使用字符串进行举例.

创建一个接口字段 :

    Stu getStuName(@Param("name") String name);

xml配置,通过#号处理字段

    <select id="getStuName" resultType="com.example.demo.entity.Stu">
        select * from stu where name = #{name}
    </select>

测试单元

    @Test
    void getStuName() {
        Stu stu = stuMapper.getStuName("李白");
        Assertions.assertEquals(10,stu.getId());
    }

测试通过

在这里插入图片描述

接下来使用$号

    <select id="getStuName" resultType="com.example.demo.entity.Stu">
        select * from stu where name = ${name}
    </select>

这个时候就会出现问题了,字符串是直接替换没有加引号.

在这里插入图片描述
我们如果想要去使用$去处理字符串也可以,我们只需要再xml里面的字段加上引号即可.

2. $符号处理关键字

使用$可以处理关键字,比如我们sql的升序降序关键字,因为$符号是直接替换,重要的事情要多次说,这样方便大家记忆.

创建接口字段

    List<Stu> getStuAll(String str);

xml配置文件

    <select id="getStuAll" resultType="com.example.demo.entity.Stu">
        select * from stu order by id ${str};
    </select>

测试单元

    @Test
    void getStuAll() {
        List<Stu> list = stuMapper.getStuAll("desc");
    }

在这里插入图片描述

如果我们传关键字的时候使用#号就会报错.

在这里插入图片描述
在这里插入图片描述

3. sql注入问题

  • 接下来我们来模拟一个登录操作,来简单描述一下我们的注入问题
  • 我们首先需要把stu表中只留下一个数据,否则属性注入会出现问题.

在这里插入图片描述

定义接口信息

    Stu login(@Param("id") Integer id,@Param("name") String name);

xml配置

    <select id="login" resultType="com.example.demo.entity.Stu">
	select * from stu where id = #{id} and name = #{name}
    </select>
  • #是不会出现属性注入的.
  • 我们主要看$符号
    $符号在处理字符串的时候需要给它加引号,sql里面单引号和双引号都可以.

xml信息

    <select id="login" resultType="com.example.demo.entity.Stu">
	select * from stu where id = ${id} and name = '${name}'
    </select>

测试单元

 @Test
    void login() {
        int id = 5;
        String name = "候六";
        //String name = "' or 1='1";
        Stu stu = stuMapper.login(id,name);
        if(stu != null){
            System.out.println("登录成功");
        }else {
            System.out.println("登录失败");
        }
    }

在这里插入图片描述

如果我们把name属性的key值写成下面的呢?这样就会出现属性注入问题.

    @Test
    void login() {
        int id = 5;
        String name = "' or 1='1";
        Stu stu = stuMapper.login(id,name);
        if(stu != null){
            System.out.println("登录成功");
        }else {
            System.out.println("登录失败");
        }
    }

我们会惊奇的发现这样也能查到数据库信息.

在这里插入图片描述

在这里插入图片描述

为什么会出现上面的问题呢?

  • $符号是直接替换,并没有通过预处理,因此$符号会把传入的参数当成sql语句.
  • 此时参数与原来的sql语句进行拼接.

上面出现了sql注入,如果我们换成了#号呢?

    <select id="login" resultType="com.example.demo.entity.Stu">
        select * from stu where id = #{id} and name = #{name}
<!--        select * from stu where id = ${id} and name = '${name}'-->
    </select>

测试单元

    @Test
    void login() {
        int id = 5;
        //String name = "候六";
        String name = "' or 1='1";
        Stu stu = stuMapper.login(id,name);
        if(stu != null){
            System.out.println("登录成功");
        }else {
            System.out.println("登录失败");
        }
    }

在这里插入图片描述

为什么#号不会出现sql注入,因为#号是预处理,它只会把那个句子当成一个value值,不会当成sql语句

4. like模糊匹配

like模式匹配会出问题?

  • like与%直接连接通过#号预处理会失败.
  • like与%直接连接通过$符号不会编译错误,但是可能出现sql注入.

4.1 like与%连接通过#号预处理

    List<Stu> getStuSel(String str);
    <select id="getStuSel" resultType="com.example.demo.entity.Stu">
        select * from stu where name like '#{str}%'
    </select>
    @Test
    void getStuSel() {
        String str = "李";
        stuMapper.getStuSel(str);
    }

我们惊奇的发现此时使用#号出错了,与%联合使用并没有真正的做到拼接作用.

在这里插入图片描述

4.2 like与%连接通过$符号处理

如果我们把#号改成$号,会测试成功嘛?

在这里插入图片描述

此时竟然测试成功.

在这里插入图片描述

  • 虽然$符号测试成功,但是我们在上面了解到$会有sql注入的问题,那么接下来我们就要使用sql中的拼接函数concat实现我们相应的功能.
  • 这样就能保证我们既使用#号,又可以成功查询

4.3 使用sql的拼接函数concat处理like

    <select id="getStuSel" resultType="com.example.demo.entity.Stu">
<!--        select * from stu where name like '${str}%'-->
        select * from stu where name like concat(#{str},'%')
    </select>

在这里插入图片描述

5. sql字段与java后端字段不统一

如果我们java后端属性和sql的字段名字不统一的时候会出现什么问题呢?我们首先另外创一个表.

 create table stu2(id int primary key auto_increment,
 username varchar(20),
 age int);

注意我们这个表是username属性,但是在我们java中是name属性

然后添加一条数据.

insert into stu2 values(null,'张三',20);

在这里插入图片描述

添加接口属性

    Stu getStuId2(@Param("id") Integer id);

添加xml配置

    <select id="getStuId2" resultType="com.example.demo.entity.Stu">
        select * from stu2 where id=${id}
    </select>

测试单元

    @Test
    void getStuId2() {
        Stu stu = stuMapper.getStuId2(1);
        System.out.println(stu);
    }

运行单元测试代码,此时我们发现后端获取到的name属性为null.

在这里插入图片描述

5.1 使用resultMap映射

这个时候我们需要使用resultMap映射,把数据库的属性和java的属性一一映射.

添加接口方法.

    Stu getStuId2(@Param("id") Integer id);

映射字段.

    <resultMap id="Map" type="com.example.demo.entity.Stu">
        <id column="id" property="id"></id>
        <result column="username" property="name"></result>
        <result column="age" property="age"></result>
    </resultMap>
  • id表示主键.
  • column表示数据库的字段名.
  • id = "Map"中的Map是标识.
  • type后面添加的是要映射的实体类.
  • property是程序中的属性名
  • result普通的字段和属性,也就resultMap里的一个标签.

xml配置

    <select id="getStuId2" resultMap="Map">
        select * from stu2 where id=${id}
    </select>

在这里插入图片描述

5.2 通过mysql的as别名

  • resultMap映射中只映射name,在单表查询中没有问题,但是在多表查询有一定的问题.
  • resultMap的方式比较复杂,有没有简单的方式呢?
    mysql里面的as别名
        <select id="getStuId2" resultType="com.example.demo.entity.Stu">
            select id,username as name,age from stu2 where id=${id}
        </select>

在这里插入图片描述

7. 多表联查

接下来我们创建一个学生信息表

create table stuInfo(
    stuId int not null,
    classInfo varchar(100),
    ident varchar(20)
);

在entity创建一个学生信息实体类StuInfo

package com.example.demo.entity;

import lombok.Data;

@Data
public class StuInfo {
    private int stuId;
    private String classInfo;
    private String ident;
}

在entity包下面建一个包vo,vo里面创一个类StuInfoVO

package com.example.demo.entity.vo;

import com.example.demo.entity.StuInfo;
import lombok.Data;

@Data
public class StuInfoVO extends StuInfo {
    //不想写基础字段,可以去继承
    private String username;
}

在mapper包里面创一个StuInfoMapper接口

package com.example.demo.mapper;

import com.example.demo.entity.vo.StuInfoVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface StuInfoMapper {
    StuInfoVO getById(@Param("id") Integer id);
}

在资源文件的mybatis中添加一个配置文件StuInfoMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace是命名空间,表示实现哪个接口-->
<mapper namespace="com.example.demo.mapper.StuInfoMapper">
    <select id="getById" resultType="com.example.demo.entity.vo.StuInfoVO">
        select id,name,classInfo,ident from stu,stuInfo where stu.id = stuInfo.stuId
        and stu.id = #{id}
    </select>
</mapper>
insert into stuInfo values(13,'计算机2020','学生会主席');
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace是命名空间,表示实现哪个接口-->
<mapper namespace="com.example.demo.mapper.StuInfoMapper">
</mapper>

整体的目录结构.

在这里插入图片描述

接下来我们实现一个简单的联合查询

创建接口字段

    StuInfoVO getById(@Param("id") Integer id);

xml文件配置

    <select id="getById" resultType="com.example.demo.entity.vo.StuInfoVO">
        select id,name,classInfo,ident from stu,stuInfo where stu.id = stuInfo.stuId
        and stu.id = #{id}
    </select>

测试单元

package com.example.demo.mapper;

import com.example.demo.entity.vo.StuInfoVO;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class StuInfoMapperTest {
    @Autowired
    private StuInfoMapper stuInfoMapper;


    @Test
    void getById() {
        StuInfoVO stuInfoVO = stuInfoMapper.getById(13);
        System.out.println(stuInfoVO);
    }
}

在这里插入图片描述

通过继承的方式后端获取不到信息.

在这里插入图片描述

那么,接下来我们不使用继承

package com.example.demo.entity.vo;

import com.example.demo.entity.StuInfo;
import lombok.Data;

@Data
public class StuInfoVO{
    //不想写基础字段,可以去继承
    private String username;
    private int stuId;
    private String classInfo;
    private String ident;
}

这样后端就能成功获取到我们的sql字段.

在这里插入图片描述

在多表联查中我们可以使用数据库里面的语句.

  • left join.
  • inner join.

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

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

相关文章

MP地面站下载和回放日志

参考 https://ardupilot.org/dev/docs/common-downloading-and-analyzing-data-logs-in-mission-planner.html#common-downloading-and-analyzing-data-logs-in-mission-planner 下载日志 首先连接上飞控 然后在下图页面下载日志&#xff1a; 点击下图下载日志 下载的日志会…

在CentOS 7上安装Python 3.9

前言 这是我在这个网站整理的笔记&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;RodmaChen 在CentOS 7上安装Python 3.9 一. 更新系统软件包二. 安装必要的软件包和依赖项三. 下载Python 3.9四. 解压和编译源代码五. 安装Python 3.9六. 验证安装 一. 更…

SpringCloud Alibaba-Seata分布式事务

SpringCloud Alibaba-Seata 1 常用事务解决方案模型1.1 DTP模型1.2 2PC1.3 3PC1.4 TCC 2 Seata2.1 Seata术语2.1 Seata AT模式2.1.1 AT模式及工作流程2.1.2 Seata-Server安装2.1.3 集成springcloud-alibaba 4.2 Seata TCC模式 3 Seata注册中心3.1 服务端注册中心配置3.2 客户端…

全国主要城市建筑轮廓(含层高)矢量数据分享及最新AI提取建筑分布方法介绍

今天要给大家带来的数据就是全国主要大中型城市的城市建筑轮廓矢量数据&#xff01;&#xff01;同时给大家一个傻瓜式的建筑物提取软件&#xff0c;以及其使用方法&#xff01;&#xff01; 第一部分&#xff1a;数据 一、数据基本情况 建筑轮廓数据实际上就是建筑的边界矢量…

easyX绘图设备相关函数(注释版)

0.前言 这里是limou3434的easyX博文系列&#xff0c;感兴趣可以看看我的其他内容。 本次我给您带来的是easyX的绘图设备相关函数&#xff0c;和上一篇一样&#xff0c;对于官方文档我给了一些自认为重要的注释和测试例子&#xff0c;来辅助您理解这些函数。 1.easyX库函数分…

【汤4操作系统】深入掌握操作系统-文件管理篇

第六章 文件管理 文件 数据项&记录&文件 数据项分为&#xff1a; 基本数据项&#xff1a;描述对象的某些属性&#xff0c;例如学生的年龄&#xff0c;姓名学号等组合数据项&#xff1a;由若干个基本数据项组合而成 记录&#xff1a;一组相关数据项的集合&#xff0…

光线追踪中的空间划分,辐射度量学简介

之前接触过四岔树&#xff0c;这里用到了KD-tree和BSP-Tree KD-Tree 对于如何划分&#xff1a; 首先需要知道需要沿着哪一条轴进行划分&#xff0c;划分的位置所有节点不存在父节点上&#xff0c;只存在于叶节点上 对于如何查找 光线穿过包围盒A&#xff0c;那么分别对其两…

4.4 超简单文书编辑器:nano

在Linux系统当中有非常多的文书编辑器存在&#xff0c;其中最重要的是vim。 nano使用很简单&#xff0c;可以直接加上文件名就能够打开一个旧文件或新文件。打开一个叫text.txt的文件名来看看&#xff1a; [ctrl]-G&#xff1a;取得线上说明&#xff08;help&#xff09;&…

Python案例——采集专栏文章保存成pdf

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 环境使用: python 3.8 >>>>>> 运行代码 pycharm 2022.3 >>>>>> 辅助敲代码 wkhtmltopdf 软件 找助理邀课老师获取 模块使用: 内置模块 re >>>正则表达式 第三方模…

es6 的模块化由来

es 模块化&#xff0c;之前是没有的。没有的时候&#xff0c;用的是社区创建的commjs模块化 commjs模块其实是一个对象&#xff0c;这个对象要在代码运行的时候才会创建出来的 这有个不好的地方&#xff0c;就是不能在编译的时候找到依赖文件&#xff0c;也不能进行类型检查&…

一文搞定C++异常机制(附代码+详细解析)

C异常 1.引文C语言传统的处理错误的方式&#xff1a; 2.C异常概念3.异常的使用3.1 异常的抛出和捕获3.2 异常的重新抛出异常捕获中的内存泄漏问题 3.3异常安全3.4异常规范 4.异常优缺点5.总结&#xff1a; 1.引文 C语言传统的处理错误的方式&#xff1a; 终止程序&#xff0c…

【GAI】红杉美国生成式AI:一个创造性的新世界

The New Language Model Stack 红杉美国官网发表了最新一篇题为《Generative AI: A Creative New World》的文章译稿&#xff0c;&#xff0c;原文作者是红杉的两位合伙人&#xff1a;Sonya Huang和Pat Grady&#xff0c;有意思的是在文章作者一栏&#xff0c;赫然还写着GPT-3…

华为OD机试真题 JavaScript 实现【磁盘容量排序】【2022Q4 100分】,附详细解题思路

一、题目描述 磁盘的容量单位常用的有M&#xff0c;G&#xff0c;T这三个等级&#xff0c;它们之间的换算关系为1T 1024G&#xff0c;1G 1024M&#xff0c;现在给定n块磁盘的容量&#xff0c; 请对它们按从小到大的顺序进行稳定排序&#xff0c;例如给定5块盘的容量&#x…

宠物电商社区APP的设计与实现

摘 要&#xff1a;为了设计并实现具有宠物产品商城和问答社区功能的APP&#xff0c;通过比较国内外宠物行业电商发展现状和国内已有的宠物电商平台的优缺点&#xff0c;分析可行性和需求&#xff0c;从而进行详细设计和实现。该APP后台采用SSM框架&#xff0c;数据库使用MySQL…

最终版:1分钟自动部署数字人平台并提供web服务:唇形合成(wav2lip) + 超分修复(codeformer),

Demo效果 本文实现步骤:数字人形象(AI绘画) -> 文字转语音(谷歌tts) -> 表情迁移 -> 唇形合成 -> 视频超分 上述步骤所有技术均已在此专栏发布,可点击上方专栏查看具体博文 所有技术依赖环境及api接口均封装打包完毕,使用docker一键部署,预计耗时10分钟 原图 …

tolua源码分析(八)lua扩展继承C#类

tolua源码分析&#xff08;八&#xff09;lua扩展继承C#类 上一节我们阐述了lua调用带out参数的C#函数机制&#xff0c;本节我们来看下lua层是如何扩展C#类的。这次的例子在example 17&#xff0c;主要都是lua代码&#xff1a; LuaTransform { } …

1.pixi.js编写的塔防游戏(类似保卫萝卜)-设计逻辑

游戏说明 一个用pixi.js编写的h5塔防游戏&#xff0c;可以用electron打包为exe&#xff0c;支持移动端&#xff0c;也可以用webview控件打包为app在移动端使用 环境说明 cnpm6.2.0 npm6.14.13 node12.22.7 npminstall3.28.0 yarn1.22.10 npm config list electron_mirr…

1.2 聚合工程与springboot整合

步骤1&#xff1a; 在顶级父工程中添加springboot相关的pom配置 <!--springboot父级依赖&#xff0c;表示是一个是springboot项目 --> <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifa…

vue3(基于vite)项目初始基本配置

简介 一个好的项目开始搭建总是需要配置许多初始化配置&#xff0c;比如eslint语法检验、prettier代码格式统一、husky做commit拦截等等&#xff0c;本文从零开始带你一步步搭建一个完整的项目配置&#xff0c;熟悉之后下次直接拿来即用 环境准备 node v16以上pnpm 8.0.0 1.新…

4.3.3 info page

在所有的Unix Like系统当中&#xff0c;都可以利用 man 来查询指令或者是相关文件的用法&#xff1b; 但是&#xff0c;在Linux里面则又额外提供了一种线上求助的方法&#xff0c;那就是利用info。 基本上&#xff0c;info与man的用途其实差不多&#xff0c;都是用来查询指令的…