【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)是核心概念,它们决定了模型的优化方向。…...
5分钟精通:roop-unleashed AI换脸技术的终极实战指南
5分钟精通:roop-unleashed AI换脸技术的终极实战指南 【免费下载链接】roop-unleashed Evolved Fork of roop with Web Server and lots of additions 项目地址: https://gitcode.com/gh_mirrors/ro/roop-unleashed 你是否想过,用一张简单的照片就…...
英雄联盟专业录像编辑器:免费开源工具League Director完全指南
英雄联盟专业录像编辑器:免费开源工具League Director完全指南 【免费下载链接】leaguedirector League Director is a tool for staging and recording videos from League of Legends replays 项目地址: https://gitcode.com/gh_mirrors/le/leaguedirector …...
【MATLAB绘图】三维曲面与二维映射组合图绘制,进阶教程与代码示例
文章目录基础示例:surfsurfsurf 三向等高线投影进阶示例:剖面切割 自定义配色高级示例:22 多子图组合常见问题与技巧基础示例:surfsurfsurf 三向等高线投影 %% 示例1:三维曲面 XY/XZ/YZ 三方向投影 clc; clear; c…...
基于Kustomize与Argo CD的Kubernetes云原生技术栈部署实践
1. 项目概述与核心价值 如果你和我一样,在家庭实验室(Homelab)或者开发测试环境中折腾过Kubernetes,那你一定对管理一大堆YAML文件深有体会。今天要聊的这个项目, zimmertr/Kubernetes-Manifests ,就是一…...
开放平台的调用日志与审计怎么设计?一次讲清 traceId、错误码、调用链与责任追踪
调用日志和审计中心怎么设计?traceId、错误码、调用链、责任追踪一次讲清 这篇直接按开放平台调用日志和审计来拆,不只讲“留个 access log”,而是把 traceId、错误码、调用链和责任追踪讲具体。 目标是你看完后,能把开放平台日志…...
避开那些坑!用Docker在Ubuntu 20.04上快速搞定OpenHarmony 4.0编译环境
避开那些坑!用Docker在Ubuntu 20.04上快速搞定OpenHarmony 4.0编译环境 在构建OpenHarmony 4.0开发环境时,许多开发者都会遇到依赖冲突、环境污染和架构不匹配等问题。传统方式需要在主机上安装大量软件包,不仅耗时耗力,还容易导致…...
Deep Searcher:解析混合搜索,打通向量检索的最后一公里
1. 项目概述:向量检索的“最后一公里”难题最近在折腾RAG(检索增强生成)应用,发现一个挺普遍的问题:向量数据库确实好用,把文本转成向量塞进去,靠相似度搜索能快速找到相关内容。但实际用起来&a…...
STM32H750驱动正点原子1.3寸屏,一个`IOSwap`参数没设对,屏幕就卡成PPT了?
STM32H750驱动1.3寸SPI屏幕:一个IOSwap参数引发的性能灾难 当我在STM32H750核心板上成功运行正点原子1.3寸屏幕的官方Demo时,那种成就感就像第一次点亮LED一样令人兴奋。然而这种喜悦很快被一个诡异现象打破——当我尝试显示自定义内容时,屏幕…...
GRADFILTERING:基于梯度信噪比的指令调优数据筛选方法
1. 项目背景与核心价值在指令调优(Instruction Tuning)领域,数据质量对模型性能的影响往往比数据量更重要。传统的数据选择方法通常依赖于人工规则或简单的启发式指标,难以有效识别数据中的噪声和低质量样本。GRADFILTERING提出了…...
新手福音:借Cousor理念在快马平台轻松学建待办事项应用
作为一个刚接触编程的新手,我最近尝试用InsCode(快马)平台做了一个待办事项应用,整个过程比想象中简单很多。这里记录下我的学习过程,希望能帮到同样想入门的朋友。 理解需求与设计思路 待办事项应用的核心功能其实很直观:能添加任…...
