浅谈 Mybatis 框架

embedded/2024/11/13 9:13:17/

文章目录

  • 一、什么是MyBatis?
    • 1.2、JDBC
  • 二、使用Mybatis
    • 2.1、配置MyBatis开发环境
      • 2.1.1、配置连接字符串
      • 2.1.2、配置MyBatis中的XML路径
    • 2.2、使用MyBatis模式和语法操作数据库
  • 三、使用 Mybatis 进行增删改查操作的要点
    • 3.1、ResultMap的用法
  • 四、Mybatis操作难点
    • 4.1、#{ } 和 ${ } 的区别
      • 4.1.1、SQL注入问题
    • 4.2、like 模糊查询
    • 4.3、多表查询、联合查询
    • 4.3、动态 sql 的使用
      • 4.3.1、if 标签
      • 4.3.2、trim 标签
      • 4.3.3、where 标签
      • 4.3.4、set 标签
      • 4.3.5、foreach 标签

一、什么是MyBatis?

MyBatis是一款优秀的持久层框架,它支持自定义SQL、存储过程(多条SQL语句的集合)以及高级映射。MyBatis 去除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的XML或注解来配置和映射原始类型、接口和Java POJO (Plain Old Java Objects,普通老式Java对象)为数据库中的记录。

存储过程:
在这里插入图片描述
高级映射:程序中的类对应数据库中的表,程序中的类里的属性对应数据库的表中的字段。ORM把数据库映射为对象:数据库表(table) -->类(class)、
记录(record, 行数据) -->对象(object)、字段(field) -->对象的属性(attribute)

简单来说MyBatis是更简单完成程序和数据库交互的工具,也就是更简单的操作和读取数据库工具。

1.2、JDBC

我们之前使用JDBC连接数据库,那为什么还要学习MyBatis?这是因为JDBC操作十分繁琐。以下是JDBC的操作流程:
(1)、创建数据库连接池DataSource
(2)、通过DataSource获取数据库连接Connection
(3)、编写要执行带 ?占位符的SQL语句
(4)、通过Connection及SQL创建操作命令对象Statement
(5)、替换占位符:指定要替换的数据库字段类型,占位符索引及要替换的值
(6)、使用Statement执行SQL语句
(7)、查询操作:返回结果集ResultSet,更新操作:返回更新的数量
(8)、处理结果集
(9)、释放资源

JDBC代码例子的链接

二、使用Mybatis

在这里插入图片描述

学会使用Mybatis需要掌握两个步骤:

2.1、配置MyBatis开发环境

在项目中添加MyBatis:
在这里插入图片描述
注意:框架 framework 和 框架 Driver 必须成对出现。
在这里插入图片描述
当项目中添加了数据库框架后,启动项目是失败的也不要慌张,这是正常现象。

因为项目中添加了数据库框架之后,却没有配置数据库的路径,所以项目启动报错。(一台机器上可以安装很多个数据库,想要连接哪个数据库就需要指定那个数据库的路径,才能够连接成功。)

2.1.1、配置连接字符串

那怎么指定呢??此时就需要配置连接字符串和MyBatis。需要进行两项设置,数据库连接字符串设置和MyBatis的XML文件配置。
(1)、配置连接字符串(4项)
如果是application.yml配置文件,则添加如下内容(系统配置项):(给的是模板,具体内容以自己的数据库为准)
#数据库连接配置

spring:datasource:url: jdbc :mysql://localhost:3306/mycnblogcharacterEncoding=utf8&useSSL=falseusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driver

在这里插入图片描述

2.1.2、配置MyBatis中的XML路径

MyBatis中有两种实现数据库增删改查的方式,分别是:1、使用 XML 的范式。2、一种是使用注解的方式。

虽然使用注解的方式来写sql语句去实现数据库的增删改查功能一开始会比较容易,但是这是假象,只适合简单的sql语句以及简单的功能,但是当业务复杂起来的时候,使用注解的方式就十分不方便,同时使用注解的方式还容易将代码与sql语句混杂在一起,不容易实现代码的复用性、简洁性。因此我们通常会使用XML文件来实现数据库的增删改查。

只放个注解的例子图,不推荐使用这种方式,现在很少有人用了。
在这里插入图片描述
这是使用XML的方式:

因为Mybatis由2部分组成:
1、接口 ( interface ) :接口里会声明所有操作方法。这些方法是给程序里的其他类来调用。
2、使用 XML 实现接口。即XML里需要写具体的SQL语句。

