MyBatis扩展

news2024/12/24 11:36:57

目录

单元测试

spring boot的单元测试

 spring boot的单元测试的使用

1.在要测试的类里,右键点击生成

 2.点击test

3.配置测试的信息,点击ok

4.在生成的测试类里,加注解,写测试代码

5.运行单元测试

6.查看测试结果

追加测试方法

 断言

MyBatis

单表传参查询

 MyBatis获取动态参数有两种实现

 安全问题sql注入

单表修改操作

单表删除操作

单表添加操作

like模糊匹配查询

返回字典映射resultMap

多表查询

动态SQL的使用

为什么要使用动态sql

if标签

trim标签

where标签

set标签

foreach标签


单元测试

单元测试(unit testing)是指对软件中的最小可测试单元进行检查和验证的过程就叫做单元测试.

单元测试是开发者编写的一小段代码,用于检验被测代码的一个很小的,很明确的代码功能是否正确.执行单元测试就是为了证明某段代码的执行结果是否符合我们的预期.如果测试结果符合我们的预期,称之为测试通过,否则就是测试未通过.

单元测试的好处

  1. 可以简单直观快速的测试某一个功能是否正确.
  2. 使用单元测试可以帮我们在打包的时候,发现一些问题,因为在打包之前,所有的单元测试必须通过,否则不能打包成功.
  3. 使用单元测试,在测试功能的时候,可以不污染数据库中的数据,也就是说可以不对数据库进行任何改变的情况下来测试功能.
  4. 可以跳过系统限制(比如登录校验),直接测试代码功能.

spring boot的单元测试

Spring Boot项目创建的时候会默认帮我们添加单元测试的框架.

 这个单元测试的框架主要是依靠另一个著名的测试框架JUnit实现的.


 spring boot的单元测试的使用

我们要测试UserMapper中的getUserById这个方法.

1.在要测试的类里,右键点击生成


 2.点击test


3.配置测试的信息,点击ok


4.在生成的测试类里,加注解,写测试代码


5.运行单元测试


6.查看测试结果


追加测试方法

如果要在生成userMapper中的getall方法,还是按照上述的方式,只不过在生成测试类的时候,会报一个error,点击ok即可.


 断言

单元测试也可以搭配断言来使用.


 在掌握了单元测试之后,我们就可以在写MyBatis的时候,边写边测试.

MyBatis

单表传参查询

@Param就是给传递的参数起名字,当里面写成uid的时候,xml里也要用${uid}来接收.


 MyBatis获取动态参数有两种实现

1.${paramName} ,这种方式是直接替换.

2.#{paramName},这种方式是采用占位符的模式.

验证上述两种模式,我们可以在配置文件里进行配置,来打印MyBatis执行的sql

直接替换:

占位符:


两者的区别:

在使用上,传递一个int的类型的数据,看不出两者的区别,我们来传递一个varchar类型的数据.

根据名称来查询用户:

先使用占位符的方式:

  一切正常.

使用直接替换的方式:

报错了,因为是直接替换

生成的sql里张三没有加上单引号,所以报错了.

因为是直接替换,在查询varchar类型的数据的时候,由于没有单引号,所以会报错.

解决这个问题,我们可以手动加上单引号,这样可以不报错,但是直接替换不能保证我们的安全问题.


 安全问题sql注入

sql注入时常发生在登录中,用了一个不正确的用户密码,但是依然查询到了数据,所以我们模拟一个登录环境:

 

 当我们使用#{}时,是安全的,不会发生sql注入.我们改成${},看sql注入是如何发生的.

为了方便演示,我们数据库中的用户表中的内容只有一条数据.

生成测试代码,看其能否正确查询到用户信息:

正确的用户名密码可以查询到,错误的用户密码查询不到.

接下来,把密码设置成比较奇怪的一段字符:

这就发生了sql注入.

但是我们将${}改为#{}就没有这个问题:

这就说明${}存在安全性问题,#{}没有安全问题.

#{}采用的是预执行,而${}采用的是及时执行.#{}没有sql注入的问题,但是它是识别不了sql关键字的,当我们有些场景需要传递sql关键字的时候,使用#{}就不行了.

 降序升序传递的就是sql的关键字..

使用#{}就会报错. 


单表修改操作

userMapper:

 xml:

单元测试:

如果想让测试的数据不污染数据库,在单元测试方法上面加一个注解即可.

数据库的数据没有改变. 执行完之后进行一个回滚操作.


单表删除操作

 


单表添加操作

