Java持久层框架之mybatis使用

article/2025/10/14 8:30:09

一.什么是框架,框架从何而来,为什么使用框架?
框架(framework):
1.是一系列jar包,其本质是对JDK功能的拓展.(jar包,jar:class文件的压缩包)
2.框架是一组程序的集合,包含了一系列的最佳实践,作用是解决某一个领域的问题.
最佳实践(Best Practice):实际上是无数程序员经历过无数次尝试之后,总结出来的处理特定问题的特定方法.
如果把程序员的自由发挥看作是一条通往成功的途径,最佳实践就是其中的最短路径,能极大的解放生产力.
Web开发中的最佳实践:分层开发模式(技术层面的"分而治之")
JavaEE开发根据职责的纵向划分:表现层,业务层,持久层:
表现层(Predentation Layer):web/mvc: 负责处理与界面交互的相关操作(Struts2/Spring MVC)
业务层(Business Layer) :service: 负责复杂的业务逻辑计算和判断(Spring)
持久层(Persistent Layer) :dao: 负责将业务逻辑数据进行持久化存储(Hibernate/MyBatis)
持久层封装了数据访问的细节,为业务逻辑层提供了面向对象的API,完善的持久层应该达到:
1.代码重用性高,可以完成所有的数据访问操作.
2.可以支持多种数据库,可以在多种数据库之前任意切换.
3.具有相对独立性,当持久层变化时,不会影响上一层(service)实现.

二.OR Mapping
对象关系映射(Object Relational Mapping,简称ORM):
是一种为了解决面向对象与关系数据库存在的互不匹配的现象的规范。
简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将java程序中的对象自动持久化到关系数据库中。
避免直接使用SQL语句对关系型数据库中的数据进行操作.
减少代码编写量,提高产品质量.
ORM 主要解决对象-关系的映射:
面向对象概念 面向关系概念

类 表
对象 表的行(记录)
属性 表的列(字段)
ORM的实现思想:
将关系数据库中表中的记录映射成为对象,以对象的形式展现,程序员可以把对数据库的操作转化为对对象的操作。因此ORM的目的是为了方便开发人员以面向对象的思想来实现对数据库的操作。
ORM 采用元数据来描述对象-关系映射细节:
元数据通常采用 XML 格式,并且存放在专门的对象-关系映射文件中。
目前流行的ORM框架:SSH
1.JPA:本身是一种ORM规范,不是ORM框架.由各大ORM框架提供实现.
2.Hibernate:目前最流行的ORM框架.设计灵巧,性能优秀,文档丰富.
3.MyBatis:本是apache的一个开源项目iBatis,提供的持久层框架包括SQL Maps和DAO,允许开发人员直接编写SQL.
在这里插入图片描述
三.mybatis简介:
MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJOs(Plan Old Java Objects,普通的 Java 对象)映射成数据库中的记录。
中文学习文档
提取码:acqt

四.第一个mybatis项目:
详见idea新建一个简单的基于mybatis的项目

五.MyBatis的运行流程:
总结:
1、获取sqlSessionFactory对象:
根据配置文件(全局,sql映射)初始化出Configuration对象
解析文件的每一个信息保存在Configuration中,返回包含Configuration的DefaultSqlSession;
注意:MappedStatement:代表一个增删改查的详细信息
2、获取sqlSession对象
返回一个DefaultSQlSession对象,包含Executor和Configuration;
这一步会创建Executor对象;
Executor(根据全局配置文件中的defaultExecutorType创建出对应的Executor)
3、获取接口的代理对象(MapperProxy)
DefaultSqlSession.getMapper():拿到Mapper接口对应的MapperProxy;
使用MapperProxyFactory创建一个MapperProxy的代理对象
代理对象里面包含了,DefaultSqlSession(Executor)
4、执行增删改查方法

1)调用DefaultSqlSession的增删改查(Executor);
2)会创建一个StatementHandler对象。
(同时也会创建出ParameterHandler和ResultSetHandler)
3)调用StatementHandler预编译参数以及设置参数值;
使用ParameterHandler来给sql设置参数
4)调用StatementHandler的增删改查方法;
5)ResultSetHandler封装结果

在这里插入图片描述
六.简单加强和一下使用小技巧:
(获取自动生成的主键,typeAlias,提取properties,ResultMap,使用Mapper接口,SqlSessionFactory)
详细介绍见我之前的一篇文章
mybatis简单加强

