【MyBatis】预编译SQL与即时SQL
目录
1. 以基本类型参数为例测试#{ }与${ }传递参数的区别
1.1 参数为Integer类型
1.2 参数为String类型
2. 使用#{ }传参存在的问题
2.1 参数为排序方式
2.2 模糊查询
3. 使用${ }传参存在的问题
3.1 SQL注入
3.2 对比#{ } 与 ${ }在SQL注入方面存在的问题
3.3 预编译SQL与即时SQL
3.4 解决模糊查询只能使用${}的问题
使用MyBatis进行数据库操作在进行参数传递时,有#{ } 与 ${ }两种方式。
本文介绍两种方式的区别;
1. 以基本类型参数为例测试#{ }与${ }传递参数的区别
1.1 参数为Integer类型
在UserInfoMapper文件中创建selectOne方法,分别使用#{ } 与 ${ }传递参数:
package com.zhouyou.mybatisdemo1.mapper;
import com.zhouyou.mybatisdemo1.model.UserInfo;
import org.apache.ibatis.annotations.*;import java.util.List;@Mapper
public interface UserInfoMapper {@Select("select* from userinfo where id= #{id}")UserInfo selectOne(Integer id);
}
编写测试类UserInfoMapperTest及测试方法:
package com.zhouyou.mybatisdemo1.mapper;import com.zhouyou.mybatisdemo1.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
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.*;
@Slf4j
@SpringBootTest
class UserInfoMapperTest {@Autowiredprivate UserInfoMapper userInfoMapper;@Testvoid selectOne() {log.info(userInfoMapper.selectOne(4).toString());}
}
使用#{ }的运行测试类情况:

使用${ }的运行测试类情况:

可见当参数为Intgeer类型时,使用#{ } 与 ${ }均可正确传递参数;
1.2 参数为String类型
在UserInfoMapper文件中创建selectOneByName方法,分别使用#{ } 与 ${ }传递参数:
package com.zhouyou.mybatisdemo1.mapper;
import com.zhouyou.mybatisdemo1.model.UserInfo;
import org.apache.ibatis.annotations.*;import java.util.List;@Mapper
public interface UserInfoMapper {@Select("select* from userinfo where username =#{username}")
// @Select("select* from userinfo where username =${username}")UserInfo selectOneByName(String name);
}
编写测试类UserInfoMapperTest及测试方法:
package com.zhouyou.mybatisdemo1.mapper;import com.zhouyou.mybatisdemo1.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
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.*;
@Slf4j
@SpringBootTest
class UserInfoMapperTest {@Autowiredprivate UserInfoMapper userInfoMapper;@Testvoid selectOneByName() {log.info(userInfoMapper.selectOneByName("zhangsan").toString());}
}
启动测试类,
对于使用#{ } 进行参数传递的方法,可正确运行;
对于使用${ } 进行参数传递的方法报错如下:

使用#{ }时,如果参数为String类型,会自动加上' ' ,
使用${ }时,会直接进行拼接,故如果参数为字符串类型,需手动增加 ' ',修改SQL语句如下:
@Select("select* from userinfo where username ='${username}'")
重启测试类,启动成功,日志如下:

2. 使用#{ }传参存在的问题
2.1 参数为排序方式
现以实现升序(参数为asc)或降序(参数为desc)的全列查询为例,分别使用#{ } 与 ${ }进行参数传递:
1、使用#{ }进行参数传递:
在UserInfoMapper中编写排序方法:
// 排序@Select("select* from userinfo order by id #{sort}")List<UserInfo> selectUserBySort(String sort);
生成测试方法并对排序结果进行打印:
@Testvoid selectUserBySort() {log.info(userInfoMapper.selectUserBySort("asc").toString());}
启动测试类,报错如下:

2、使用${ }参数传递:
在UserInfoMapper中编写修改排序方法,使用${ }传参:
@Select("select* from userinfo order by id ${sort}")List<UserInfo> selectUserBySort(String sort);
启动测试类,运行成功:

可见当参数为sql查询语句的排序方式:asc与desc时,若使用#{ }进行参数传递,则在该字符串上加上' '会造成错误,因此对于参数为排序方式的方法,只能使用${ }进行参数传递;
不止排序方式,包括参数为表名、字段名等作为参数时,也不能使用#{ }进行参数传递;
2.2 模糊查询
1、使用#{ }参数传递:
在UserInfoMapper中编写排序方法:
// 模糊查询@Select("select* from userinfo where username like '%#{partPara}%' ")List<UserInfo> selectUserByLike(String partPara);
生成测试方法并对排序结果进行打印:
@Testvoid selectUserByLike() {log.info(userInfoMapper.selectUserByLike("tian").toString());}
启动测试类,报错如下:

可见由于#{ }由于增加引号,也使得模糊查询出现问题。
2、使用${ }参数传递:
在UserInfoMapper中修改排序方法,使用${ }传递参数:
// 模糊查询@Select("select* from userinfo where username like '%${partPara}%' ")List<UserInfo> selectUserByLike(String partPara);
启动测试类,运行成功,查询结果如下:

