MyBatis -- 参数占位符 #{} 和 ${}

news2024/11/26 15:52:47

MyBatis -- 参数占位符 #{} 和 ${}

  • 一、准备工作
  • 二、参数占位符 #{} 和 ${}
  • 三、特殊场景
    • 3.1 特殊场景 1 -- String
      • 3.1.1 使用 #{}
      • 3.1.2 使用 ${}
      • 3.1.3 分析与解决
    • 3.2 特殊场景 2 -- MySQL 关键字
    • 3.3 特殊场景 3 -- SQL 注入问题 (重要)
    • 3.4 特殊场景 4 -- 模糊查询 like

一、准备工作

创建数据库和表

-- 创建数据库
drop database if exists mycnblog;
create database mycnblog DEFAULT CHARACTER SET utf8mb4;

-- 使用数据数据
use mycnblog;

-- 创建表[用户表]
drop table if exists  userinfo;
create table userinfo(
    id int primary key auto_increment,
    username varchar(100) not null,
    password varchar(32) not null,
    photo varchar(500) default '',
    createtime datetime default now(),
    updatetime datetime default now(),
    `state` int default 1
) default charset 'utf8mb4';

添加实体类

package com.example.demo.model;

import lombok.Data;

import java.util.Date;

/**
 * 普通的实体类,用于 Mybatis 做数据库表(userinfo表)的映射
 * 注意事项:保证类属性名称和userinfo表的字段完全一致!
 */
@Data
public class UserInfo {
    private int id;
    private String name;
    private String password;
    private String photo;
    private Date createtime;
    private Date updatetime;
    private int state;
}

添加 mapper 接口 (数据持久层)

package com.example.demo.mapper;

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper {
    
}

创建与接口对应的 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">
<mapper namespace="com.example.demo.mapper.UserMapper">

</mapper>

二、参数占位符 #{} 和 ${}

  • #{}:预编译处理。
    预编译处理是指:MyBatis 在处理#{}时,会将 SQL 中的 #{} 替换为?号,使⽤ PreparedStatement 的 set ⽅法来赋值。

  • ${}:字符直接替换。
    直接替换:是MyBatis 在处理 ${} 时,就是把 ${} 替换成变量的值。

预编译处理和字符串替换的区别故事(头等舱和经济舱乘机分离的故事):
乘坐飞机,头等舱和经济舱的区别是很⼤的。

  • ⼀般航空公司乘机都是头等舱和经济舱分离的,头等舱的⼈先登机,登机完之后,封闭经济舱,然后再让经济舱的乘客登机,这样的好处是可以避免浑⽔摸⻥,经济舱的⼈混到头等舱的情况,这就相当于预处理,可以解决程序中不安全(越权处理)的问题。
    在这里插入图片描述
  • ⽽直接替换的情况相当于,头等舱和经济舱不分离的情况,这样经济舱的乘客在通过安检之后可能越权摸到头等舱,如下图所示:
    在这里插入图片描述
    这就相当于参数直接替换,它的问题是可能会带来越权查询和操作数据等问题,⽐如后⾯会讲的 SQL 注⼊问题。

三、特殊场景

3.1 特殊场景 1 – String

3.1.1 使用 #{}

username 唯一。

插入一条数据:

-- 添加一个用户信息
INSERT INTO `mycnblog`.`userinfo` (`id`, `username`, `password`, `photo`, `createtime`, `updatetime`, `state`) VALUES 
(1, 'admin', 'admin', '', '2021-12-06 17:10:48', '2021-12-06 17:10:48', 1);

UserMapper 接口:

    // 根据用户姓名完全匹配查询
    public UserInfo getUserByName(@Param("username") String username);

UserMapper.xml:

    <select id="getUserByName" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where username=#{username}
    </select>

单元测试:

package com.example.demo.mapper;

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

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest // 当前测试的上下文环境为 springboot
class UserMapperTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    void getUserByName() {
        UserInfo userInfo = userMapper.getUserByName("admin");
        System.out.println("userinfo -> " + userInfo);
    }
}

经测试,成功打印了我们插入的数据信息。

3.1.2 使用 ${}

UserMapper.xml:

    <select id="getUserByName" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where username=${username}
    </select>

此时进行单元测试,报错了!:
在这里插入图片描述

3.1.3 分析与解决

  • #{} 预编译处理:识别出来为字符串,就会自动加上引号''
  • ${} 字符直接替换:缺少引号,所以查找不到 username (去查找字段了!)

在其外加一层单引号:'${username}' 即可。

那么无论是 #{} 还是 ${},都加上 '' 不就可以了吗?
理论上是可以的,但是会产生很多隐式类型转换!一旦存在隐式类型转换就不会走索引了,效率会大大降低!!!

3.2 特殊场景 2 – MySQL 关键字

例如排序时:order by xxx asc/desc

在这里插入图片描述

此时传递的虽然也是一个字符串,但是我们并不希望给它加上引号!
所以只能使用 ${} 字符直接替换!