七.MyBatis的动态SQL
mybatis使用之动态sql(if,where,foreach,set,trim,choose, when, otherwise)的使用
在这里插入图片描述
详细介绍见我之前的一篇文章:
mybatis使用之动态sql

八.IDEA插件Free Mybatis plugin的使用
详细介绍见我之前的一篇文章:
free mybatis plugin 使用

九.使用@Param注解来实现多个参数的问题

  User checkLogin(@Param("name") String name,@Param("password") String password);

原理:MyBatis会将使用@Param标注的参数封装到一个Map集合中
@Param中指定的名称设置为map的key
真实参数的值设置为map的value
注意:在mapper中使用#{}获取参数的时候,是从传递进来的参数(普通类型的:String/自定的对象:User)中取值, 如果是一个自定的对象,那么要从该对象中取出对应的属性的值,那么使用 . 取值

十.MyBatis的对象关系映射细节:

(1).对象之间的关联关系
对象之间的关系(写少量代码):
关联关系:A对象依赖B对象,并且把B对象作为A对象的一个属性,则A和B是依赖关系.
按照多重性分:
1).一对一:一个A对象属于一个B对象,一个B对象属于一个A对象.
QQ和QQ空间
2).一对多:一个A对象包含多个B对象.
3).多对一:多个A对象属于一个B对象,并且每个A对象只能属于一个B对象.(90%)
4).多对多:一个A对象属于多个B对象,一个B对象属于多个A对象.
按照导航性分:如果通过A对象中的某一个属性可以访问该属性对应的B对象,则说A可以导航到B.
1).单向:只能从A通过属性导航到B,B不能导航到A.
2).双向:A可以通过属性导航到B,B也可以通过属性导航到A.
判断方法:
1,判断都是从对象的实例上面来看的;
2,判断关系必须确定一对属性;
3,判断关系必须确定具体需求;

(2).单向many2one
在这里插入图片描述
多对一的保存操作:
SQL语句:
insert into department(name) values(?)
insert into employee(name,dept_id) values(?,?)

注意:多对一的操作中,必须先保存one方,再保存many方
mybatis执行的所有的SQL,都是我们程序员去手动的让他发送的,
所以在查询多方的时候,不会自动的去查询one方的数据
只有我们去告诉他,他才发送
根据多方查询one方的SQL:select * from department where id = ?(参数应该是many方的dept_id)
1.发送额外sql的方式去查询one方数据
在这里插入图片描述
这里涉及到延迟加载的问题:
在执行多对一的查询操作的时候,往往不需要去查询到所有的关联的对象
在查询到员工对象的时候,可能就不需要去获取到对应的部门信息,但是,现在我们每次查询员工的时候,都会发送SQL去数据库中查询部门信息

解决方案:使用延迟加载
当我不需要查询到对应的关联对象的时候,就不要去发送SQL去数据库中查询

通过修改主配置中的配置:
这些是极其重要的调整, 它们会修改 MyBatis 在运行时的行为方式
在这里插入图片描述
2.默认情况下,在访问主对象的任何属性的时候,都会将所有的关联对象查询出来
此时将aggressiveLazyLoading值修改为false

3.默认情况下,调用Object对象中的equals,clone,hashCode,toString方法时候,都会出发延迟加载
通常情况下,是不要这样去出发延迟加载

注意:在MyBatis中,访问了one方的任何属性(无论是否是主键:Hibernate不会)都会触发延迟加载
在这里插入图片描述
(2).解决N+1问题:
当在查询所有的员工的时候,再获取员工对应的部门信息,此时就会发送多条SQL去数据库中查询关联的对象
比如:有10员工,每个员工的部门都不一样,那么此时会发送10+1条SQL

解决思路:此时在需求中我们是要关心主对象中的关联的对象, 所以最好在一次查询中将所有的信息查询出来

查询出所有的员工信息以及其所在部门的信息
SQL:
select e.id,e.name,d.id as did,d.name as dname
from employee e left join department d
on e.dept_id=d.id

如何将数据封装到对象中?
将e.id和e.name封装到一个Employee对象中
将d.id和d.name封装到一个Department对象中

解决方案:使用内联查询的方式
在这里插入图片描述
在这里插入图片描述
(3).session的一级缓存
在mybatis中,如果查询相同的数据,会每次将数据放到一个缓存中,然后,后面的查询直接从缓存去取数据(如果有,就直接使用,反之,就发送SQL去数据库中查询)

