myBatis源码学习之SqlSessionFactory
上一篇博客 SqlSessionFactoryBuilder 中介绍了它的作用就是获得DefaultSqlSessionFactory
SqlSessionFactory是一个接口,其具体实现类是DefaultSqlSessionFactory,通过类名我们可以看到SqlSessionFactory是一个SqlSession工厂,用来生产SqlSession对象,SqlSession中有我们进行数据库操作的增删改查接口
SqlSessionFactory源码及注释:
/**
* Creates an {@link SqlSesion} out of a connection or a DataSource
*
* @author Clinton Begin
*/
//SqlSessionFactory接口,通过openSession方法获得SQLSession
public interface SqlSessionFactory {
SqlSession openSession();
SqlSession openSession(boolean autoCommit);
SqlSession openSession(Connection connection);
SqlSession openSession(TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType);
SqlSession openSession(ExecutorType execType, boolean autoCommit);
SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType, Connection connection);
Configuration getConfiguration();
}
DefaultSqlSessionFactory构造函数主要设置了一些属性包括是否支持事务,事务的类型及隔离等级和sql语句的执行类型等。
DefaultSqlSessionFactory设置的事务的管理主要有三种方式:
(1)使用JDBC的事务管理机制,就是利用java.sql.Connection对象完成对事务的提交
(2)使用MANAGED的事务管理机制,这种机制mybatis自身不会去实现事务管理,而是让程序的容器(JBOSS,WebLogic)来实现对事务的管理
(3)不支持任何事务
DefaultSqlSessionFactory设置的事务的隔离等级有5个:
(1)Connection.TRANSACTION_NONE表示不支持事务的常量
(2)Connection.TRANSACTION_READ_COMMITTED不可重复读和虚读可以发生
(3)Connection.TRANSACTION_READ_UNCOMMITTED表示可以发生脏读 (dirty read)、不可重复读和虚读 (phantom read) 的常量
(4)Connection.TRANSACTION_REPEATABLE_READ虚读可以发生
(5)Connection.TRANSACTION_SERIALIZABLE指示不可以发生脏读、不可重复读和虚读的常量
DefaultSqlSessionFactory设置的sql语句操作类型有以下4个(到了sql执行时具体分析):
(1)BatchExecutor用于执行批量sql操作
(2)ReuseExecutor会重用statement执行sql操作
(3)SimpleExecutor简单执行sql操作
(4)CachingExecutor 在查找数据库前先查找缓存,若没有找到的话调用delegate从数据库查询,并将查询结果存入缓存中。
DefaultSqlSessionFactory源码及注释:
/**
* @author Clinton Begin
*/
//实现了sqlSessionFactory,
public class DefaultSqlSessionFactory implements SqlSessionFactory {
private final Configuration configuration;
//传入配置文件生成的对象,配置文件中包含了mybatis的所有配置信息
public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
}
public SqlSession openSession() {
//executor类型是默认的simple
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
//autoCommit true为不支持事务,false为支持事务
public SqlSession openSession(boolean autoCommit) {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, autoCommit);
}
public SqlSession openSession(ExecutorType execType) {
return openSessionFromDataSource(execType, null, false);
}
// TransactionIsolationLevel 事务隔离等级,有5种,详见下面说明
public SqlSession openSession(TransactionIsolationLevel level) {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), level, false);
}
//执行类型,有4种,BatchExecutor、ReuseExecutor、SimpleExecutor和CachingExecutor
public SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level) {
return openSessionFromDataSource(execType, level, false);
}
public SqlSession openSession(ExecutorType execType, boolean autoCommit) {
return openSessionFromDataSource(execType, null, autoCommit);
}
public SqlSession openSession(Connection connection) {
return openSessionFromConnection(configuration.getDefaultExecutorType(), connection);
}
public SqlSession openSession(ExecutorType execType, Connection connection) {
return openSessionFromConnection(execType, connection);
}
public Configuration getConfiguration() {
return configuration;
}
//最终是获得一个sqlsession
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
//获得配置文件中的environment配置
final Environment environment = configuration.getEnvironment();
//事务工厂,通过xml配置文件中的transactionManager 元素配置的type来选择事务
//JDBC是直接全部使用JDBC的提交和回滚功能。它依靠使用链接的数据源来管理事务的作用域
//MANAGED这个类型什么都不做,它从不提交、回滚和关闭连接,而是让窗口来管理事务的全部生命周期
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
//TransactionIsolationLevel事务的隔离级别有5个
//Connection.TRANSACTION_NONE表示不支持事务的常量
//Connection.TRANSACTION_READ_COMMITTED不可重复读和虚读可以发生
//Connection.TRANSACTION_READ_UNCOMMITTED表示可以发生脏读 (dirty read)、不可重复读和虚读 (phantom read) 的常量
//Connection.TRANSACTION_REPEATABLE_READ虚读可以发生
//Connection.TRANSACTION_SERIALIZABLE指示不可以发生脏读、不可重复读和虚读的常量
//脏读:如果一个事务对数据进行了更新,但事务还没有提交,另一个事务就可以“看到”该事务没有提交的更新结果。这样造成的问题是,
//如果第一个事务回滚,那么第二个事务在此之前所“看到”的数据就是一笔脏数据。
//不可重复读:指同个事务在整个事务过程中对同一笔数据进行读取,每次读取结果都不同。如果事务1在事务2的更新操作之前读取一次数据,
//在事务2的更新操作之后再读取同一笔数据一次,两次结果是不同的。所以TRANSACTION_READ_COMMITTED是无法避免不可重复读和虚读。
//幻读:指同样一个查询在整个事务过程中多次执行后,查询所得的结果集是不一样的。幻读针对的是多笔记录。
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
//execType是sql操作类型
//BatchExecutor用于执行批量sql操作
//ReuseExecutor会重用statement执行sql操作
//SimpleExecutor简单执行sql操作
//CachingExecutor 在查找数据库前先查找缓存,若没有找到的话调用delegate从数据库查询,并将查询结果存入缓存中。
final Executor executor = configuration.newExecutor(tx, execType);
//返回SqlSession
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();
}
}
private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
try {
boolean autoCommit;
try {
autoCommit = connection.getAutoCommit();
} catch (SQLException e) {
// Failover to true, as most poor drivers
// or databases won't support transactions
autoCommit = true;
}
//获得配置文件中的environment配置
final Environment environment = configuration.getEnvironment();
//事务工厂,通过xml配置文件中的transactionManager 元素配置的type来选择事务
//JDBC是直接全部使用JDBC的提交和回滚功能。它依靠使用链接的数据源来管理事务的作用域
//MANAGED这个类型什么都不做,它从不提交、回滚和关闭连接,而是让窗口来管理事务的全部生命周期
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
final Transaction tx = transactionFactory.newTransaction(connection);
//execType是sql操作类型
//BatchExecutor用于执行批量sql操作
//ReuseExecutor会重用statement执行sql操作
//SimpleExecutor简单执行sql操作
//CachingExecutor 在查找数据库前先查找缓存,若没有找到的话调用delegate从数据库查询,并将查询结果存入缓存中。
final Executor executor = configuration.newExecutor(tx, execType);
//返回SqlSession
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
//事务工厂,mybatis对于事务的管理有两种形式,
//(1)使用JDBC的事务管理机制,就是利用java.sql.Connection对象完成对事务的提交
//(2)使用MANAGED的事务管理机制,这种机制mybatis自身不会去实现事务管理,而是让程序的容器(JBOSS,WebLogic)来实现对事务的管理
private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
if (environment == null || environment.getTransactionFactory() == null) {
//没有配置的话就使用manage形式
return new ManagedTransactionFactory();
}
return environment.getTransactionFactory();
}
private void closeTransaction(Transaction tx) {
if (tx != null) {
try {
tx.close();
} catch (SQLException ignore) {
// Intentionally ignore. Prefer previous error.
}
}
}
}
myBatis源码学习之SqlSessionFactory的更多相关文章
- mybatis源码学习(一) 原生mybatis源码学习
最近这一周,主要在学习mybatis相关的源码,所以记录一下吧,算是一点学习心得 个人觉得,mybatis的源码,大致可以分为两部分,一是原生的mybatis,二是和spring整合之后的mybati ...
- mybatis源码学习:一级缓存和二级缓存分析
目录 零.一级缓存和二级缓存的流程 一级缓存总结 二级缓存总结 一.缓存接口Cache及其实现类 二.cache标签解析源码 三.CacheKey缓存项的key 四.二级缓存TransactionCa ...
- mybatis源码学习:基于动态代理实现查询全过程
前文传送门: mybatis源码学习:从SqlSessionFactory到代理对象的生成 mybatis源码学习:一级缓存和二级缓存分析 下面这条语句,将会调用代理对象的方法,并执行查询过程,我们一 ...
- mybatis源码学习:插件定义+执行流程责任链
目录 一.自定义插件流程 二.测试插件 三.源码分析 1.inteceptor在Configuration中的注册 2.基于责任链的设计模式 3.基于动态代理的plugin 4.拦截方法的interc ...
- Mybatis源码学习第六天(核心流程分析)之Executor分析
今Executor这个类,Mybatis虽然表面是SqlSession做的增删改查,其实底层统一调用的是Executor这个接口 在这里贴一下Mybatis查询体系结构图 Executor组件分析 E ...
- Mybatis源码学习之整体架构(一)
简述 关于ORM的定义,我们引用了一下百度百科给出的定义,总体来说ORM就是提供给开发人员API,方便操作关系型数据库的,封装了对数据库操作的过程,同时提供对象与数据之间的映射功能,解放了开发人员对访 ...
- mybatis源码分析(1)——SqlSessionFactory实例的产生过程
在使用mybatis框架时,第一步就需要产生SqlSessionFactory类的实例(相当于是产生连接池),通过调用SqlSessionFactoryBuilder类的实例的build方法来完成.下 ...
- Spring mybatis源码学习指引目录
前言: 分析了很多方面的mybatis的源码以及与spring结合的源码,但是难免出现错综的现象,为了使源码陶冶更为有序化.清晰化,特作此随笔归纳下分析过的内容.博主也为mybatis官方提供过pul ...
- mybatis源码学习(三)-一级缓存二级缓存
本文主要是个人学习mybatis缓存的学习笔记,主要有以下几个知识点 1.一级缓存配置信息 2.一级缓存源码学习笔记 3.二级缓存配置信息 4.二级缓存源码 5.一级缓存.二级缓存总结 1.一级缓存配 ...
随机推荐
- Combiners和Partitioner编程
Combiners的作用: 每一个map可能会产生大量的输出,combiner的作用就是在map端对输出先做一次合并,以减少传输到reducer的数据量. combiner最基本是实现本地key的归并 ...
- Java提升篇之反射的原理
Java提升篇之反射的原理 1.构造方法的反射 import java.lang.reflect.Constructor; public class ReflectConstructor { publ ...
- socket系列之socket服务端与客户端如何通信
上面已经分别介绍了ServerSocket跟Socket的工作步骤,并且从应用层往系统底层剖析其运作原理,我们清楚了他们各自的一块,现在我们将把他们结合起来,看看他们是如何通信的,并详细讨论一下他们之 ...
- C/C++的mem函数和strcpy函数的区别和应用
mem系列函数是面试的时候常考的知识点,我们需要熟练掌握这三个函数的原理和代码实现,要能准确无误的写出代码. memcpy.memset和memset三个函数在使用过程中,均需包含以下头文件: //在 ...
- 1Nginx+fastdfs分布式文件存储
准备,将所需的软件传到服务器上,服务器的列表如下: fastdfs-nginx-module_v1.15.tar.gz FastDFS_v4.06.tar.gz libevent-2.0.21- ...
- iOS 南京互联网大会分享及个人见解 韩俊强的博客
首先分两大块: 1.如何打造高效/稳定的App (重点): 2.软件自动化测试: 每日更新关注:http://weibo.com/hanjunqiang 新浪微博! 每日更新关注:http://we ...
- UNIX网络编程——客户/服务器程序设计示范(六)
TCP并发服务器程序,每个客户一个线程 前面讲述了,每个客户一个进程的服务器,或为每个客户现场fork一个子进程,或者预先派生一定数目的子进程.如果服务器主机支持线程,我们就可以改用线程以取代子进程. ...
- [django]项目打包构建
django项目的结构大体上都是类似,打包主要的功能就是把一些不需要部署的文件剔除,把需要部署的文件直接压缩打包. 这里还想集成一个配置文件模板生成配置文件的过程,或者写一个配置文件生成的工具,不用每 ...
- (八十七)AutoLayout的简介与实例
AutoLayout是继AutoResizing之后的一种自动布局方法,解决了AutoResizing无法处理控件间相互关系的问题. AutoLayout在storyboard中通过底部工具条设置,底 ...
- iOS中发送短信/发送邮件的实现 韩俊强的博客
需要引入框架: MessageUI.framework 布局如下: 短信和邮件: #import "ViewController.h" #import <MessageUI/ ...