UserMapper 接口:

    // 查询所有的信息(根据排序条件进行排序)
    public List<UserInfo> getAllByOrder(@Param("order") String order);

UserMapper.xml:

    <select id="getAllByOrder" resultType="com.example.demo.model.UserInfo">
        select * from userinfo order by id ${order}
    </select>

但因为 SQL 注入问题,这种场景使用 ${} 时必须在 controller 中验证一下参数 (字符串必须是 asc/desc,否则代码就不要继续往下执行了!)

3.3 特殊场景 3 – SQL 注入问题 (重要)

    <select id="isLogin" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where username='${name}' and password='${pwd}'
    </select>

sql 注入代码:' or 1='1

在这里插入图片描述

${} 字符直接替换,这时就忽略了密码直接登录了!十分危险!!!
因此绝大部分场景都会避免使用 ${}。

3.4 特殊场景 4 – 模糊查询 like

    <select id="findUserByName2" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where username like '%#{username}%';
    </select>

使用 #{} 会报错!
预编译会识别为字符串类型自动加上引号,不符合预期
相当于是:select * from userinfo where username like ‘%‘username’%’;

此时也并不能直接使用 ${}:会有 SQL 注入风险。在 controller 进行检查判断也不可取,因为传来的字符串是有无数种可能的,无法检查判断!