想要使用 XML 的方式实现数据库的增删改查,还需要在配置文件中配置如下内容:(这些配置信息是告诉Mybatis要使用哪些文件)
在这里插入图片描述

#设置mybatis的xml保存路径
mybatis:mapper-locations: classpath:mapper/*Mapper.xml

2.2、使用MyBatis模式和语法操作数据库

这一步就是遵循MyBatis的写法在项目中构建相应的业务实现即可。

项目的业务交互图:
在这里插入图片描述

此处是一个项目例子来使用MyBatis模式和语法操作数据库

一、基础准备
(1)、首先需要创建一个ssm的项目,项目需要准备好Mybatis Framework以及 MySQL Driver ,创建好后将配置文件中的配置信息先配置好:
在这里插入图片描述

(2)、然后在项目中依次创建好 controller层(控制器层)、service层(服务层)、mapper层(数据库持久层)、entity层(实体类)。

(3)、然后需要准备一个数据库数据库中含有一张表,将表与程序中的类映射起来。

在这里插入图片描述
在这里插入图片描述
二、构建 Mapper 层的代码实现

(1)、在mapper层定义一个接口:
接口中可以含有多个方法,这些方法就对应你项目的增删改查或者其他的功能模块。

在这里插入图片描述
(2)、创建 XML 实现
在这里插入图片描述
在mapper包下创建一个 xml 文件:
在这里插入图片描述
在这里插入图片描述
三、实现服务层代码
在这里插入图片描述
四、实现控制器层代码
在这里插入图片描述
写完代码后,启动项目,在浏览器上输入URL,获取数据库中的数据:
在这里插入图片描述

三、使用 Mybatis 进行增删改查操作的要点

(1)、使用Mybatis进行查询操作
在这里插入图片描述
查询操作的两个必备属性中,第一个属性是id;第二个属性写法可以是 ResultType,也可以是 ResultMap。

使用ResultType,是因为程序中的实体类里的属性名称都和数据库中表的字段名称一致,所以可以使用ResultType。

使用ResultMap,是因为一般在公司,数据库是专门由DB负责的,而程序代码的书写由程序员负责,一般开始项目大家都是同时开工,程序员不知道DB设计出的数据库里面会用什么表名、字段名,因此此时想要让程序与表映射,需要用到ResultMap。(即ResultMap 用在当程序中的属性名与数据库表中的字段名不一致时)。

举个例子:
在这里插入图片描述
这是因为在查询的过程中,如果数据库表的字段名能够与程序中的属性名对应上,那就将数据库中的数据赋值给程序中的属性,如果数据库表中的字段名和程序中的属性名对应不上,那程序中的属性值就是null。

插入、删除、修改操作时也有这样的情况,但是和查询时相反的。若程序中的属性名与数据库表中的字段名匹配,可以赋值,操作成功,否则反之。

ResultMap(返回字典映射) 应用场景
(1)、字段名称和程序中的属性名不同的情况,可使用resultMap配置映射;
(2)、一对一和一对多关系可以使用resultMap映射并查询数据。

3.1、ResultMap的用法

(1)、先声明
在这里插入图片描述
(2)、再使用
在这里插入图片描述
除了使用 resultMap 的方法,还有另一种更加简单的方法:
使用数据库别名 as 重命名。
在这里插入图片描述

(2)、使用Mybatis进行添加操作
在这里插入图片描述

因为我们的IDEA是默认隐藏Mybatis生成sql的执行细节,因此如果想要让控制台打印我们所执行的sql语句,可以在配置文件中进行配置。配置后,可利用sql语句排查问题。
在这里插入图片描述
配置文件:
在这里插入图片描述
在这里插入图片描述

(3)、使用Mybatis进行删除操作
在这里插入图片描述

(4)、使用Mybatis进行修改操作
在这里插入图片描述

Mybatis项目例子,这个链接是上面所写的项目例子与数据库所进行的增删改查的操作的具体代码,大家可以跟着动手写一写,熟能生巧。

四、Mybatis操作难点

前面在项目例子中演示的增删改查操作,是最基本最简单的操作,但其实在实际项目中,远比这些难得多,不仅仅涉及到对一个表的增删改查,还会涉及到多表查询操作、联合查询、条件查询…这个时候的sql语句就会比较难了。

4.1、#{ } 和 ${ } 的区别

在.xml文件里书写sql语句时,其实我们一般见到的都是 #{ } 类型的:
在这里插入图片描述

但是其实 ${ } 也可以实现和 #{ } 一样的功能,但是为什么现在常见的都是使用#{ },而 ${ }却很少见呢?他们有什么区别?

#{ } 的sql语句时使用的是预编译处理,即sql语句中先使用占位符?。这样的好处就是先占了才赋值,可以适配多种情况,不管是整型还是字符串…
在这里插入图片描述
在这里插入图片描述
而 ${ } 的sql语句是直接赋值,直接赋值的话整型的情况下没有问题,但是字符串的情况下就会有问题:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
但是,${ } 有一个 #{ }不具备的重要功能:能够传递一些关键字。(但是在使用 ${ } 传递关键字时,我们还必须确定这个传递的值能够穷举:就是需要先在 controller 层对这个值进行参数校验,比如传的是一个order值,这个order变量它的取值是否是desc或者asc,如果都不是,不给传值,避免 ${ } 的sql注入问题)
在这里插入图片描述
代码实现:
在这里插入图片描述
在这里插入图片描述
单元测试:
在这里插入图片描述
在这里插入图片描述

4.1.1、SQL注入问题

我们上面说了,传关键字是 ${ } 的唯一应用场景(是因为 ${ } 不安全,会产生SQL注入的问题)。但是我们必须保证传的这个参数是可预期的,如果传的是一个不可预期的参数,有可能会产生SQL注入的问题:因为 ${ } 是直接赋值,因此一些有心人会抓住这个漏洞做一些非法的事情。

譬如:当我们进行登陆操作时,当使用 ${ } 进行登陆操作的sql语句书写时(要想测试sql注入现象成功,需要保证数据库里只有一行记录的情况下才可以):
在这里插入图片描述
单元测试1:
在这里插入图片描述
单元测试2(sql注入问题):
在这里插入图片描述

但是使用 #{ } 就没有sql注入这样的问题:
在这里插入图片描述
在这里插入图片描述
那么为什么这样一串字符串:’ or 1='1 就会引起sql注入问题?
在这里插入图片描述

总结:#{ } 和 ${ } 的区别:
(1)、 ${ } 存在 sql注入问题,而 #{ } 不存在。
(2)、 ${ } 是直接赋值,而#{ } 是采用预编译的。

使用 ${ } 的注意事项:
(1)、确保传入的值是可穷举,可预期的。
(2)、需要先在 controller 层进行参数校验。

4.2、like 模糊查询

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

此时可以采用 mysql 的内置函数 concat() 进行拼接:
在这里插入图片描述
在这里插入图片描述

4.3、多表查询、联合查询

多表查询是非常容易遇到的操作,并且多表查询比单表查询要难。当我们需要进行多表查询,但是实体类却只包含单表查询的实体类,该怎么办??
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

针对上面的问题,有两个解决方法:
(1)、不再继承基础类,直接写全所有属性:
在这里插入图片描述
在这里插入图片描述
(2)、仍旧是继承自基础类,但是需要将lombok生成的toString()覆盖
在这里插入图片描述
因此我们可以在扩展类中自己写一个 toString() 方法,将lombok自动生成的toString() 方法覆盖掉:
在这里插入图片描述
注意:一般我们在写实体类的时候,习惯将类都实现 Serializable 接口并新增一个版本字段。因为我们写的实体类,不可避免后面都会有可能进行序列化/反序列化。

当我们遇到多表联查,直接采用这个解决方案即可:
联表查询语句(left jion / inner join)+XXXVO 解决。

4.3、动态 sql 的使用

动态 sql 是 Mybatis 强大特性之一,能够实现复杂条件下不同的 sql 拼接。
动态sql的应用场景一般在当前界面既含有必填项又含有非必填项,如下图此类:
在这里插入图片描述

4.3.1、if 标签

if标签是一个条件判断,如果if标签里的属性test是true,就执行if标签里的内容,如果属性test是false,就不执行if标签里的内容。if标签一般用于含有较少非必填项的场景。

if标签语法:

<if test = "参数名 != null  and 参数名 != ''">...
</if>

例子:
在这里插入图片描述
使用动态sql时:
在这里插入图片描述
在这里插入图片描述

4.3.2、trim 标签

trim标签一般用于含有多个非必填项的场景。trim要求里边必须至少包含一个if标签去配合使用!
trim标签的语法:
在这里插入图片描述
这两标签一般用于插入操作。

4.3.3、where 标签

where 标签的语法:
在这里插入图片描述
在这里插入图片描述

4.3.4、set 标签

set 标签语法:
在这里插入图片描述
以上标签也可以使用 < trim prefix= “set” suffixoverrides=“,”> < /trim>替换。
单元测试成功:
在这里插入图片描述

4.3.5、foreach 标签

foreach标签的应用场景一般是在批量操作上。例如批量删除批量修改批量添加…当系统进行批量操作时,前端传的是一个集合,后端需要对集合进行遍历时就可以使用该标签。

< foreach> 标签有如下属性:
(1)、collection: 绑定方法参数中的集合,如List, Set, Map或数组对象
(2)、item: 遍历时的每一 个对象
(3)、open:语句块开头的字符串
(4)、close: 语句块结束的字符串
(5)、separator:每次遍历之间间隔的字符串

foreach标签语法:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


http://www.ppmy.cn/embedded/91139.html

相关文章

FPGA设计之跨时钟域(CDC)设计篇(5)----同步FIFO的两种设计方法(计数器法/高位扩展法 | 手撕代码)

1、什么是FIFO? FIFO(First In First Out) 是一种先进先出的数据缓存器,在逻辑设计里面用的非常多。它是一种存储器结构,被广泛应用于芯片设计中。FIFO由存储单元队列或阵列构成,第一个被写入队列的数据也是第一个从队列中读出的数据。 FIFO 设计可以说是逻辑设计人员必须…

Python 爬虫入门(八):爬虫工程化及Scrapy简介「详细介绍」

Python 爬虫入门&#xff08;八&#xff09;&#xff1a;爬虫工程化及Scrapy简介「详细介绍」 前言1. Python1.1 Python 简介1.2 Python 爬虫的优势1.3 必须掌握的 Python 基础知识1.3.1 基本语法1.3.2. 函数和模块1.3.3 文件操作1.3.4 数据处理1.3.5 类和对象1.3.6 异常处理 2…

48天笔试训练错题——day41

目录 选择题 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 编程题 1. 五子棋 2. Emacs计算器 选择题 1. 当发生拥塞时&#xff0c;TCP 有个机制&#xff0c;会从慢开始进行发送。 1. 把慢开始的门限值设为当前窗口的一半&#xff0c;即 ssthresh 1/2 * 8 4 KB 2. 把拥塞窗…

提升生产效率:APS高级计划排程系统在车间工序级排程的革命性应用

在制造业的数字化转型浪潮中&#xff0c;APS高级计划排程系统以凭借自身卓越的排程运算能力和应用灵活性&#xff0c;已经成为中大型制造业提升生产效率的关键工具。APS系统的介入&#xff0c;打通了传统ERP和MES等各类业务系统运营平台&#xff0c;并且通过产能均衡规划&#…

Sentinel-1 Level 1数据处理的详细算法定义(五)

《Sentinel-1 Level 1数据处理的详细算法定义》文档定义和描述了Sentinel-1实现的Level 1处理算法和方程,以便生成Level 1产品。这些算法适用于Sentinel-1的Stripmap、Interferometric Wide-swath (IW)、Extra-wide-swath (EW)和Wave模式。 今天介绍的内容如下: Sentinel-1 L…

flex的css总结,

1、App.vue的<style>中全局阴影 <style> /* 引入flex布局样式 */ import "./styles/flex.css"; </style> 2、编写flex.css文件 charset "UTF-8";.flex {display: -webkit-flex;display: flex; }/*即项目的排列方向*/ .flex-direction…

【Visual Studio Code】源代码管理 传入/传出 更改配置开关

July 2024 (version 1.92)版本更新的Visual Studio Code 增加了 【源代码管理 - 传入/传出】的可视化视图。 但是目前发现也会导致加载变慢 占用页面的影响&#xff0c;如果希望关闭该视图&#xff0c; 可以在设置里搜索 scm.showHistoryGraph 关闭即可

华清IOday7 24-8-5

文章目录 使用有名管道实现&#xff0c;一个进程用于给另一个进程发消息&#xff0c;另一个进程收到消息后&#xff0c;展示到终端上&#xff0c;并且将消息保存到文件上一份使用有名管道实现两个进程间相互通信 使用有名管道实现&#xff0c;一个进程用于给另一个进程发消息&a…