当前位置: 首页 > news >正文

【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.什么是线程&#xff1f; 线程是操作系统能够进行运算调度的最小单位&#xff0c;它被包含在进程之中&#xff0c;是进程中的实际运作单位。 2.线程和进程有什么区别&#xff1f; 线程是进程的子集&#xff0c;一个进程可以有很多线程&#xff0c;每条线程并行执行不同的任…...

分布式光纤传感:为生活编织“感知密网”

分布式光纤测温技术虽以工业场景为核心&#xff0c;但其衍生的安全效益已逐步渗透至日常生活。 分布式光纤测温技术&#xff08;DTS&#xff09;作为一种先进的线型温度监测手段&#xff0c;近年来在多个领域展现了其独特的优势。虽然其核心应用场景主要集中在工业、能源和基础…...

cmake Qt Mingw windows构建

今天教大家怎么在windows构建qt应用使用cmd命令行&#xff0c;而不是一键通过QtCreator一键构建。首先我们用qtcreator创建一个模板程序(PS&#xff1a;记得在安装qt时要悬着mingw套件&#xff0c;如果安装太慢可以换源&#xff09; 输入以下的命令&#xff1a; mkdir build …...

无人机信号调制技术原理

一、调制技术的必要性 频谱搬移&#xff1a;将低频的基带信号搬移到高频的载波上&#xff0c;便于天线辐射和传播。 信道复用&#xff1a; 利用不同的载波频率或调制方式&#xff0c;实现多路信号同时传输&#xff0c;提高信道利用率。 抗干扰&#xff1a; 通过选择合适的调…...

书评与笔记:《如何有效报告Bug》

文章目录 书评笔记核心原则1. 首要目标&#xff1a;让程序员亲眼看到问题2. 次要目标&#xff1a;详细描述问题3. 保持冷静&#xff0c;避免误操作4. 提供额外信息5. 清晰、准确地表达 实用建议不要自作聪明地诊断问题类比&#xff1a;看医生时的症状描述程序员的心理 总结 原文…...

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&#xff08;JVM Peocess Status Tool - 虚拟机进程状况工具&#xff09; jstat(JVM Statistics Monitoring Too - 虚拟机统计信息监视工具) jinfo( Configuration info for Java - Java配置信息工具) jmap(Memory Map for…...

UniApp 中 margin 和 padding 属性的使用详解

margin 属性的作用与使用 margin 属性用于设置元素的外边距&#xff0c;也就是元素与其他元素之间的距离。它可以分别设置元素四个方向&#xff08;上、右、下、左&#xff09;的外边距&#xff0c;也支持使用简写形式来一次性设置多个方向的外边距。 <template><view…...

`fi` 是 Bash 脚本中用来结束 `if` 条件语句块的关键字

fi 是 Bash 脚本中 if 语句的结束标志&#xff0c;它用于结束一个 if 块。与其他编程语言&#xff08;如 C、Java&#xff09;中的 } 不同&#xff0c;Bash 使用 fi 来标识条件语句的结束。 语法示例&#xff1a; if [ condition ]; then# 如果条件为真时执行的代码echo &quo…...

cap2:1000分类的ResNet的TensorRT部署指南(python版)

《TensorRT全流程部署指南》专栏文章目录&#xff1a; cap1&#xff1a;TensorRT介绍及CUDA环境安装cap2&#xff1a;1000分类的ResNet的TensorRT部署指南&#xff08;python版&#xff09;cap3&#xff1a;自定义数据集训练ResNet的TensorRT部署指南&#xff08;python版&…...

每日一题——把数字翻译成字符串

把数字翻译成字符串 题目描述示例示例1示例2 题解动态规划代码实现复杂度分析 总结 题目描述 有一种将字母编码成数字的方式&#xff1a;‘a’->1, ‘b’->2, … , ‘z’->26。 现在给一串数字&#xff0c;返回有多少种可能的译码结果。 数据范围&#xff1a;字符串…...

我们来学HTTP/TCP -- 三次握手?

三次握手 题记三次呼叫结语 题记 来&#xff0c;我们来演示下川普王和普京帝会面了 哎呦&#xff01;你好你好&#xff0c;握手…哎嗨&#xff01;侬好侬好&#xff0c;握手…欧嘿呦玛斯&#xff0c;握手… 抓狂啊&#xff01;作孽啊!!! 不说人话啊! 关键的是&#xff0c;“三…...

多媒体软件安全与授权新范例,用 CodeMeter 实现安全、高效的软件许可管理

背景概述 Reason Studios 成立于 1994 年&#xff0c;总部位于瑞典斯德哥尔摩&#xff0c;是全球领先的音乐制作软件开发商。凭借创新的软件产品和行业标准技术&#xff0c;如 ReWire 和 REX 文件格式&#xff0c;Reason Studios 为全球专业音乐人和业余爱好者提供了一系列高质…...

SQL复习

SQL复习 MySQL MySQL MySQL有什么特点&#xff1f; MySQL 不支持全外连接。 安装 数据类型 MySQL中的数据类型分为哪些&#xff1f; MySQL中的数据类型主要分为三大类&#xff1a;数值类型、字符串类型、日期时间类型。 其中&#xff0c; 数值类型又分为七种&#xff1a;T…...

红队视角出发的k8s敏感信息收集——日志与监控系统

针对 Kubernetes 日志与监控系统 的详细攻击视角分析&#xff0c;聚焦 集群审计日志 和 Prometheus/Grafana 暴露 的潜在风险及利用方法 攻击链示例 1. 攻击者通过容器逃逸进入 Pod → 2. 发现未认证的 Prometheus 服务 → 3. 查询环境变量标签获取数据库密码 → 4. 通过审…...

Flask中获取请求参数的一些方式总结

在 Flask 中&#xff0c;可以从 request 对象中获取各种类型的参数。以下是全面整理的获取参数的方式及示例代码。 1. 获取 URL 查询参数&#xff08;Query String Parameters&#xff09; URL 中的查询参数通过 ?keyvalue&key2value2 的形式传递&#xff0c;使用 reques…...

架构——LVS负载均衡主要模式及其原理、服务水平、优缺点

LVS&#xff08;Linux Virtual Server&#xff09;是一款高性能的开源负载均衡软件&#xff0c;支持多种负载均衡模式。以下是其主要模式及其原理、服务水平、优缺点&#xff1a; 1. NAT 模式&#xff08;Network Address Translation&#xff09; 原理&#xff1a; 请求流程…...

【漫话机器学习系列】093.代价函数和损失函数(Cost and Loss Functions)

代价函数和损失函数&#xff08;Cost and Loss Functions&#xff09;详解 1. 引言 在机器学习和深度学习领域&#xff0c;代价函数&#xff08;Cost Function&#xff09;和损失函数&#xff08;Loss Function&#xff09;是核心概念&#xff0c;它们决定了模型的优化方向。…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;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 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

R 语言科研绘图第 55 期 --- 网络图-聚类

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; 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 注意&#xff1a;运行前…...

华为OD机试-最短木板长度-二分法(A卷,100分)

此题是一个最大化最小值的典型例题&#xff0c; 因为搜索范围是有界的&#xff0c;上界最大木板长度补充的全部木料长度&#xff0c;下界最小木板长度&#xff1b; 即left0,right10^6; 我们可以设置一个候选值x(mid)&#xff0c;将木板的长度全部都补充到x&#xff0c;如果成功…...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道

文/法律实务观察组 在债务重组领域&#xff0c;专业机构的核心价值不仅在于减轻债务数字&#xff0c;更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明&#xff0c;合法债务优化需同步实现三重平衡&#xff1a; 法律刚性&#xff08;债…...