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

news/2025/2/22 5:21:10/

前言:
大家好,我是良辰丫,今天还是我们的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>

测试单元

    @Testvoid 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>

测试单元

    @Testvoid 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>

测试单元

 @Testvoid 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值写成下面的呢?这样就会出现属性注入问题.

    @Testvoid 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>

测试单元

    @Testvoid 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>
    @Testvoid 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>

测试单元

    @Testvoid 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.stuIdand 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.stuIdand 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 {@Autowiredprivate StuInfoMapper stuInfoMapper;@Testvoid 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.ppmy.cn/news/436136.html

相关文章

FPGA基础知识-时序和延迟

目录 学习目标&#xff1a; 学习内容&#xff1a; 1.延迟模型的类型 2.路径延迟建模 3.时序检查 4.延迟反标注 学习时间&#xff1a; 学习总结 学习目标&#xff1a; 提示&#xff1a;这里可以添加学习目标 鉴别Verilog 仿真中用到的延迟模型的类型&#xff0c;分布延…

公司电脑能装监控系统吗?

在许多国家&#xff0c;包括中国在内&#xff0c;公司通常可以合法地在其自有电脑设备上安装监控系统。然而&#xff0c;具体的法规和规定可能因国家和地区而异&#xff0c;所以最好在使用电脑监控系统之前&#xff0c;先了解所在地区的法律要求和规定。在安装监控系统时&#…

游戏怎么这么卡?!--浅谈手游开发性能优化

前言、手游优化为什么这么难&#xff1f;手机性能比pc差很多&#xff0c;而且手机性能参差不齐&#xff0c;低端机占有的比例又比较大&#xff0c;导致很多游戏必须向低端机对齐&#xff0c;很苛刻的优化游戏的性能。并且&#xff0c;手游端的开发环境还有很多缺陷&#xff0c;…

手把手教你将H5游戏打包为手游

H5游戏可以通过快应用的web组件快速打包成快游戏&#xff0c;打包上架后的快游戏&#xff0c;只要原H5游戏的url不发生变动&#xff0c;快游戏就不需要做更新&#xff0c;维护工作量小。 使用快应用IDE&#xff0c;打包快游戏的操作很简单。 访问官网安装开发工具&#xff0c;…

【悬赏贴】C端手游游戏产品任务

【悬赏贴】 任务需求&#xff1a; 1&#xff0c;请根据王者荣耀手游&#xff0c;从社区产品经理的角度提出官方社区优化方案&#xff08;包含游戏内置微社区、双端官网等&#xff09;&#xff0c;并用交互原型、流程图等描述优化思路&#xff1b; 2&#xff0c;基于王者荣耀手游…

Laya-魅族快游戏--错误码

Laya-魅族错误码100135 魅族报错100135 魅族快游戏100135 &#xff08;百度上搜不到自己的文章&#xff0c;加多了一点字&#xff0c;抱歉啊&#xff09; 广告位被冻结了&#xff0c;去联系魅族那边吧&#xff0c;可能需要两个小时才能解冻 Laya-魅族错误码 102006 魅族官方…

Laya-魅族小游戏开发接入

1、找到对应技术文档&#xff0c;最好使用官网的最新版本&#xff0c;在线技术文档 2、安装上图里的魅族调试工具&#xff0c;测试机器必须是魅族手机 3、上图里的打包工具也是必需的 4、使用LayaAir将项目打包发布&#xff0c;选择为web 5、LayaAir打包成web之后&#xff0c…