这时可以使用 MySQL 的内置函数 concat() 来处理,实现代码如下:

    <select id="findUserByName3" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where username like concat('%',#{username},'%');
    </select>

这种写法完全没有问题 ~

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

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

相关文章

测试开发 | 想测试入门就必须要懂的软件开发流程

本文节选自霍格沃兹测试学院内部教材 从事软件测试行业&#xff0c;每天面对的被测对象都是软件。如果想要更好的去完成测试工作&#xff0c;首先需要对被测对象&#xff0c;也就是对软件要有基本的了解。 软件 与计算机系统操作有关的计算机程序、可能有的文件、文档及数据。…

多轮对话(二):多轮对话理解的研究进展和主流方法

本文是基于 Advances in Multi-turn Dialogue Comprehension: A Survey。这是一篇综述论文&#xff0c;我也顺便总结一下像我一样的小白&#xff0c;怎么读综述好一些。我读综述是为了快速切入某领域&#xff0c;比如我以前做的是跨模态检索&#xff0c;现在要进入对话系统&…

C++STL-stackqueue的实现

文章目录1. deque的简单介绍1.1 deque的原理介绍1.2 deque的优缺点1.3 为什么选择deque作为底层默认容器2. stack的实现3. queue的实现1. deque的简单介绍 在前面已经介绍过&#xff0c;stack和queue这两个容器适配器&#xff0c;是由deque这个容器封装的。现在我们就需要先学…

易观千帆 | 11月用户体验GX评测:银行APP用户体验稳定提升,从流量竞争逐渐转向用户体验竞争

易观&#xff1a;随着银行行业对用户体验的重视&#xff0c;手机银行APP用户体验稳定提升&#xff0c;竞争也从注重MAU的流量竞争逐渐转移为用户体验竞争。11月易观千帆用户体验GX评测显示&#xff0c;平安口袋银行、中国工商银行、招商银行仍是AAAAA级&#xff0c;在用户体验维…

对于搞钱我们是认真的

前言 大家好&#xff0c;我是xiezhr。一提到搞钱&#xff0c;想必大家都非常非常感兴趣&#xff0c;立马就精神抖擞了。说实话&#xff0c;在这疫情爆发这几年里&#xff0c;赚点钱真不容易。 不知道你是不是也跟我一样&#xff0c;一个人在夜深人静的时候就在想怎么才能通过自…

十三.动态内存管理

目录 一.为什么存在动态内存分配 二.动态内存函数的介绍 1.malloc函数 2.free函数 3.calloc函数 4.reallco函数 三.常见的动态内存错误 1.对NULL空指针的解引用操作 2.对动态开辟空间的越界访问 3.对非动态开辟的内存使用free释放 4.使用free释放一块动态开辟内存的一…

HTML实现除夕最美烟花,2023春节倒计时,新年不可没有烟花,最炫烟花代码分享

&#x1f4cb; 前言 &#x1f5b1; 博客主页&#xff1a;在下马农的碎碎念✍ 本文由在下马农原创&#xff0c;首发于CSDN&#x1f4c6; 首发时间&#xff1a;2023/01/17&#x1f4c5; 最近更新时间&#xff1a;2023/01/17&#x1f935; 此马非凡马&#xff0c;房星本是星。向前…

Android入门第58天-真机调试

开篇 随着我们的Android开始慢慢往后面涉及到设备、网络、通讯内容的开发。我们开始要把真机调试提上日程来了。 比如说&#xff1a;我们用Android扫描barcode、二维码都需要使用到Android的摄像头。而在Android Studio的AVP&#xff08;模拟器&#xff09;里&#xff0c;它的摄…

【树莓派4B】搭建HomeAssistant服务端(二)(systemd配置开机自启动,cpolar内网穿透)

设置开机自启动 创建home-assistanthomeassistant.service服务&#xff1a; sudo nano /etc/systemd/system/home-assistanthomeassistant.service复制以下内容&#xff0c;定义服务&#xff0c;其中After定义先行服务&#xff0c;ExecStart执行启动脚本&#xff1a; [Unit]…

程序跑起来数据总是关闭及丢失?保存进文件里面美滋滋

文章目录前言文件是什么&#xff1f;程序文件数据文件文件名C语言中的文件打开和关闭文件指针文件的打开和关闭fopenfclose文件的顺序读写文件的随机读写fseekftellrewind文件读取结束的判定feof&#xff1a;我们之间可能有误会文件缓冲总结前言 我们或许都有这样的苦恼&#…

【手写 Vue2.x 源码】第二十八篇 - diff算法-问题分析与patch优化

一&#xff0c;前言 首先对 6 月更文内容做一下简单的回顾&#xff1a; Vue2.x 源码环境的搭建Vue2.x 初始化流程介绍对象的单层、深层劫持数组的单层、深层劫持数据代理的实现对象、数组数据变化的观测Vue 数据渲染流程介绍模板生成 AST 语法树AST 语法树生成 render 函数re…

【Java寒假打卡】Java基础-XML文件

【Java寒假打卡】Java基础-XML文件概述标签的规则xml的语法规则解析XMLXML解析的准备工作XML解析文件的代码实现概述 标签的规则 xml的语法规则 <?xml version"1.0" encoding"UTF-8" ?> <!--本xml文件用于描述多个学生信息--> <students&…

教程: nodejs 做微信公众号开发,回复 xml 消息

教程&#xff1a; nodejs 做微信公众号开发&#xff0c;回复 xml 消息 首先需要你的后台跟服务器已经可以建立连接&#xff0c;这个不再冗述看官方教程就好 接入指南 。此篇介绍的是如何获取用户发来的信息&#xff0c;并回复它。 一、接收 xml 信息内容 我用的是 nodejs 的…

Android应用模块化开发指南

Android应用模块化开发指南 包含多个Gradle模块的项目称为多模块项目。本文包含多模块应用项目的最佳实践和推荐模式。 代码规模变大带来的问题 可扩缩性、可读性和整体代码质量会随着时间的推移而降低&#xff0c;代码维护者未采取积极的措施来保持易于维护的结构。模块化是…

【营销】uplift建模方案-专利总结

之前准备写专利的时候浏览了一下其他公司的专利&#xff0c;对于one model&#xff0c;还是two model&#xff0c;基模型是什么做了简单总结。 浦发银行&#xff08;CN 112446541 A&#xff09;——one model&#xff08;标签转换&#xff09; 基模型&#xff1a;NN分类融合m…

经济学学习(宏观)

--------------------------------------- 第8篇&#xff1a;宏观经济学的数据 --------------------------------------- 23. 一国收入的衡量(GDP&#xff0c;通胀) gdp衡量总收入和总支出&#xff0c;总收入总支出 某一既定时期&#xff0c;一个国家内生产的所有最终商品…

【科研试剂】16-Heptadecynoic acid,93813-16-2,16-庚二酸

【中文名称】16-庚二酸【英文名称】 16-Heptadecynoic acid&#xff0c;16-Heptadecynoic COOH【结 构 式】【CAS】93813-16-2【分子式】C17H30O2【分子量】266.43【纯度标准】95%【包装规格】1g&#xff0c;5g&#xff0c;10g【是否接受定制】可进行定制&#xff0c;定制时间周…

Java日志系统介绍和slf4j的使用

目录1. 日志系统介绍2. slf4j的使用2.1 slf4j的入门2.2 slf4j绑定日志框架1. 日志系统介绍 日志门面位于应用程序和日志框架之间&#xff0c;日志门面提供一个抽象的能力&#xff0c;日志框架进行具体的日志实现。可以很方便的更换日志框架。类似JDBC驱动 日志门面有&#xf…

业务逻辑漏洞

1、容易忽略的低危漏洞以及延伸利用 一、容易忽略的低危漏洞以及延伸利用 在挖洞的过程当中&#xff0c;比如我们碰到信息泄露漏洞&#xff0c;但是我们不知道这个是信息泄露&#xff1b;或者说我们碰到一个xss&#xff0c;我们不会利用&#xff0c;只能弹个窗&#xff0c;比如…

AcWing 4510. 寻宝!大冒险!(暴力枚举)

题目如下&#xff1a; 输入样例1&#xff1a; 5 100 2 0 0 1 1 2 2 3 3 4 4 0 0 1 0 1 0 1 0 0输出样例1&#xff1a; 3样例 111 解释 绿化图上 (0,0)(0,0)(0,0)、(1,1)(1,1)(1,1) 和 (2,2)(2,2)(2,2) 三处均可能埋有宝藏。 输入样例2&#xff1a; 5 4 2 0 0 1 1 2 2 3 3 …