一级缓存:
生命周期:和SQLSession一致,一个SQLSession,一个一级缓存
在这里插入图片描述
注意:一级缓存的缓存能力有限,只能在一次会话中生效

(4).one2many
在这里插入图片描述

保存操作:
员工insert into employee(name) values(?)insert into employee(name) values(?)
部门insert into department(name) values(?)在发送一条SQL去更新员工信息,将部门编号更新到员工表中
update employee set dept_id=? where id=?
update employee set dept_id=? where id=?查询操作:查询部门:select * from dept where id = ?如果要想得到部门中的员工方式一:发送额外的SQL去数据库中查询select * from employee where dept_id = ?方式二:使用内联查询的方式

需要发送一条sql去更新双方之间的关系,否则,在many方是不会有one方的数据,也就是外键列需要手动去更新数据
在这里插入图片描述
在这里插入图片描述
(5).删除操作:
删除操作:在多表环境中,需要考虑外键的问题
在删除one方的时候,不能随便删除,因为one方的数据可能会被关联

如果非得删除被关联的数据,如何实现???
解决的思路:让被关联的数据不再被关联
解决方案:
1.先将关联它的数据删除(软删除,通过设置一个属性),再删除当前的数据
2.将外键列的数据设置为null,打破两者之间的关系
在这里插入图片描述


http://chatgpt.dhexx.cn/article/DEWgZUFw.shtml

相关文章

数据持久层框架Mybatis

目录 1.软件开发3层架构 2.什么是框架? 3.传统JDBC开发的不足? 4.什么是Mybatis? 5.Mybatis入门案例? 6.Mybatis增删改查案例? 7.Mybatis代理实现DAO开发? 8.Mybatis高级映射 1.软件开发3层架构 软…

常见持久层框架赏析,到底是什么让你选择 MyBatis?

在绝大多数在线应用场景中,数据是存储在关系型数据库中的,当然,有特殊要求的场景中,我们也会将其他持久化存储(如 ElasticSearch、HBase、MongoDB 等)作为辅助存储。但不可否认的是,关系型数据库…

Java持久层框架

一、ORM框架 ORM:对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换 。从效果上说,它其实是创建了一…

17-Spring持久层框架整合

上一篇:16-Spring 基于注解的AOP编程、AOP总结https://blog.csdn.net/fsjwin/article/details/109482768 1.为什么Spring要与持久层框架进行整合 spring是一个优秀的框架,他的优秀支持就是能整合所有程序员想要让他整合的框架,这里所说的持…

MyBatis持久层框架

文章目录 一、Maven搭建1、本地maven仓库以及本地依赖2、idea搭建maven环境3、配置Product实体类4、配置Product接口5、配置db.properties文件6、配置SqlMapperConfig.xml文件7、配置ProductMapper.xml8、配置测试类9、运行 一、Maven搭建 1、本地maven仓库以及本地依赖 2、id…

Java数据持久层框架

一、前言 1.持久层 Java数据持久层,其本身是为了实现与数据源进行数据交互的存在,其目的是通过分层架构风格,进行应用&数据的解耦。 我从整体角度,依次阐述JDBC、Mybatis、MybatisPlus。 前者总是后者的依赖。只有在了解前…

三大框架 —— 持久层框架MyBatis

持久层框架MyBatis 1. mybatis介绍2. 执行流程3. 使用步骤代码实现举例:商品分类CRUD操作 4. 关联关系4.1 一对一4.2 一对多 5. 参数占位符6. 复杂搜索6.1 动态SQL语句6.2 集合参数 1. mybatis介绍 传统框架的缺点: 使用jdbc需要程序员创建连接&#xff…

持久层框架(Mybatis)

持久层框架 工具和框架 工具: JDBC -> DbUtils(QueyRunner) -> JdbcTemplate: 功能简单,SQL语句编写在Java代码中,这是硬编码,高耦合。 框架: 框架是整体解决方案。 如何进行事务控制,如何实现查询缓…

【Java必学框架】一文搞懂Java持久层框架Mybatis,由浅入深

文章目录 一.简介二.快速入门三.映射文件配置详解1.基本增删改查标签、属性2.动态sql2.1\标签2.2\标签 四.核心配置文件1.核心配置文件标签层级关系及作用2.配置示例3.事务管理器4.数据源5.Mapper标签6.自定义类型转换器7.插件机制 五.相应API1.工具对象2.openSession方法3.Sql…

