【MyBatis系列5】MyBatis4大核心对象SqlSessionFactoryBuiler,SqlSessionFactory,SqlSession,Mapper
前言
前几篇篇我们简单讲解了MyBatis的简单用法,以及一对一和一对多以及多对多的相关动态sql查询标签的使用,也提到了嵌套查询引发了N+1问题,以及延迟加载相关功能,本篇文章将会从MyBatis底层实现着手,来分析MyBatis的4大核心对象。
MyBatis四大核心对象
我们先来回忆一下上一篇文章中,利用MyBatis来完成一次数据库操作需要经过哪些步骤,如下图所示:
可以得出主要分为以下步骤:
- 1、加载配置文件
- 2、获取SqlSessionFactoryBuiler对象
- 3、通过SqlSessionFactoryBuiler和配置文件流来获取SqlSessionFactory对象
- 4、利用SqlSessionFactory对象来打开一个SqlSession
- 5、通过SqlSession来获得对应的Mapper对象
- 6、通过Mapper对象调用对应接口来查询数据库
从这些步骤我们可以看到,MyBatic完成一次数据库操作主要有4大核心对象:SqlSessionFactoryBuiler,SqlSessionFactory,SqlSession和Mapper。
SqlSessionFactoryBuiler
SqlSessionFactoryBuilder的唯一作用就是用来创建SqlSessionFactory,创建完成之后就不会用到它了,所以SqlSessionFactoryBuiler生命周期极短。
SqlSessionFactoryBuiler中提供了9个方法,返回的都是SqlSessionFactory对象。
SqlSessionFactoryBuiler内使用到了建造者模式
(2+1)方法分析
虽然说提供了9个方法,但是实际上我们可以看成(2+1)个方法。
请看下图,前面三个方法最终都调用了第4个方法,所以实际上就是一个方法
在看下面这个其实也是一回事,有三个方法最终也是调用了同一个方法:
所以这两个方法就对应了2+1方法中的2。
上面图中也可以看到,这2个方法在将配置文件解析成一个Java配置类Configuration之后,又同时调用了另一个方法build(Configuration config),而这个方法也没做什么事,就是把配置类传进去返回了一个DefaultSqlSessionFactory对象,这个对象就是SqlSessionFactory的实现类
所以说2+1中的1没什么好分析的,那么这个2其实就是支持了2种读取文件的方式,比如说我们获取一个SqlSessionFactory对象最常用的是通过如下方式:
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
但是其实我们同样可以采用下面的方式才获取SqlSessionFactory对象:
Reader reader = Resources.getResourceAsReader(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
这两个方法的唯一区别就是在这里,另外两个参数都是一样的。
String environment:
这个其实就是用来决定加载哪个环境的。下图就是我们一个mybatis文件,有定义了一个environment id,当我们需要支持多环数据源切换的时候可以定义多个id,然后根据不同环境传入不同id即可。
在这里插入图片描述Properties properties:上图中我们下面的dataSource内的属性没有直接输入,而是采用了${jdbc.driver}来配置,而这些属性的值我们可以单独维护在一个properties文件内。
[图片上传失败...(image-689cd-1604121808670)]然后代码中就可以这么改写:
Reader reader = Resources.getResourceAsReader(resource);
Properties properties = Resources.getResourceAsProperties("db.properties");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader,properties);
采用这种方式之后,mybatis-config.xml文件可以直接用${}来取值了。当然其实还有一种更简单的方式,那就是直接在mybatis-config.xml引入properties文件,这样就不用在代码中去解析properties文件了:
<properties resource="db.properties"></properties>
可能现在的很多人没用过这种properties文件,但是在我刚开始学习编程的时候这种方式还是很常见的。
build()方法的功能就是去读取XML文件,并将读取到的信息封装到Congiguration中,至于如何解析XML文件不是本文的重点,我们就不过多介绍了。
通过上面的分析我们也很容易的知道,既然提供了一个方法可以直接传入Congiguration来获取SqlSessionFactory对象,那么其实我们也可以不采用XML形式,转而直接通过Java代码的方式来直接构建Congiguration,然后直接获取SqlSessionFactory对象。如下:
Configuration congiguration = new Configuration();
congiguration.setDatabaseId("xxx");
congiguration.setCacheEnabled(false);
SqlSessionFactory sqlSessionFactory1 = new SqlSessionFactoryBuilder().build(congiguration);
当然,这种方式如果要修改的话每次都要改代码,会比较麻烦,而且看起来比较不直观,所以还是推荐使用xml方式来进行MyBatis的基础属性配置。
InputStream和Reader
Reader和InputStream都是Java中I/O库提供的两套读取文件方式。Reader用于读入16位字符,也就是Unicode 编码的字符;而 InputStream 用于读入ASCII字符和二进制数据。关于这个区别后面我会再单独拿出来总结一下Java中的输入输出流,感兴趣的可以关注我,留意我后面的博客。在这里就不展开叙述这两种方式,大家在这里需要知道的是这是两种不同的输入方式就可以了。
SqlSessionFactory
SqlSessionFactory是一个接口,默认的实现类,主要是用来生成SqlSession对象,而SqlSession对象是需要不断被创建的,所以SqlSessionFactory是全局都存在的,也没有必要重复创建,所以这是一个单例对象。
SqlSessionFactory看名字就可以很容易想到,用到的是工厂设计模式
SqlSessionFactory只有两个实现类:DefaultSqlSessionFactory和SqlSessionManager。
DefaultSqlSessionFactory
DefaultSqlSessionFactory是SqlSessionFactory默认的实现类,现在用的也基本上就是它。这个类提供了8个方法用来获取SqlSession对象。这个截图不太好截,为了方便对比,我把方法列举出来:
SqlSession openSession();
SqlSession openSession(boolean autoCommit);
SqlSession openSession(TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType,TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType);
SqlSession openSession(ExecutorType execType, boolean autoCommit);
SqlSession openSession(Connection connection);
SqlSession openSession(ExecutorType execType, Connection connection);
这8个方法中TransactionIsolationLevel和autoCommit都比较好理解,就是事务隔离级别和是否开启自动提交。
前面6个方法最终实际上调用了openSessionFromDataSource方法,而后面2个又是调用了openSessionFromConnection方法。
从上面的两个方法截图中很明显可以看到,这两个方法基本一样,唯一的区别是openSessionFromConnection方法是从Connection对象中获取当前会话是否需要开启自动提交。
Executor
MyBatis中最终去执行sql语句是通过Executor对象实现的,Executor只有三种类型:
SIMPLE, REUSE, BATCH。默认使用的是SIMPLE类型对应的SimpleExecutor执行器。SimpleExecutor表示普通的执行器,不会做任何处理。REUSE类型对应的是ReuseExecutor执行器,会复用预处理语句。BATCH类型对应的是BatchExecutor执行器,一般用来执行批量操作。
Executor是属于SqlSession的四大对象之一,后面会有一篇博客来专门分析,在这里我们暂时不深入展开。
SqlSessionManager
SqlSessionManager其实也不是什么新东西,只是同时把SqlSessionFactory和SqlSession的职责放到了一起,所以这个我们不过多的讨论。
[图片上传失败...(image-871850-1604121808671)]
SqlSession
SqlSession是用来操作xml文件中我们写好的sql语句,每次操作数据库我们都需要一个SqlSession对象,SqlSession是用来和数据库中的事务进行对接的,所以SqlSession里面是包含了事务隔离级别等信息的。
SqlSession实例是线程不安全的,故最佳的请求范围是请求(request)或者方法(method)。
SqlSession也是一个接口,有两个实现类:DefaultSqlSession和SqlSessionManager。
SqlSessionManager上面有提到,这里就不重复了,这里我们可以看一下这几个类的类图就会更清晰:
Mapper
Mapper是一个接口,没有任何实现类。主要作用就是用来映射Sql语句的接口,映射器的接口实例从SqlSession对象中获取,所以说Mapper实例作用域是和SqlSession相同或者更小。
Mapper实例的作用范围最好是保持在方法范围,否则会难以管理。
Mapper接口的名称要和对应sql语句的xml文件同名,Mapper接口中定义的方法名称对应了xml文件中的语句id。
四大对象生命周期
SqlSessionFactoryBuiler只需要在创建SqlSessionFactory对象的时候使用,创建完成之后即可被丢弃。SqlSessionFactory全局唯一,是一个单例对象,但是需要全局存在。SqlSession一般对应了一个request,Mapper一般控制在方法内。
对象 | 生命周期 |
---|---|
SqlSessionFactoryBuiler | 方法局部(Method)使用完成即可被丢弃 |
SqlSessionFactory | 应用级别(Application),全局存在,是一个单例对象 |
SqlSession | 请求或方法(Request/Method) |
Mapper | 方法(Method) |
总结
本文主要分析了MyBatis中的四大核心对象:SqlSessionFactoryBuiler,SqlSessionFactory,SqlSession,Mapper。并从源码的角度分析了四大对象的生成过程以及生命周期。
下一篇,将会分析SqlSession的执行流程,分析完之后就会了解到我们的参数以及结果集到底是如何实现映射的。
8人点赞
作者:刀哥说Java
链接:https://www.jianshu.com/p/a8e8a3c0ff36
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【MyBatis系列5】MyBatis4大核心对象SqlSessionFactoryBuiler,SqlSessionFactory,SqlSession,Mapper的更多相关文章
- MyBatis的2个核心对象:SqlSessionFactory、SqlSession
SqlSessionFactory SqlSessionFactory是单个数据库映射关系经过编译后的内存镜像,主要作用是创建SqlSession. InputStream inputStream = ...
- spring两大核心对象IOC和AOP(新手理解)
现在自己对spring的理解是:spring的主要的作用是用来进行业务的处理和实现类与类之间的解耦. 其中实现解耦功能 是IOC(控制反转)通过sessionfactory工厂来为需要的对象注入对应的 ...
- Ajax系列之二:核心对象XMLHttpRquest
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/zhanghongjie0302/article/details/31432939 ...
- Git-第一篇认识git,核心对象,常用命令
1.git一般使用流程 4大核心对象:工作区.暂存区.本地库.远端库. 2.常用命令 1>git init:初始化本地仓库 2>git clone:克隆仓库到指定地方 3>git a ...
- Mybatis 系列9-强大的动态sql 语句
[Mybatis 系列10-结合源码解析mybatis 执行流程] [Mybatis 系列9-强大的动态sql 语句] [Mybatis 系列8-结合源码解析select.resultMap的用法] ...
- Mybatis 系列7-结合源码解析核心CRUD 配置及用法
[Mybatis 系列10-结合源码解析mybatis 执行流程] [Mybatis 系列9-强大的动态sql 语句] [Mybatis 系列8-结合源码解析select.resultMap的用法] ...
- Mybatis系列全解(八):Mybatis的9大动态SQL标签你知道几个?提前致女神!
封面:洛小汐 作者:潘潘 2021年,仰望天空,脚踏实地. 这算是春节后首篇 Mybatis 文了~ 跨了个年感觉写了有半个世纪 ... 借着女神节 ヾ(◍°∇°◍)ノ゙ 提前祝男神女神们越靓越富越嗨 ...
- 深入详解Mybatis的架构原理与6大核心流程
MyBatis 是 Java 生态中非常著名的一款 ORM 框架,目前在一线互联网大厂中应用广泛,Mybatis已经成为了一个必会框架. 如果你想要进入一线大厂,能够熟练使用 MyBatis 开发已经 ...
- Mybatis的基本要素--核心对象
大家好啊,今天呢来说下Mybatis的核心对象,也就是说基本三要素. >核心接口和类. >Mybatis核心配置文件(mybatis-config.xml) >SQL映射文件 一.下 ...
随机推荐
- c++中的基本IO
引言 c++不直接处理输入和输出,而是通过标准库中的类型处理IO.IO的设备可以是文件.控制台.string.c++主要定义了三种IO类型,分别被包含在iostream.fstream.sstream ...
- Java多线程系列-基本概念
Java的线程基本用法 创建线程 创建线程的方法: 实现Runnable接口 首先我们查看Runnable接口的定义: package java.lang; @FunctionalInterface ...
- Java的代理模式
最近在学习Spring,关于Spring AOP的代理模式不是很了解,看了一篇博文就懂了. https://www.cnblogs.com/cenyu/p/6289209.html Java的三种代理 ...
- Pytest单元测试框架之setup/teardown模块示例操作
"""模块级(setup_module/teardown_module)开始于模块始末,全局的函数级(setup_function/teardown_function)只 ...
- python编程面试题
# 实现需求为 注册.登录.查看昵称的功能 # def userN(): # username = input("请输入账号: \n") # password = ...
- 【爬虫系列】0. 无内鬼,破解前端JS参数签名
PS:这是一个系列,坐等我慢慢填坑. PS:不太会直接能跑的代码,抛砖引玉. PS:那些我也不太熟练的就不搞了,包括(破滑块.验证码..) PS: 反编译搞Apk会有很长的几个文章,稍后慢慢更. 最近 ...
- Tarjan判断为什么不能把dfn写成low
Tarjan,我相信大多数人是这么写的: void tarjan(int x) { dfn[x]=low[x]=++cnt; st.push(x),vis[x]=1; for(int i=head[x ...
- [考试总结]noip模拟13
因为最近考试频繁,所以咕掉了好长时间... 淦,刚说完又来一场... 先咕了,等以后有时间再写.... 回来了... 首先看到这个题目们,感觉就不存好意... 然后开始开 \(T1\). 只能蒻蒻地按 ...
- Tree Widget -- 基本方法
Tree Widget这个空间类似于一种表格的形式,是一种树状结构 效果图: 第一步:打开designer.exe,拖动一个Tree Widget空间到主窗口上 第二步:双击Tree Widget,添 ...
- Maven国内仓库
由于国外的官方Maven仓库比较慢,所以寻找国内的代理仓库. 网上找了一些博客,内容都是一模一样,并且不贴代理官方的说明. 我在阿里云的Maven仓库找到了官方说明. 下面直接贴配置指南: 配置指南 ...