我们在添加用户的时候,除了返回受影响的行数之外,还希望得到添加的用户的id,这个应该怎么实现

呢?

单元测试的结果:

 useGeneratedKeys:这会令 MyBatis 使⽤ JDBC 的 getGeneratedKeys ⽅法来取出由数据

库内部⽣成的主键,默认是false.
keyProperty:指定能够唯⼀识别对象的属性,MyBatis 会使⽤ getGeneratedKeys 的返回值insert 语句的 selectKey ⼦元素设置它的值.默认值:未设置(unset)。如果⽣成列 不⽌⼀个,可以⽤逗号分隔多个属性名称。

like模糊匹配查询

我们实现根据用户名来模糊查询.

在UserMapper里实现方法声明:

在UserMapper.xml里实现方法的具体实现:

生成单元测试代码并启动: 

启动之后发现报错了.

报错的原因就是:我们使用#{}是占位符的方式

 所以,它会根据我们传递的参数类型来判断是否加单引号,由于我们传递的是String类型,所以最终生成的sql:

解决这个问题,我们可以使用mysql的内置函数concat,它的作用就是实现字符串的拼接.


返回字典映射resultMap

当实体类中的属性名称(pwd)和数据库中表的字段名称(password)不一致时,Mybatis就无法实现属性和字段的映射了.

在此种场景下,我们可以使用resultMap字典映射.此外resultMap也可以应用在一对一和一对多的关系查询中.

resultMap定义是在xml中的.

启动单元测试:

虽然名称不一致,但是由于我们设定了字典映射,所以返回的password依然能够映射到pwd上.

面对属性字段名称不一致的情况,我们还可以使用mysql的重命名,对查询的结果集的字段进行重命名.


多表查询

实现通过文章的id来查询文章表的详情页查询,除了要查询文章表的字段之外,还要知道文章的作者是谁.

创建一个ArticleInfo实体类

创建一个 ArticleInfoVO类,因为我们要查询的内容不只是文章表的,所以要使用到vo(value object).

vo中文翻译为'值对象',是一种特殊的Java Bean,与Entity相比,vo的作用更多是用于传递一些特定的数据,而不是表现整个业务实体数据.其属性通常是只读的.vo的属性通常是多个表或者其他来源手机并组装成的,用于集合多表数据.

我们只需要让其继承自ArticleInfo,在加一个username 属性即可,不必在把ArticleInfo的属性在写一遍.

创建ArticleMapper,加@Mapper注解,声明方法

创建 ArticleMapper.xml,进行方法的具体实现

生成单元测试,加@SpringBootTest注解,引入ArticleMapper

启动单元测试

发现只打印了子类的属性,没有打印父类的属性.

出现这个问题的原因就是,我们使用了lombok的@Data注解,生成的子类的toString方法默认是不打印父类属性的.这一点我们可以查看生成的target来验证.

解决这个问题.只需要重写toString方法即可.当我们重写toString之后,lombok的toString就会不起作用.

右键生成,点击toString(),选择本类+父类的模板.点击ok.

再次启动单元测试:


动态SQL的使用

动态 sql 是Mybatis的强⼤特性之⼀,能够完成不同条件下不同的 sql 拼接 .

就是允许在xml里面写逻辑判断.不同的执行生成的sql可能不同.

为什么要使用动态sql

在添加用户的时候会有这么一个场景:

必填字段和非必填字段.对于非必填字段,用户填入了,就在数据库正常插入即可.如果用户没有填,那么传过来就是null,如果不使用动态sql,在数据库中就插入了null值,但是我们期望的是用户不填我们就使用该字段的默认值,而不是null值.

我们就拿用户表中的state字段举例:

默认值是1.


if标签

模拟添加用户的时候photo是非必传的 .

方法实现:

 生成单元测试:

不传photo

传photo:

两次生成的sql是不同的,这就是动态sql.


trim标签

<trim>标签结合<if>标签,对多个字段都采取动态⽣成的⽅式。
<trim>标签中有如下属性:
prefix:表示整个语句块,以prefix的值作为前缀
suffix:表示整个语句块,以suffix的值作为后缀
prefixOverrides:表示整个语句块要去除掉的前缀
suffixOverrides:表示整个语句块要去除掉的后缀
在三个都是非必填的时候,仅仅使用if标签无法解决问题,原因就是对于sql中的逗号无法处理.


where标签


set标签

set标签用来修改操作的时候,它会帮我们自动生成set(set标签内容不为空的时候),也会帮我们自动去除逗号后缀.


foreach标签

对集合进⾏遍历时可以使⽤该标签。<foreach>标签有如下属性:

collection:绑定⽅法参数中的集合,如 List,Set,Map或数组对象

item:遍历时的每⼀个对象
open:语句块开头的字符串
close:语句块结束的字符串
separator:每次遍历之间间隔的字符串
<foreach>标签应用的场景就是在进行批量删除的时候.
像根据id删除文章的时候:

collection就是方法中的集合参数名称.
item就是遍历的每一个对象,名称是我们自己起的,用于在下面#{}拿到对象.
open前缀close后缀
separator间隔符.
生成的sql语句:
delete from article where id in (1,2,3);

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

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

相关文章

YOLO V3 SPP ultralytics 第二节:根据yolo的数据集,生成准备文件和yolo的配置文件

目录 1. 介绍 2. 完整代码 3. 代码讲解 3.1 生成 my_train_data.txt和my_val_data.txt 3.2 生成 my_data.data 文件 3.3 生成 my_yolov3.cfg 3.4 关于my_data_label.names文件 1. 介绍 根据 第一节 的操作&#xff0c;已经生成了下图中圆圈中的部分&#xff0c;而本…

又一个2W+的答题抽奖活动,复盘复盘总结总结

又一个2W的答题抽奖活动&#xff0c;复盘复盘总结总结 前段时间太忙了&#xff0c;现在才有时间对一些活动进行复盘总结&#xff0c;这里先对其中一个答题抽奖活动进行复盘总结一下。遇到的一些问题、分析以及其解决方案。 答题抽奖 参与者每答对一道题既可获得相对应的分数&…

什么是 Schnorr 签名?

在密码学中&#xff0c;Schnorr 签名是由 Schnorr 签名算法生成的数字签名。 与大多数区块链不同&#xff0c;BTC自其早期以来基本保持不变&#xff0c;大多数升级都是有限的&#xff0c;并旨在增强网络的效率而不是功能。BTC协议的更新是非常罕见的&#xff0c;并且通常用于技…

华为云赋能云:聚焦产数融合,深化数字赋能

编辑&#xff1a;阿冒 设计&#xff1a;沐由 假如你是一家制造企业的老板&#xff0c;一定会觉得近期的日子不太好过&#xff1a;国家统计局最新公布的数据显示&#xff0c;4月份制造业采购经理指数&#xff08;PMI&#xff09;为49.2%&#xff0c;较上月下降了2.7个百分点。 市…

I/O控制方式

目录 一、程序查询方式 1.程序查询流程 2.程序查询接口结构 3.案例习题 四、优缺点 二、程序中断方式 1.中断的概念 2.流程图 3.案例习题 三、DMA方式 1.DMA传送过程 2.DMA与主存交换数据的三种方式 3. 与中断程序处理的区别 4.案例习题 一、程序查询方式 1.程序…

C++中pair用法

博主简介&#xff1a;Hello大家好呀&#xff0c;我是陈童学&#xff0c;一个与你一样正在慢慢前行的人。 博主主页&#xff1a;陈童学哦 所属专栏&#xff1a;CSTL 前言&#xff1a;Hello各位小伙伴们好&#xff01;欢迎来到本专栏CSTL的学习&#xff0c;本专栏旨在帮助大家了解…

使用FFMPEG进行音频重采样

准备 1. ffmpeg 4.4 2. sdl2 3.一段原始的音频PCM数据 重采样流程 1.设置输入音频参数和输出音频参数 2.根据设置的参数初始化SwrContent上下文 3.创建一个输入buffer, 根据输入的音频参数&#xff08;采样率&#xff0c;通道数&#xff0c;样本位深度&#xff09;申请空间…

机器学习项目实战-能源利用率 Part-3(特征工程与特征筛选)

博主前期相关的博客可见下&#xff1a; 机器学习项目实战-能源利用率 Part-1&#xff08;数据清洗&#xff09; 机器学习项目实战-能源利用率 Part-2&#xff08;探索性数据分析&#xff09; 这部分进行的特征工程与特征筛选。 三 特征工程与特征筛选 一般情况下我们分两步走…

李彦宏一句“车水马龙”,中国AI的一幕天地宽广

“什么叫生成式&#xff1f;比如说&#xff0c;给我画一幅车水马龙的图片。这种东西&#xff0c;过去人们不觉得是人工智能应该做的事&#xff0c;现在可以做了。”5月18日&#xff0c;百度CEO李彦宏在天津举办的第七届世界智能大会上演讲时&#xff0c;说了这么一句话。 不了解…

保护你无价的数据 | 推荐一个开源备份工具,可去重、增量、压缩、还原到特定日期...

