MyBatis(二)

文章目录

  • 一.MyBatis的模式开发
    • 1.1 定义数据表和实体类
    • 1.2 配置数据源和MyBatis
    • 1.3 编写Mapper接口和增加xxxMapper.xml
    • 1.4 测试我们功能的是否实现.
  • 二. Mybatis的增删查改操作
  • 2.1 单表查询
  • 2.2 多表查询
  • 三.动态SQL的实现
    • 3.1 什么是动态SQL
    • 3.2 动态SQL的使用
      • if标签的使用
      • trim标签的使用
      • where标签的使用
      • set标签的使用
      • foreach标签的使用
    • 3.3 综合练习

一.MyBatis的模式开发

我们在开始MyBatis模式开发之前,我们首先来了解一下mybaits在整个框架的定位.看下图可知
在这里插入图片描述
MyBatis 也是一个ORM框架,ORM(Object Relational Mapping) ,即对象关系映射。在面向对象编程语言中,将关系型数据库中的数据与对象建立起映射关系,进而自动的完成数据与对象的互相转换:
1.将输入数据(即传入对象)+SQL映射成原生SQL
2.将结果集映射为返回对象,即输出对象

也就是说使⽤ MyBatis 可以像操作对象⼀样来操作数据库中的表,可以实现对象和数据库表之间
的转换,接下来我们来看 MyBatis 的使⽤吧.

使用过程中,还需要按照后端工程师的思路,来实现查询所有用户的功能.
在这里插入图片描述

1.1 定义数据表和实体类

