上一篇博客 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的更多相关文章

  1. mybatis源码学习(一) 原生mybatis源码学习

    最近这一周,主要在学习mybatis相关的源码,所以记录一下吧,算是一点学习心得 个人觉得,mybatis的源码,大致可以分为两部分,一是原生的mybatis,二是和spring整合之后的mybati ...

  2. mybatis源码学习:一级缓存和二级缓存分析

    目录 零.一级缓存和二级缓存的流程 一级缓存总结 二级缓存总结 一.缓存接口Cache及其实现类 二.cache标签解析源码 三.CacheKey缓存项的key 四.二级缓存TransactionCa ...

  3. mybatis源码学习:基于动态代理实现查询全过程

    前文传送门: mybatis源码学习:从SqlSessionFactory到代理对象的生成 mybatis源码学习:一级缓存和二级缓存分析 下面这条语句,将会调用代理对象的方法,并执行查询过程,我们一 ...

  4. mybatis源码学习:插件定义+执行流程责任链

    目录 一.自定义插件流程 二.测试插件 三.源码分析 1.inteceptor在Configuration中的注册 2.基于责任链的设计模式 3.基于动态代理的plugin 4.拦截方法的interc ...

  5. Mybatis源码学习第六天(核心流程分析)之Executor分析

    今Executor这个类,Mybatis虽然表面是SqlSession做的增删改查,其实底层统一调用的是Executor这个接口 在这里贴一下Mybatis查询体系结构图 Executor组件分析 E ...

  6. Mybatis源码学习之整体架构(一)

    简述 关于ORM的定义,我们引用了一下百度百科给出的定义,总体来说ORM就是提供给开发人员API,方便操作关系型数据库的,封装了对数据库操作的过程,同时提供对象与数据之间的映射功能,解放了开发人员对访 ...

  7. mybatis源码分析(1)——SqlSessionFactory实例的产生过程

    在使用mybatis框架时,第一步就需要产生SqlSessionFactory类的实例(相当于是产生连接池),通过调用SqlSessionFactoryBuilder类的实例的build方法来完成.下 ...

  8. Spring mybatis源码学习指引目录

    前言: 分析了很多方面的mybatis的源码以及与spring结合的源码,但是难免出现错综的现象,为了使源码陶冶更为有序化.清晰化,特作此随笔归纳下分析过的内容.博主也为mybatis官方提供过pul ...

  9. mybatis源码学习(三)-一级缓存二级缓存

    本文主要是个人学习mybatis缓存的学习笔记,主要有以下几个知识点 1.一级缓存配置信息 2.一级缓存源码学习笔记 3.二级缓存配置信息 4.二级缓存源码 5.一级缓存.二级缓存总结 1.一级缓存配 ...

随机推荐

  1. Java线程状态

    线程跟人类一样拥有自己的生命周期,一条线程从创建到执行完毕的过程即是线程的生命周期,此过程可能在不同时刻处于不同的状态,线程状态正是这小节的主题,线程到底有多少种状态?不同状态之间是如何转化的? 对于 ...

  2. Java: How to resolve Access Restriction error

    Issue: Access restriction: The constructor 'BASE64Decoder()' is not API (restriction on required lib ...

  3. 指令汇B新闻客户端开发(六) 浅谈屏幕适配解决方案

    屏幕适配的问题,我相信很多大牛的经验远比我丰富,在此就简单的分享一下我所做的的屏幕适配方案,当然我说的是安卓方面的啦,嘿嘿,屏幕适配我们一般用1280*720的屏幕作为我们的主流开发屏,当然现在And ...

  4. GDAL 2.0版本RPC校正速度测试

    GDAL2.0版本的更新日志中提到了对RPC校正的优化,今天测试了一下,发现提升的速度还是蛮快的,测试的数据是一个IRS-P5的数据. 单线程测试 首先使用一个线程进行测试,使用下面的批处理进行运行, ...

  5. 2.1、Android Studio通过Lint提升你的代码

    为了测试你的Android应用符合功能需求.最重要的是确保你的代码没有结构性问题.结构差的代码影响你的Android应用的可靠性,让你的代码难以维护.比如,如果你的XML资源文件包含未使用的明明空间, ...

  6. SYBASE bcp用法及例子

    BCP是SYBASE公司提供专门用于数据库表一级数据备份的工具. 语法: 语法如下:(可用 bcp – 得到) 常用参数说明: -b batch_size 指定所复制的每批数据中的行数.每个批处理作为 ...

  7. 无刷新更新listview

    闲来无事,写点水文吧!有用得着的可以参考下,无刷新更新listview是什么意思呢?举个例子,在订单类listview列表中,常常会有各种订单状态,拿商城类app来说,会有待付款,待收货,确认收货等等 ...

  8. struts extjs 3.3.1 读取JSON文件

    json文件和脚本代码: jsonSrc/jsonTxt1.json, { "personInfoList": [ { "id": 0, "name& ...

  9. 后端分布式系列:分布式存储-HDFS 与 GFS 的设计差异

    「后端分布式系列」前面关于 HDFS 的一些文章介绍了它的整体架构和一些关键部件的设计实现要点. 我们知道 HDFS 最早是根据 GFS(Google File System)的论文概念模型来设计实现 ...

  10. Cocos2D iOS之旅:如何写一个敲地鼠游戏(十一):完善游戏逻辑

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...