Borg 数据备份 Borg 的优势是 高效&#xff1a;BorgBackup 会将文件按数据块去重&#xff0c;只有改动的数据块才会被备份。一个 25 GiB 的虚拟机磁盘文件&#xff0c;只改动了 1 GiB&#xff0c;那就只会新增备份这 1 GiB 的数据&#xff1b;高速&#xff1a;核心算法使用 C 编…

5-《Kotlin》

5-《Kotlin》 1.kotlin基础&#xff1a; From Java To Kotlin2.Kotlin 的延迟初始化: lateinit var 和 by lazy1.lateinit var2.by lazy 3 Kotlin Tips:怎么用 Kotlin 去提高生产力&#xff08;kotlin优势&#xff09;Tip1- 更简洁的字符串Tip2- Kotlin中大多数控制结构都是表达…

[RapidOCRWeb] 桌面版使用教程

引言 说明&#xff1a;桌面版指的是可以直接解压&#xff0c;双击即可运行的版本。通俗来说&#xff0c;对rapidocr_web做了打包&#xff0c;将相关依赖全部放到一个zip包中&#xff0c;不需要本地有额外的环境&#xff0c;降低使用门槛。下面会以Windows版为例&#xff0c;作…

LeetCode 1373. 二叉搜索子树的最大键值和

【LetMeFly】1373.二叉搜索子树的最大键值和 力扣题目链接&#xff1a;https://leetcode.cn/problems/maximum-sum-bst-in-binary-tree/ 给你一棵以 root 为根的 二叉树 &#xff0c;请你返回 任意 二叉搜索子树的最大键值和。 二叉搜索树的定义如下&#xff1a; 任意节点的…

pandas---数据处理(excel文件)

近期在弄一个项目的前期数据&#xff0c;所以总结了一下&#xff0c;内容如下&#xff08;以下以csv文件为例&#xff09; 1. DataFrame常用操作1.1 DataFrame去除空行&#xff08;1&#xff09;对于一般空行&#xff08;2&#xff09;对于列表式&#xff08;list&#xff09;空…

Redis(二)对事务进行操作及Jedis

系列文章目录 Redis入门笔记&#xff08;一&#xff09;&#xff1a;Redis在Linux下安装和八大数据类型 文章目录 系列文章目录前言Redis对事务进行操作开启事务&#xff1a;multi执行事务&#xff1a;exec放弃事务&#xff1a;discard编译型异常&#xff08;命令错误&#xf…

信息安全-数据安全-字节大数据平台安全与权限治理实践

导读&#xff1a;本次分享题目为字节跳动大数据平台安全与权限治理实践&#xff0c;文章会围绕下面四点展开&#xff1a; 字节大数据安全体系现状和难点 细粒度权限管控和治理 资产保护能力 数据删除能力 分享嘉宾&#xff5c;许从余 火山引擎 数据平台产品经理 编辑整理&#…

Spring 5 笔记 - 新功能

1. Spring 5 框架新功能 整个Spring 5 框架的代码基于Java8&#xff0c;运行时兼容JDK9&#xff0c;许多不建议使用的类和方法在代码库中删除。Spring 5.0 框架自带了通用的日志封装 &#xff08;1&#xff09;Spring 5 已经移除 Log4jConfigListener&#xff0c;官方建议使用…

立创EDA标准版指南1-原理图与封装库

立创 EDA 标准版 由于立创 EDA 新版本改了对应术语&#xff0c;这是对于的表格&#xff1a; 原理图库->符号 PCB 库->封装 PCB 3D 库->3D 模型 下面的全部讲述将依据旧版称呼&#xff0c;因为更直观&#xff0c;新版称呼模棱两可并且与 AD 的工程架构差别较大 这是…

数据分析11——Pandas中数据偏移/数据切分/数据结构转换

数据偏移&#xff1a; 1、shift函数&#xff1a; 在 Pandas 中&#xff0c;shift 函数用于将数组的数据向前或向后平移指定的步数。它可以应用于 Series 或 DataFrame 类型的数据中&#xff0c;并返回一个平移后的新数据结构&#xff0c;其中每个元素都被取代为原始序列中对应…

kubernetes根据podName获取对应的主机pid

获取指定的podName kubectl get pods -n demo -owide登录对应的主机执行docker命令,获取到容器的id docker ps | grep PODNAME拿到的容器id&#xff0c;执行如下命令 获取容器的长的容器id docker inspect container_id找到容器id后 执行 apt-get install jq cat /var/lib…