创建数据表

 CREATE TABLE `userinfo` (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(100) NOT NULL,`password` varchar(32) NOT NULL,`photo` varchar(500) DEFAULT '',`createtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,`updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,`state` int(11) DEFAULT '1',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4

创建实体类

@Data
public class UserEntity {private Integer id;private String username;private String pwd;private String photo;private LocalDateTime createTime;private LocalDateTime updateTime;
}

1.2 配置数据源和MyBatis

在application.properties中配置以下内容

# mysql的配置文件
spring.datasource.url=jdbc:mysql://localhost:3306/mycnblog?characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
driver.class.driver-class-name=com.mysql.jdbc.Driver#配置 MyBatis 中的 XML 路径
# 1.保存路径 2.xml格式
mybatis.mapper-locations=classpath:mybatis/**Mapper.xml

1.3 编写Mapper接口和增加xxxMapper.xml

我们现来实现查询所有用户的功能.

定义接口UserMapper接口:

@Mapper注解代表一个Mapper

@Mapper
public interface UserMapper {public List<UserEntity> getAll();}

定义UserMapper.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">\
<select id="getAll" resultType="com.example.demo.entity.UserEntity">select*from userinfo</select>
</mapper>

针对以上标签进行说明
标签:需要指定namespace 属性,表示命名空间,值为 mapper接口的全限定名,包括全包名.类名。
查询标签:是用来执行数据库的查询操作的:
id:是和Interface (接口)中定义的方法名称一样的,表示对接口的具体实现方法。
resultType:是返回的数据类型,也就是开头我们定义的实体类。

1.4 测试我们功能的是否实现.

我们会引入一个单元测试的概念,我们每实现一个功能没必要,都要去启动项目,然后去验证,这时候我们就可以启动单元测试.
在springboot中启动单元测试也是比较简单的事情,具体的步骤如下:

  1. 在要测试的类上石健Generate…
    在这里插入图片描述
    在这里插入图片描述

  2. 在测试方法中加上@SpringBootTest注解
    在这里插入图片描述
    直接执行此方法,得出查询结果.
    在这里插入图片描述

二. Mybatis的增删查改操作

我们在知道了基本的Mybatis的流程,我们来进行基本的增删改查操作

2.1 单表查询

UserMapper接口文件

 //根据id查询对象UserEntity getUserById(@Param("id") Integer id);//根据名称查询用户对象UserEntity getUseByUserName(@Param("username")String username);// 登录方法UserEntity login(UserEntity user);// 修改密码int updatePassword(@Param("id") Integer id,@Param("password") String password,@Param("newpassword") String newPassword);//删除操作int delById(@Param("id") Integer id);//增加用户int addUser(UserEntity user);//得到用户idint addUserGetID(UserEntity user);//根据用户模糊查询List<UserEntity> getListByName(@Param("username")String username);

Usermapper.xml文件

    <select id="getUserById" resultType="com.example.demo.entity.UserEntity">select * from userinfo where id=#{id}</select><select id="getUseByUserName" resultType="com.example.demo.entity.UserEntity">select * from userinfo where username=${username}</select><select id="login" resultType="com.example.demo.entity.UserEntity">select * from userinfo where username= '${username}' and password= '${password}'</select><update id="updatePassword">update userinfo set password=#{newpassword}where id = #{id} and password=#{password}</update><delete id="delById">delete from userinfo where id=#{id}</delete><insert id="addUser">insert into userinfo(username,password) values(#{username},#{password})</insert><insert id="addUserGetID" useGeneratedKeys="true" keyProperty="id">insert into userinfo(username,password) values(#{username},#{password})</insert><select id="getListByName" resultMap="BaseMap">select id,username,password as pwd from userinfo where username like concat('%',#{username},'%')</select>

这上面有参数占位符,具体的解释如下;

#预编译处理。
$:字符直接替换。
预编译处理是指:MyBatis在处理f时,会将SQL 中的州替换为?号,使用PreparedStatement的set方法来赋值。
直接替换:是MyBatis 在处理$时,就是把$替换成变量的值。

这里来说明一下预编译处理和字符串直接替换

预编译处理(Prepared Statement)和字符串替换(String Replacement)是两种不同的数据库查询参数传递方式,它们在性能和安全性方面有着明显的区别。

预编译处理(Prepared Statement)

预编译处理是一种参数化查询的方式,在查询语句中使用占位符(通常是问号 “?”)来表示参数。
在执行预编译处理时,数据库会将SQL语句和参数分开处理,首先将SQL语句编译成一个准备好的查询模板,然后再将参数传递到模板中执行。
预编译处理将SQL语句与参数分开,因此能够有效地防止SQL注入攻击,提高了查询性能和安全性。
由于数据库在执行查询前已经对SQL语句进行了编译,所以对于多次执行相同查询但参数不同的情况,预编译处理能够提高性能,因为数据库可以重复使用相同的查询模板。
字符串替换(String Replacement):
字符串替换是一种直接将参数值嵌入到SQL语句中的方式。在查询语句中,直接将参数值拼接到SQL语句中的相应位置。
字符串替换的查询方式容易受到SQL注入攻击,因为恶意用户可以在参数值中插入恶意的SQL代码,破坏数据库或获取敏感数据。
由于字符串替换是每次执行查询都会生成一个新的SQL语句,所以对于相同查询的多次执行,每次都需要重新编译和执行,性能相对较低。

具体来说的话,我们来看下面的图示:
在这里插入图片描述

不知道大家注意到没有.上面的字符串替换,为什么会出现SQL注入问题,这里我用一张图给大家去解释
在这里插入图片描述

2.2 多表查询

在进行多表联查之前,我们还需要准备一个文章表

 CREATE TABLE `articleinfo` (`id` int(11) NOT NULL AUTO_INCREMENT,`title` varchar(100) NOT NULL,`content` text NOT NULL,`createtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,`updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,`uid` int(11) NOT NULL,`rcount` int(11) NOT NULL DEFAULT '1',`state` int(11) DEFAULT '1',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 |

插入了几条数据:
文章表的内容:

用户表的内容:
在这里插入图片描述
多表查询的接口类如下:

@Mapper
public interface ArticleMapper {//查询文章详情 一对一,一篇文章最多有一个作者ArticleInfoVO getDetail(@Param("id") Integer id);List<ArticleInfoVO> getArticleByUid(@Param("uid") Integer uid);}

配置文件如下:

  <select id="getDetail" resultType="com.example.demo.entity.vo.ArticleInfoVO">select a.*,u.username from articleinfo aleft join userinfo u on u.id=a.uidwhere a.id=#{id}</select><select id="getArticleByUid" resultType="com.example.demo.entity.vo.ArticleInfoVO">select a.* ,u.username from articleinfo aleft join userinfo u on u.id = a.uidwhere a.uid=#{uid}</select>

三.动态SQL的实现

3.1 什么是动态SQL

动态sql 是Mybatis的强大特性之一,能够完成不同条件下不同的sql拼接。
当然官网对其的解释入下:
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

3.2 动态SQL的使用

if标签的使用

if标签用于在SQL语句中根据条件判断是否包含某个SQL片段。语法如下:

<select id="getUsers" resultType="User">SELECT * FROM users<where><if test="name != null">AND name = #{name}</if><if test="age != null">AND age = #{age}</if></where>
</select>

在上面的例子中,根据传入的name和age参数的值,如果它们不为空,就会拼接对应的SQL条件,实现动态的查询语句。

trim标签的使用

trim标签用于在SQL语句的头部或尾部去除多余的SQL片段,以避免不必要的SQL语法错误。trim标签还可以根据条件去除WHERE或AND等关键字,以确保动态SQL的正确性。
trim标签中有如下属性:
prefix:表示整个语句块,以prefix的值作为前缀
suffix:表示整个语句块,以suffix的值作为后缀.
prefixOverrides:表示整个语句块要去除掉的前缀.
suffixOverrides:表示整个语句块要去除掉的后缀

<select id="getUsers" resultType="User">SELECT * FROM users<trim prefix="WHERE" prefixOverrides="AND | OR"><if test="name != null">AND name = #{name}</if><if test="age != null">AND age = #{age}</if><if test="gender != null">AND gender = #{gender}</if></trim>
</select>

在上面的例子中,我们使用了trim标签来包裹if标签,prefix属性指定了在条件满足时在WHERE关键字之前添加"WHERE",prefixOverrides属性指定了当条件不满足时去除多余的"AND "或"OR "。

where标签的使用

where标签用于在SQL语句中包含WHERE子句,并根据条件动态拼接查询条件。

<select id="getUsers" resultType="User">SELECT * FROM users<where><if test="name != null">AND name = #{name}</if><if test="age != null">AND age = #{age}</if></where>
</select>

set标签的使用

根据传⼊的⽤户对象属性来更新⽤户数据,可以使⽤标签来指定动态内容。
UserMapper 接⼝中修改⽤户⽅法:根据传⼊的⽤户 id 属性,修改其他不为 null 的属性:

<update id="updateUser" parameterType="User">UPDATE users<set><if test="name != null">name = #{name},</if><if test="age != null">age = #{age},</if></set>WHERE id = #{id}
</update>

foreach标签的使用

foreach的属性如下所示:
collection:绑定方法参数中的集合,如List,Set,Map或数组对象item:遍历时的每一个对象
open:语句块开头的字符串close:语句块结束的字符串
separator:每次遍历之间间隔的字符串
foreach标签用于在SQL语句中遍历集合,生成对应的SQL片段。它常用于批量插入或更新操作。

 <delete id="delByIdList"><!--        where id in(1,2..)-->delete from articleinfowhere id in<foreach collection="idList" item="aid" open="(" close=")" separator=",">#{aid}</foreach></delete>

这上面生成的语句,入下所示
delete from articleinfo where id in (1, 2, 3)

3.3 综合练习

在我们了解了基本的动态SQL标签之后,我们来一个综合的练习.
假设我们假如我们传入的参数都是非必须的.我们怎么才能完成SQL的拼接.
SQL如下:
select * from articleinfo WHERE id=? and title like concat(‘%’,?,‘%’)
我们传入参数的情况如下:
1.传入id,不传入title
2.传入title,不传入id
3.两个都不传
动态SQL的拼接策略如下:

方案一:

 <select id="getListByIdOrTitle" resultType="com.example.demo.entity.vo.ArticleInfoVO">select * from articleinfowhere 1=1 <trim prefixOVerrides="and"><if test="id!=null and id>0">and id=#{id}</if><if test="title!=null and title!=''">and title like concat('%',#{title},'%')</if></trim></select>

trim prefixOVerrides=“and”: 这是MyBatis的动态SQL标签trim的使用。trim标签用于在SQL语句的头部或尾部去除多余的SQL片段,并可以根据条件去除特定的关键字,如这里的and。prefixOverrides属性指定了当条件不满足时去除的前缀关键字,这里是and,表示如果条件不满足,就去除SQL语句中多余的and关键字。

方案二:

 <select id="getListByIdOrTitle" resultType="com.example.demo.entity.vo.ArticleInfoVO">select * from articleinfo<trim prefix ="where" suffixOverrides="and"><if test="id!=null and id>0">id=#{id}</if><if test="title!=null and title!=''">and title like concat('%',#{title},'%')</if></trim></select>

中间解释:
trim prefix=“where” suffixOverrides=“and”>: 这是MyBatis的动态SQL标签trim的使用。trim标签用于在SQL语句的头部或尾部去除多余的SQL片段,并可以根据条件去除特定的关键字,如这里的and。prefix属性指定了在条件满足时在WHERE关键字之前添加"where",suffixOverrides属性指定了当条件不满足时去除SQL语句中多余的"and"。
方案三:

 <select id="getListByIdOrTitle" resultType="com.example.demo.entity.vo.ArticleInfoVO">select * from articleinfo<where><if test="id!=null and id>0">id=#{id}</if><if test="title!=null and title!=''">and title like concat('%',#{title},'%')</if></where></select>

where标签: 这是MyBatis的动态SQL标签的使用。where标签的作用是将包含在其中的条件片段包裹在WHERE子句中,如果条件满足,WHERE关键字和多余的AND或OR将会被自动添加,如果条件不满足,则WHERE关键字也不会出现在最终的查询语句中

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

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

相关文章

M1/M2 通过VM Fusion安装Win11 ARM,解决联网和文件传输

前言 最近新入了Macmini M2&#xff0c;但是以前的老电脑的虚拟机运行不起来了。&#x1f605;&#xff0c;实际上用过K8S的时候&#xff0c;会发现部分镜像也跑不起来&#xff0c;X86的架构和ARM实际上还是有很多隐形兼容问题。所以只能重新安装ARM Win11&#xff0c;幸好微软…

Spring整合junit

1、导入pom坐标 <dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>org.springframework</gro…

【LeetCode】169.多数元素

题目 给定一个大小为 n 的数组 nums &#xff0c;返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的&#xff0c;并且给定的数组总是存在多数元素。 示例 1&#xff1a; 输入&#xff1a;nums [3,2,3] 输出&#xff1a;3…

【MySQL】表的操作

今天我们来谈谈MySQL下对表的操作 目录 一、创建表 二、查看表 2.1 查看库中存有的表 2.2 查看表结构 2.3 查看表的创建语句 三、修改表 3.1 重命名表名 3.2 新增列 3.3 修改列的数据类型 3.4 删除列 3.5 重命名列 四、删除表 一、创建表 我们要想在数据库中创建…

SpringMvc+阿贾克斯

0目录 1.SpringMVC 加阿贾克斯 2.分页版 1.实战 创建数据库 创建工程和pom依赖 配置web.xml和applicationContext.xml 实体类 Mapper接口方法 Mapper.xml BookService BookSeriviceImpl 控制层 测试 加入findAll.html 测试 2.分页版 控制层 PostMan测…

华为OD机试真题 Java 实现【AI面板识别】【2023 B卷 100分】,附详细解题思路

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明4、控制台输出 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08…

Redis旁路缓存,大KEY

Redis 旁路缓存 由于高并发原因&#xff0c;先更新数据库和先更新缓存策略都会因为延迟时间而导致数据不一致问题。 两种策略 先删除缓存&#xff0c;再更新数据库&#xff1b;先更新数据库&#xff0c;再删除缓存。 因为缓存的写入通常要远远快于数据库的写入&#xff0c;…

nginx 反向代理浅谈

前言 通常情况下&#xff0c;客户端向Web服务器发送请求&#xff0c;Web服务器响应请求并返回数据。而在反向代理中&#xff0c;客户端的请求不直接发送到Web服务器&#xff0c;而是发送到反向代理服务器。反向代理服务器会将请求转发给真实的Web服务器&#xff0c;Web服务器响…

MySQL - 报错问题解决

1、[HY000][1290] 错误信息"[HY000][1290] MySQL服务器使用了–secure-file-priv选项&#xff0c;因此无法执行此语句"表示MySQL服务器已配置启用了–secure-file-priv选项。此选项限制了LOAD DATA INFILE和SELECT INTO OUTFILE语句可以读取或写入文件系统的位置。默…

【C++】STL中stack,queue容器适配器的模拟实现(使用deque容器)

文章目录 前言一、deque的一些基本知识相比vector&#xff1a;相比list&#xff1a;3为什么选择deque作为stack和queue的底层默认容器 二、stack模拟实现三、queue的模拟实现 前言 STL标准库中stack和queue的底层结构 &#xff1a;虽然stack和queue中也可以存放元素&#xff0c…

java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法

文章目录 一、记录文件相关操作方法二、代码1.读取路径返回List\<File>2.读取路径返回List\<String>3.删除文件夹4.删除文件 一、记录文件相关操作方法 二、代码 1.读取路径返回List<File> import org.slf4j.LoggerFactory; import org.slf4j.Logger;impo…

【计算机视觉 | 图像分割】arxiv 计算机视觉关于图像分割的学术速递(7 月 26 日论文合集)

文章目录 一、分割|语义相关(7篇)1.1 Learning Transferable Object-Centric Diffeomorphic Transformations for Data Augmentation in Medical Image Segmentation1.2 Optical Flow boosts Unsupervised Localization and Segmentation1.3 Spectrum-guided Multi-granularity…

【LeetCode热题100】打卡第45天:倒数第24~20题

文章目录 【LeetCode热题100】打卡第45天&#xff1a;倒数第24~20题⛅前言 最佳卖股票时机含冷冻期&#x1f512;题目&#x1f511;题解 戳气球&#x1f512;题目&#x1f511;题解 零钱兑换&#x1f512;题目&#x1f511;题解 打家劫舍III&#x1f512;题目&#x1f511;题解…

opencv-25 图像几何变换04- 透视 cv2.warpPerspective()

什么是透视&#xff1f; 透视是一种几何学概念&#xff0c;用于描述在三维空间中观察物体时&#xff0c;由于视角的不同而产生的变形效果。在现实世界中&#xff0c;当我们从不同的角度或位置观察物体时&#xff0c;它们会呈现出不同的形状和大小。这种现象被称为透视效果。 透…

FFmpeg-两个文件mix重采样以那个为主

ffmpeg -i 2ch-44.1k.wav -i 2ch-16k.wav -filter_complex " \ [0:a][1:a]amixinputs2[aout]" \ -map [aout] -f null -ffmpeg -i 2ch-44.1k.wav -i 2ch-16k.wav -filter_complex " \ [0:a][1:a]amixinputs2[aout]" \ -map [aout] -f null -对比发现&#…

TCP网络通信编程之字节流

目录 【TCP字节流编程】 // 网络编程中&#xff0c;一定是server端先运行 【案例1】 【思路分析】 【客户端代码】 【服务端代码】 【结果展示】 【案例2】 【题目描述】 【注意事项】 【服务端代码】 【客户端代码】 【代码结果】 【TCP字节流编程】 // 网络编程中&a…

python刑事案卷图片转pdf

分两步&#xff0c;第一步是转图片&#xff0c;第二步是合并。 # -*- coding: utf-8 -*- import glob,os from PIL import Imagedef convert_to_pdf(path):# 打开图片文件img Image.open(path)# 将图片转换为 PDF&#xff0c;并保存到同名文件pdf_path os.path.splitext(path…

SVG图标,SVG symbols,SVG use标签

SVG图标&#xff0c;SVG symbols 项目中图标的使用&#xff0c;趋势是使用svg作图标的&#xff0c;优点如下 兼容现有图片能力前提还支持矢量 可读性好&#xff0c;有利于SEO与无障碍 在性能和维护性方面也比iconfont要强很多 怎么在项目中优雅的使用svg图标&#xff0c;下面…

minus(Oracle)集合减运算符

mysql不支持minus运算符 minus集合减运算符&#xff0c;即两个集合进行相减 举例&#xff1a;显示表格中第3-5行的内容 Oracle: select * from class01 where rownum<5 minus (select *from class01where rownum<2); 但是mysql可以使用join来模拟minus mysql使用jo…

We are the Lights 2023牛客暑期多校训练营4-L

登录—专业IT笔试面试备考平台_牛客网 题目大意&#xff1a;有n*m盏灯&#xff0c;q次操作&#xff0c;每次可以将一整行或一整列的等打开或关闭 1<n,m<1e6;1<q<1e6 思路&#xff1a;对于同一行或者同一列来说&#xff0c;只要最后一次操作时开或者关&#xff0…