3. 使用${ }传参存在的问题
3.1 SQL注入
SQL注入:是指将另外的SQL语句作为参数,执行后修改了原本的SQL语句,从而通过执行代码对服务器进行攻击。
比如:正常SQL如下:以参数为'admin'为例:
select* from userinfo where username= 'admin'
试传参为 'or 1 = ' 1,(使用'or 1 = ' 1直接替换admin),则SQL语句变为:
select* from userinfo where username= ''or 1 = ' 1'
1='1'恒成立,故会导致进行全列查询,获取userinfo整张表的信息。
3.2 对比#{ } 与 ${ }在SQL注入方面存在的问题
1、使用# { }传参:
在UserInfoMapper文件中创建selectOneByName方法,使用#{ } 传递参数:
package com.zhouyou.mybatisdemo1.mapper;
import com.zhouyou.mybatisdemo1.model.UserInfo;
import org.apache.ibatis.annotations.*;import java.util.List;@Mapper
public interface UserInfoMapper {@Select("select* from userinfo where username =${username}")UserInfo selectOneByName(String name);
}
编写测试类UserInfoMapperTest及测试方法:
package com.zhouyou.mybatisdemo1.mapper;import com.zhouyou.mybatisdemo1.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
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.*;
@Slf4j
@SpringBootTest
class UserInfoMapperTest {@Autowiredprivate UserInfoMapper userInfoMapper;@Testvoid selectOneByName() {log.info(userInfoMapper.selectOneByName("'or 1='1 ").toString());}
}
运行启动类,可见发生了SQL注入,使得查询到了整张表的信息:

2、使用# { }传参:
修改UserInfoMapper文件中的selectOneByName方法,改为使用#{ }传参:
@Select("select* from userinfo where username =#{username}")List<UserInfo> selectOneByName(String name);
重新启动测试类,查询结果如下:

可见使用#{ }进行参数传递并未发生SQL注入问题;
3.3 预编译SQL与即时SQL
1、对于使用#{ }进行参数传递的SQL语句采取预编译的方式,称为预编译SQL,SQL执行会进行语法解析、SQL优化、SQL编译等步骤,可避免SQL注入的发生;
2、对于使用${ }进行参数传递的SQL语句采取即时的方式,称为即时SQL,直接对参数进行拼接,有出现SQL注入的风险;
可见综合比对,使用#{}进行参数传递是更安全的选择。
3.4 解决模糊查询只能使用${}的问题
为了防止模糊查询使用${ }进行参数传递时导致的SQL注入问题,可以使用mysql的内置函数CONCAT搭配#{ }进行参数传递实现模糊查询:
@Select("select* from userinfo where username like CONCAT('%',#{partPara},'%')")List<UserInfo> selectUserByLike(String partPara);
测试函数传递参数为tian:

