myBatis源码学习之SqlSessionFactory

myBatis源码学习之SqlSessionFactory/***Createsan{@linkSqlSesion}outofaconnectionoraDataSource**@authorClintonBegin*///SqlSessionFactory接口,通过openSession方法获得SQLSessionpublicinterfaceSqlSessionFactory{SqlS

大家好,又见面了,我是你们的朋友全栈君。

上一篇博客 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.
      }
    }
  }

}

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/143945.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • elasticsearch集群搭建_Linux如何关闭kafka集群

    elasticsearch集群搭建_Linux如何关闭kafka集群安装包自己自行准备,或者用我百度网盘的安装包,ElasticSearchLogstashKibanaFileBeat:**链接:**https://pan.baidu.com/s/1_Iv2R8pmYaHkoaOk_m8OuQ提取码:5ezt复制这段内容:后打开百度网盘手机App,操作更方便哦创建普通用户ES不能使用root用户来启动,必须使用普通用户来安装启动。这里我们创建一个普通用户以及定义一些常规目录用于存放我们的数据文件以及安装包等。创建一个es专门的用户(必须)使

    2022年10月13日
    2
  • 图标变成了一张白纸_win10桌面图标变白纸

    图标变成了一张白纸_win10桌面图标变白纸win+R输入ie4uinit-show

    2022年10月19日
    4
  • navicat premium mac 激活码【2021.10最新】「建议收藏」

    (navicat premium mac 激活码)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html2JTX0APX6F-eyJsaWNlbnNlSWQi…

    2022年3月30日
    1.2K
  • ccd视觉定位教程_正规CCD视觉定位系统工作原理[通俗易懂]

    ccd视觉定位教程_正规CCD视觉定位系统工作原理[通俗易懂]产品品牌CCD视觉定位系统发货城市-有效期至长期有效最小起订1产品单价面议深圳精科视觉科技有限公司成立于2011年底,是一家在视觉及自动化领域有着多年经验的科技公司,专业从事非标自动化机器视觉整套解决方案。公司集研发、销售、维护为一体,汇聚了一批追求卓越、勇于探索、敢于创新、在行业内具有丰富经验的工程技术人员,组建了一支专业、敬业的市场营销团队。激光打标技术具有以下的特点1、可对绝大多数金属或非金…

    2022年6月16日
    53
  • mtk-keypad[通俗易懂]

    mtk-keypad[通俗易懂]一.keypad基本原理col作为输出,row作为输入检测,低电平有效colA~D轮流输出低电平,通过rol1~4上的低电平可以检测是哪个按键按下了但是存在这样的问题,A1,A2,B1同时按下,会造成B2按下的假象,称为鬼影(这3个键导通,colB打开,row2处也会检测到低电平)可以通过增加二极管的方式防止鬼影问题二.keypadporti…

    2022年5月4日
    65
  • 解决8080端口被占用问题「建议收藏」

    解决8080端口被占用问题「建议收藏」问题叙述在IDEA中运行项目时会出现8080端口被占用的情况,可能是运行tomcat的时候,也可能是在用vue进行前后端分离项目,运行后端代码时出现端口被占用。这里以运行tomcat显示占用举例,如下图所示;解决方法1、按快捷键windows+R,在运行框里输入cmd,如图所示,2、在dos命令中输入netstat-aon|findstr“8080”,查看端口。3、找到8080端口,查看正在运行程序的pid,如图所示。4、回到桌面,任务栏,右键,任务管理器,如图所示会显示正在运行的

    2025年6月24日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号