Mybatis精讲(二)---生命周期
回顾
上一章节我们通过xml和代码的方式实现了Mybatis环境的配置。代码方式只是简单介绍下。我们也知道我们大部分情况使用的是xml方式的配置。在实际开发中我们那样开发显然是不合理的。
上章节提到的组件显示不可能每次执行sql都要重新创建的。这样性能上肯定是过不去的。今天我们就来简单聊聊SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession、Mapper这些组件的生命周期吧。
SqlSessionFactoryBuilder
- 通过观察分析这个类我们就知道既然是Builder模式的类,那他的作用就是构建起(孵化器).换句话说这个类不是那么的重要,因为他唯一的作用就是孵化SqlSessionFactory。在Spring与Mybatis整合的框架中,我相信Spring一定是在构建了SqlSessionFactory之后就将这个类进行回收了。因为后面就不需要了。这里纯属个人猜想。
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
- 上面就是我们通过加载xml配置文件的源码。我们不难发现build核心是通过XMLConfigBuilder这个类去负责解析mybatis-config.xml配置文件并生成Configuration对象。
SqlSessionFactory
- 看名字就知道是工厂模式。在这里我们可以把他看成数据库连接池。既然是工厂就肯定得有产品。SqlSessionFactory的产物就是SqlSession。SqlSession是与数据库的一次连接。管理数据库的连接的自然就是连接池了。
- Mybatis中使用的SqlSessionFactory是
DefaultSqlSessionFactory
。 以连接池的角度看待我们不难推断出SqlSessionFactory应该是个单例 。SqlSessionFactory对应的是数据库。一个数据库原则上应该对应一个SqlSessionFactory来管理。这点在Spring中正好无缝连接。把SqlSessionFactory交由spring管理。spring默认是单例模式bean.
openSessionFromDataSource
- SqlSessionFactory通过openSession方法获取SqlSession.SQLSession实际上可以看做是一次数据库的连接。下面我们通过源码的方式去看看工厂是如何生产SqlSession的。
<!--定义数据库信息,默认使用development数据库构建环境-->
<environments default="development">
<environment id="development">
<!--jdbc事物管理-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据库连接信息-->
<dataSource type="POOLED">
<property name="driver" value="${database.driver}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</dataSource>
</environment>
</environments>
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
//定义一个事物对象
Transaction tx = null;
try {
//通过配置对象获取事先配置好的环境对象 这里对应了xml中的environments标签 。environments默认develop.所以是develop的environment
final Environment environment = configuration.getEnvironment();
//通过环境获取事物。在environment里配置了JDBC类型的事物==JdbcTransactionFactory;如果没有配置则默认采用ManagedTransactionFactory
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
//构建事物对象 , 实际就是属性的赋值
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
//获取执行器 BatchExecutor、ReuseExecutor、SimpleExecutor , 选择SimpleExecutor
//因为默认有缓存,这里会用CachingExecutor包裹原始Executor , 之后会加载各种插件
final Executor executor = configuration.newExecutor(tx, execType);
//返回DefaultSqlSession。写死
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
Executor
- Mybatis的数据库执行器。Mybatis提供了一共四中Executor.这里严格意义上应该说是三种 BatchExecutor、ReuseExecutor、SimpleExecutor。还有一个CachingExecutor。这里为什么不把他算上了。因为这个是一个全局的开关。在settings标签的cacheEnabled设置的。说道这个标签大家都知道这个就是二级缓存的开关。所以这里CachingExecutor就不做介绍了。
- SimpleExecutor是一种常规执行器,每次执行都会创建一个statement,用完后关闭。
- ReuseExecutor是可重用执行器,将statement存入map中,操作map中的statement而不会重复创建statement。
- BatchExecutor是批处理型执行器,doUpdate预处理存储过程或批处理操作,doQuery提交并执行过程。
- 关于Executor的选取也是在settings标签控制的。defaultExecutorType。 默认是simple
SqlSession
- 每个线程都有一个属于自己的Sqlsession对象。这里我们看成是一次Connection。他的生命周期应该是一次完成的事物处理过程。他是一个线程不安全的对象。在多线程操作的时候我们需要注意事物的隔离级别。我们操作时需要注意的是每次处理玩需要将他关闭。否则会造成资源浪费。在Mybaits中已经通过finnally把我们将他释放了。
Mapper
- Mapper是一个接口,我们可以将xml看成他的一个实现类。这里的实现类虚化。通过Java代码的调用实际将xml对应的sql发送给数据库并获取数据结果。
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
- 通过上述代码我们能够发现。在获取Mapper的时候先通过类型看是否被注册了。然后根据类别获取代理实例。
总结
- 关于生命周期其实没什么重点。这一章节也比较简单。我们只需要知道我们最终需要的Mapper。然后是如何从配置到获取Mapper.这过程中哪些是全局的。哪些又适合做成复用的。
# 加入战队
微信公众号
Mybatis精讲(二)---生命周期的更多相关文章
- 学习MyBatis必知必会(5)~了解myBatis的作用域和生命周期并抽取工具类MyBatisUtil、mybatis执行增删改查操作
一.了解myBatis的作用域和生命周期[错误的使用会导致非常严重的并发问题] (1)SqlSessionFactoryBuilder [ 作用:仅仅是用来创建SqlSessionFactory,作用 ...
- iOS开发——语法篇OC篇&高级语法精讲二
Objective高级语法精讲二 Objective-C是基于C语言加入了面向对象特性和消息转发机制的动态语言,这意味着它不仅需要一个编译器,还需要Runtime系统来动态创建类和对象,进行消息发送和 ...
- mybatis精讲(五)--映射器组件
目录 前言 标签 select insert|update|delete 参数 resultMap cache 自定义缓存 # 加入战队 微信公众号 前言 映射器之前我们已经提到了,是mybatis特 ...
- Spring之bean二生命周期
上一博客主要学习了下bean的配置.注入.自定义属性编辑器,今天来熟悉bean的生命周期.在开发中生命周期是一个很常见的名词,基本每种编程语言都能找到与它关联的.关于bean的生命周期我在网上也找了好 ...
- mybatis精讲(三)--标签及TypeHandler使用
目录 话引 XML配置标签 概览 properties 子标签property resource 程序注入 settings 别名 TypeHandler 自定义TypeHandler EnumTyp ...
- react基础学习 二——生命周期
生命周期mount: mounting装载创建 update更新 unmounting卸载 错误捕获 注意点:生命周期函数的 作用,什么之后用 只有类式组件有生命周期,函数式组件没有生命周期 moun ...
- react学习二 生命周期
转自:https://www.cnblogs.com/gdsblog/p/7348375.html react 中compent getDefaultProps object getDefaultPr ...
- VUE 学习笔记 二 生命周期
1.除了数据属性,Vue 实例还暴露了一些有用的实例属性与方法.它们都有前缀 $,以便与用户定义的属性区分开来 var data = { a: 1 } var vm = new Vue({ el: ' ...
- Spring注解驱动开发(二)-----生命周期、属性赋值
bean的生命周期 bean的生命周期:bean创建---初始化----销毁的过程容器管理bean的生命周期:我们可以自定义初始化和销毁方法:容器在bean进行到当前生命周期的时候来调用我们自定义的初 ...
随机推荐
- Hibernate HQL注入与防御(ctf实例)
遇到一个hql注入ctf题 这里总结下java中Hibernate HQL的注入问题. 0x01 关于HQL注入 Hibernate是一种ORM框架,用来映射与tables相关的类定义(代码) ...
- linux系统取证
目录 0x00 查看系统信息 0x01 用户及组信息 0x02 防火墙及路由信息 0x03 查看网络.端口信息 0x04 系统运行信息查看 0x05 日志查看分析 0x00 查看系统信息 name-a ...
- Hadoop(MapR)分布式安装及自动化脚本配置
MapR的分布式集群安装过程还是很艰难的,远远没有计划中的简单.本人总结安装配置,由于集群有很多机器,手动每台配置是很累的,编写了一个自动化配置脚本,下面以脚本为主线叙述(脚本并不完善,后续继续完善中 ...
- Flink 从 0 到 1 学习 —— 如何自定义 Data Source ?
前言 在 <从0到1学习Flink>-- Data Source 介绍 文章中,我给大家介绍了 Flink Data Source 以及简短的介绍了一下自定义 Data Source,这篇 ...
- 百万年薪python之路 -- 小数据池和代码块练习
1.请用代码验证 "alex" 是否在字典的值中? info = {'name':'王刚蛋','hobby':'铁锤','age':'18',...100个键值对} info = ...
- 使用 Django 项目中的 ORM 编写伪造测试数据脚本
作者:HelloGitHub-追梦人物 文中所涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 为了防止博客首页展示的文章过多以及提升加载速度,可以对文章列表进行分页展示.不过这需 ...
- Ubuntu 14.04 sudo免密码的方法| sudo不需要密码
Ubuntu 14.04 sudo免密码的方法| sudo不需要密码 cd /etc/sudoers.d sudo touch nopasswd4sudo sudo vi nopasswd4sudo ...
- linux下安装配置svn服务器
linux下安装配置svn服务器 1. svn服务器安装 将subversion-1.4.0.tar.gz和subversion-deps-1.4.0.tar.gz传到服务器. tar xfvz su ...
- MyBatis(4)-- 动态SQL
如果使用JDBC或者类似于Hibernate的其他框架,很多时候要根据需要去拼装SQL,这是一个麻烦的事情.因为某些查询需要许多条件.通常使用其他框架需要大量的Java代码进行判断,可读性比较差,而M ...
- unity 截屏总结
转载与https://www.cnblogs.com/MissLi/p/8005342.html 1.针对指定的相机进行截屏 此中方式要添加yield return waitfortheEndofFr ...