【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)是核心概念,它们决定了模型的优化方向。…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...
基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...
