前言

前几篇篇我们简单讲解了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只有两个实现类:DefaultSqlSessionFactorySqlSessionManager

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也是一个接口,有两个实现类:DefaultSqlSessionSqlSessionManager

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的更多相关文章

  1. MyBatis的2个核心对象:SqlSessionFactory、SqlSession

    SqlSessionFactory SqlSessionFactory是单个数据库映射关系经过编译后的内存镜像,主要作用是创建SqlSession. InputStream inputStream = ...

  2. spring两大核心对象IOC和AOP(新手理解)

    现在自己对spring的理解是:spring的主要的作用是用来进行业务的处理和实现类与类之间的解耦. 其中实现解耦功能 是IOC(控制反转)通过sessionfactory工厂来为需要的对象注入对应的 ...

  3. Ajax系列之二:核心对象XMLHttpRquest

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/zhanghongjie0302/article/details/31432939           ...

  4. Git-第一篇认识git,核心对象,常用命令

    1.git一般使用流程 4大核心对象:工作区.暂存区.本地库.远端库. 2.常用命令 1>git init:初始化本地仓库 2>git clone:克隆仓库到指定地方 3>git a ...

  5. Mybatis 系列9-强大的动态sql 语句

    [Mybatis 系列10-结合源码解析mybatis 执行流程] [Mybatis 系列9-强大的动态sql 语句] [Mybatis 系列8-结合源码解析select.resultMap的用法] ...

  6. Mybatis 系列7-结合源码解析核心CRUD 配置及用法

    [Mybatis 系列10-结合源码解析mybatis 执行流程] [Mybatis 系列9-强大的动态sql 语句] [Mybatis 系列8-结合源码解析select.resultMap的用法] ...

  7. Mybatis系列全解(八):Mybatis的9大动态SQL标签你知道几个?提前致女神!

    封面:洛小汐 作者:潘潘 2021年,仰望天空,脚踏实地. 这算是春节后首篇 Mybatis 文了~ 跨了个年感觉写了有半个世纪 ... 借着女神节 ヾ(◍°∇°◍)ノ゙ 提前祝男神女神们越靓越富越嗨 ...

  8. 深入详解Mybatis的架构原理与6大核心流程

    MyBatis 是 Java 生态中非常著名的一款 ORM 框架,目前在一线互联网大厂中应用广泛,Mybatis已经成为了一个必会框架. 如果你想要进入一线大厂,能够熟练使用 MyBatis 开发已经 ...

  9. Mybatis的基本要素--核心对象

    大家好啊,今天呢来说下Mybatis的核心对象,也就是说基本三要素. >核心接口和类. >Mybatis核心配置文件(mybatis-config.xml) >SQL映射文件 一.下 ...

随机推荐

  1. C语言:printf标志符

    %d 十进制整数 %i %lf双精度浮点数 %o八进制整数  0%o或0%O %x十六进制整数  0x%x 或  0X%X %f单精度浮点数 %E  %e科学计数法 %s  字符串 %c  字符(单个 ...

  2. PYTHON找色不变移动

    import cv2 import aircv as ac import numpy as np def wmhd(sjh): bzz0=0 bzz1=0 bzz2=0 xxa=0 yya=0 xxb ...

  3. if函数+isna函数+vlookup函数实现不同列相同单元格内容排列在同一行

    1,首先学习的网址:https://jingyan.baidu.com/album/22a299b5dd0f959e19376a22.html?picindex=1 2,excel 这也许是史上最好最 ...

  4. .NET6 preview is coming

    快速升级.NET 6.0 本文发布文章,只是证明,从5.0到6.0还是那么简单.其实官网永远是最好的老师,你可以直接看官网: https://docs.microsoft.com/zh-cn/aspn ...

  5. springboot-3-web开发

    一.视图层技术thymeleaf 我们一般都是基于3.x版本 1.流程: 导入依赖 <!--整合thymeleaf技术--> <dependency> <groupId& ...

  6. .net 5+ 知新:【1】 .Net 5 基本概念和开发环境搭建

    最近一两年搞了很多其它事情,.net web方面的基本没做,之前做过几个小的项目零星的学习了些,从.net core 发布后其实都没正真的系统学习过. 就是上手做项目,平时也有关注和看些资料,所以项目 ...

  7. P5042 丢失的题面

    P5042 丢失的题面 顺序:10 - 1 - 7 - 8 - 9 - 4 - 5 - 6 - 2 - 3 Point 10 读入,特判,输出. 读入的英文意思是让选手输出自己的程序本身,这个题的确存 ...

  8. python里面的MD5加密 ---# hashlib包的使用

    在应用程序的接口里,常用到签名:其中签名里用到MD5加密,这里用hashlib实现 hashlib 概念:Hash,译做"散列",也有直接音译为"哈希"的.把任 ...

  9. 流畅的python-2

    一.python数据结构  ----------------> ()      []          {} List 列表[] 可变的 lst = [1,2,3,4] #改 lst[(元素下标 ...

  10. iTextSharp导出PDF模板(报告)

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.IO;us ...