python怎么输入根号

今天我们来说一说Python中如何实现对一个数字开平方。有三种解决办法、 下面我们分别来演示Python中数字开平方的三种方法 第一种方法:使用math模块,使用之前需要先调用,如下 第二种方法:使用内置函数pow(),如下 第三种方法:使用数…

Python-开根号的几种方式

文章目录 前言方法一方法二方法三 前言 使用Python中的自带库math、自带函数pow和自带库cmath来对数字进行开根号运算 方法一 使用:math.sqrt(数字) import math n int(input(数字:)) x math.sqrt(n) print(x) print(type(x)) #开根号后的类型为float方法二 使用&…

chatgpt赋能python:Python开根号:从入门到精通

Python开根号: 从入门到精通 Python是一种通用的高级编程语言,被广泛应用于数据、人工智能、网络应用、图像处理等多个领域。其中,数学计算是使用Python的常见场景之一,而在数学计算中,常常需要对数值进行开根号运算。…

求解任意正整数n开根号的值,不用函数求解√2(根号二),二分法求根号,定义函数fun()求根号,二分法查找

求解任意正整数n开根号的值 提示&#xff1a;理解二分法、函数调用 定义函数double fun(int n)实现 #include<bits/stdc.h> //万能函数头文件 using namespace std; double fun(int n); //定义一个求解根号的函数声明 int main() { int n;cout<<"输入想…

C语言根号作用,c语言中如何开根号运算

用math.h里封装好的函数&#xff0c;具体如下&#xff1a; 求平方根&#xff1a;double sqrt(double x) 例&#xff1a; #include #include int main(void) { double x 4.0, result; result sqrt(x); printf("The square root of %lf is %lf ", x, result); retu…

JavaScript中的乘方和开根号的使用方法

1、乘方 <script>var ikun Math.pow(4,3);console.log(ikun); </script> 2、开根号 <script>var ikun Math.sqrt(64);console.log(ikun); </script> 我们在开根号后还可以再次开根号 <script>var ikun Math.sqrt( Math.sqrt(81));console.…

python三种方法开根号(穷举法、二分法、牛顿拉夫逊法)

文章目录 方法一&#xff1a;穷举法方法二&#xff1a;二分法方法三&#xff1a;牛顿-拉夫逊算法总结 方法一&#xff1a;穷举法 positive_num int(input("输入一个正数:")) #无穷逼近法 answer0 #正数的根号结果 numGuess0 #循环次数 epsilon0.01 …

计算机开根号原理,根号的原理_怎么开的根号,有原理吗

怎么开的根号,有原理吗 JPG&#xff0c;526x296&#xff0c;128KB&#xff0c;444_250 怎么在数轴上画出根号3,求详细过程和原理 JPG&#xff0c;600x293&#xff0c;231KB&#xff0c;514_250 求根号 X 2 2 9 根号 X 3 2 4 的最小值 JPG&#xff0c;598x800&#xff0c;128KB&…

python中根号怎么输入_python中根号怎么表示

sqrt() 方法返回数字x的平方根。 以下是 sqrt() 方法的语法:&#xff08;推荐学习&#xff1a;Python视频教程&#xff09;import math math.sqrt( x ) 注意&#xff1a;sqrt()是不能直接访问的&#xff0c;需要导入 math 模块&#xff0c;通过静态对象调用该方法。 参数 x…

java 开三次根号_java里实现开根号

java里实现开根号 [2021-02-03 08:57:13] 简介: php去除nbsp的方法:首先创建一个PHP代码示例文件;然后通过“preg_replace("/(\s|\&nbsp\;| |\xc2\xa0)/", " ", strip_tags($val));”方法去除所有nbsp即可。推荐:《PHP视频教 excel中开根号的函数…

开根号的笔算算法图解_一个数的开根号怎么计算

一个数的开根号怎么计算2020-11-08 15:46:47文/钟诗贺 带根号的式子可以直接进行开平方的运算。一些特殊的根号运算有;√2≈1.414、1/2-√3≈0.5-1.732≈-1.232、2√5≈22.236≈4.236、√7-√6≈2.646-2.449≈0.197。 开平方的笔算方法 1&#xff0e;将被开方数的整数部分从个位…