在实际开发中,尽量都使用#{ }进行传递。
相关文章:
【MyBatis】预编译SQL与即时SQL
目录 1. 以基本类型参数为例测试#{ }与${ }传递参数的区别 1.1 参数为Integer类型 1.2 参数为String类型 2. 使用#{ }传参存在的问题 2.1 参数为排序方式 2.2 模糊查询 3. 使用${ }传参存在的问题 3.1 SQL注入 3.2 对比#{ } 与 ${ }在SQL注入方面存在的问题 3.3 预编译…...
Python--正则表达式
1. 日志打印与终端颜色控制 1.1 使用 loguru 打印日志 from loguru import loggerlogger.debug("调试信息") logger.info("普通信息") logger.warning("警告信息") logger.error("错误信息") logger.success("成功信息"…...
【java面试】线程篇
1.什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。 2.线程和进程有什么区别? 线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任…...
分布式光纤传感:为生活编织“感知密网”
分布式光纤测温技术虽以工业场景为核心,但其衍生的安全效益已逐步渗透至日常生活。 分布式光纤测温技术(DTS)作为一种先进的线型温度监测手段,近年来在多个领域展现了其独特的优势。虽然其核心应用场景主要集中在工业、能源和基础…...
cmake Qt Mingw windows构建
今天教大家怎么在windows构建qt应用使用cmd命令行,而不是一键通过QtCreator一键构建。首先我们用qtcreator创建一个模板程序(PS:记得在安装qt时要悬着mingw套件,如果安装太慢可以换源) 输入以下的命令: mkdir build …...
无人机信号调制技术原理
一、调制技术的必要性 频谱搬移:将低频的基带信号搬移到高频的载波上,便于天线辐射和传播。 信道复用: 利用不同的载波频率或调制方式,实现多路信号同时传输,提高信道利用率。 抗干扰: 通过选择合适的调…...
书评与笔记:《如何有效报告Bug》
文章目录 书评笔记核心原则1. 首要目标:让程序员亲眼看到问题2. 次要目标:详细描述问题3. 保持冷静,避免误操作4. 提供额外信息5. 清晰、准确地表达 实用建议不要自作聪明地诊断问题类比:看医生时的症状描述程序员的心理 总结 原文…...
3.【线性代数】——矩阵乘法和逆矩阵
三 矩阵乘法和逆矩阵 1. 矩阵乘法1.1 常规方法1.2 列向量组合1.3 行向量组合1.4 单行和单列的乘积和1.5 块乘法 2. 逆矩阵2.1 逆矩阵的定义2.2 奇异矩阵2.3 Gauss-Jordan 求逆矩阵2.3.1 求逆矩阵 ⟺ \Longleftrightarrow ⟺解方程组2.3.2 Gauss-Jordan求逆矩阵 1. 矩阵乘法 1.…...
[JVM篇]虚拟机性能监控、故障处理工具
虚拟机性能监控、故障处理工具 基础故障处理工具 jps(JVM Peocess Status Tool - 虚拟机进程状况工具) jstat(JVM Statistics Monitoring Too - 虚拟机统计信息监视工具) jinfo( Configuration info for Java - Java配置信息工具) jmap(Memory Map for…...
UniApp 中 margin 和 padding 属性的使用详解
margin 属性的作用与使用 margin 属性用于设置元素的外边距,也就是元素与其他元素之间的距离。它可以分别设置元素四个方向(上、右、下、左)的外边距,也支持使用简写形式来一次性设置多个方向的外边距。 <template><view…...
`fi` 是 Bash 脚本中用来结束 `if` 条件语句块的关键字
fi 是 Bash 脚本中 if 语句的结束标志,它用于结束一个 if 块。与其他编程语言(如 C、Java)中的 } 不同,Bash 使用 fi 来标识条件语句的结束。 语法示例: if [ condition ]; then# 如果条件为真时执行的代码echo &quo…...
cap2:1000分类的ResNet的TensorRT部署指南(python版)
《TensorRT全流程部署指南》专栏文章目录: cap1:TensorRT介绍及CUDA环境安装cap2:1000分类的ResNet的TensorRT部署指南(python版)cap3:自定义数据集训练ResNet的TensorRT部署指南(python版&…...
每日一题——把数字翻译成字符串
把数字翻译成字符串 题目描述示例示例1示例2 题解动态规划代码实现复杂度分析 总结 题目描述 有一种将字母编码成数字的方式:‘a’->1, ‘b’->2, … , ‘z’->26。 现在给一串数字,返回有多少种可能的译码结果。 数据范围:字符串…...
我们来学HTTP/TCP -- 三次握手?
三次握手 题记三次呼叫结语 题记 来,我们来演示下川普王和普京帝会面了 哎呦!你好你好,握手…哎嗨!侬好侬好,握手…欧嘿呦玛斯,握手… 抓狂啊!作孽啊!!! 不说人话啊! 关键的是,“三…...
多媒体软件安全与授权新范例,用 CodeMeter 实现安全、高效的软件许可管理
背景概述 Reason Studios 成立于 1994 年,总部位于瑞典斯德哥尔摩,是全球领先的音乐制作软件开发商。凭借创新的软件产品和行业标准技术,如 ReWire 和 REX 文件格式,Reason Studios 为全球专业音乐人和业余爱好者提供了一系列高质…...
SQL复习
SQL复习 MySQL MySQL MySQL有什么特点? MySQL 不支持全外连接。 安装 数据类型 MySQL中的数据类型分为哪些? MySQL中的数据类型主要分为三大类:数值类型、字符串类型、日期时间类型。 其中, 数值类型又分为七种:T…...
红队视角出发的k8s敏感信息收集——日志与监控系统
针对 Kubernetes 日志与监控系统 的详细攻击视角分析,聚焦 集群审计日志 和 Prometheus/Grafana 暴露 的潜在风险及利用方法 攻击链示例 1. 攻击者通过容器逃逸进入 Pod → 2. 发现未认证的 Prometheus 服务 → 3. 查询环境变量标签获取数据库密码 → 4. 通过审…...
Flask中获取请求参数的一些方式总结
在 Flask 中,可以从 request 对象中获取各种类型的参数。以下是全面整理的获取参数的方式及示例代码。 1. 获取 URL 查询参数(Query String Parameters) URL 中的查询参数通过 ?keyvalue&key2value2 的形式传递,使用 reques…...
架构——LVS负载均衡主要模式及其原理、服务水平、优缺点
LVS(Linux Virtual Server)是一款高性能的开源负载均衡软件,支持多种负载均衡模式。以下是其主要模式及其原理、服务水平、优缺点: 1. NAT 模式(Network Address Translation) 原理: 请求流程…...
【漫话机器学习系列】093.代价函数和损失函数(Cost and Loss Functions)
代价函数和损失函数(Cost and Loss Functions)详解 1. 引言 在机器学习和深度学习领域,代价函数(Cost Function)和损失函数(Loss Function)是核心概念,它们决定了模型的优化方向。…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
Linux部署私有文件管理系统MinIO
最近需要用到一个文件管理服务,但是又不想花钱,所以就想着自己搭建一个,刚好我们用的一个开源框架已经集成了MinIO,所以就选了这个 我这边对文件服务性能要求不是太高,单机版就可以 安装非常简单,几个命令就…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...
