1.先看一个mybatis最简单的Demo

        String resource = "mybatis-config.xml";
//1.流形式读取mybatis配置文件
InputStream stream = Resources.getResourceAsStream(resource);
//2.通过配置文件创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(stream);
//3.通过SqlSessionFactory创建sqlSession
SqlSession session = sessionFactory.openSession();
//4.通过SqlSession执行Sql语句获取结果
List<User> userList = session.selectList("selectAll");
System.out.println(userList.size());

1.通过InputStream获取mybatis的配置文件

2.通过SqlSessionFactoryBuilder创建SqlSessionFactory

3.通过SqlSessionFactory创建一个SqlSession

4.通过SqlSession执行Sql语句并获取结果

那么接下来先来了解下SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession都是什么,是怎么工作的?

一、SqlSessionFactoryBuilder解析

由类名可知SqlSessionFactoryBuilder是SqlSessionFactory的构造类,而SqlSessionFactory又是SqlSession的工厂接口,SqlSession从字面意思可知是sql会话接口;

所以SqlSessionFactoryBuilder可定义为Sql会话工厂构造类,顾名思义此类的作用就是创建SqlSessionFactory用的

话不多说,代码写贴为敬

 package org.apache.ibatis.session;

 import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Properties;
import org.apache.ibatis.builder.xml.XMLConfigBuilder;
import org.apache.ibatis.exceptions.ExceptionFactory;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory; public class SqlSessionFactoryBuilder { //方法1
public SqlSessionFactory build(Reader reader) {
return build(reader, null, null);
} //方法2
public SqlSessionFactory build(Reader reader, String environment) {
return build(reader, environment, null);
} //方法3
public SqlSessionFactory build(Reader reader, Properties properties) {
return build(reader, null, properties);
} //方法4
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
} //方法5
public SqlSessionFactory build(InputStream inputStream) {
return build(inputStream, null, null);
} //方法6
public SqlSessionFactory build(InputStream inputStream, String environment) {
return build(inputStream, environment, null);
} //方法7
public SqlSessionFactory build(InputStream inputStream, Properties properties) {
return build(inputStream, null, properties);
} //方法8
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.
}
}
} //方法9
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}

由源码可知该类共有9个public方法,方法1、2、3最终都是调用了方法4;而方法5、6、7最终都是调用了方法8;而方法4和方法8都是根据传参创建了一个XMLConfiguration对象;

然后根据XMLConfiguration对象的parse方法创建了一个Configuration对象,然后都调用了方法9,所以该类的所有方法最终都是调用了方法9。而方法9是根据传入的Configuration参数新建了一个DefaultSqlSessionFactory对象返回;

很显然DefaultSqlSessionFactory是SqlSessionFactory接口的默认实现类(SqlSessionFactory还有一个SqlSessionManager实现类,后续继续了解)

总结:SqlSessionFactoryBuilder根据mybatis的配置文件流创建Configuration对象,然后新建一个SqlSessionFactory的默认实现类DefaultSqlSessionFactory的对象

二、SqlSessionFactory解析

 package org.apache.ibatis.session;

 import java.sql.Connection;

 /**
* Creates an {@link SqlSession} out of a connection or a DataSource
*
* @author Clinton Begin
*/
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(); }

SqlSessionFactory接口定义了8个创建SqlSession的接口,和一个获取Configuration,该接口的主要作用也就是创建SqlSession

可以看出这里面涉及到了几个参数:

autoCommit:数据库是否自动提交

Connection:数据库连接

TransactionIsolationLevel:数据库隔离级别

ExecutorType:执行器类型

这几个参数具体含义暂不讨论,后续继续了解,那么现在继续了解下SqlSessionFactory的默认实现类DefaultSqlSessionFactory

三、DefaultSqlSessionFactory解析

先贴下源码如下:

 package org.apache.ibatis.session.defaults;

 import java.sql.Connection;
import java.sql.SQLException; import org.apache.ibatis.exceptions.ExceptionFactory;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.managed.ManagedTransactionFactory; /**
* @author Clinton Begin
*/
public class DefaultSqlSessionFactory implements SqlSessionFactory { private final Configuration configuration; public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
} @Override
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
} @Override
public SqlSession openSession(boolean autoCommit) {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, autoCommit);
} @Override
public SqlSession openSession(ExecutorType execType) {
return openSessionFromDataSource(execType, null, false);
} @Override
public SqlSession openSession(TransactionIsolationLevel level) {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), level, false);
} @Override
public SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level) {
return openSessionFromDataSource(execType, level, false);
} @Override
public SqlSession openSession(ExecutorType execType, boolean autoCommit) {
return openSessionFromDataSource(execType, null, autoCommit);
} @Override
public SqlSession openSession(Connection connection) {
return openSessionFromConnection(configuration.getDefaultExecutorType(), connection);
} @Override
public SqlSession openSession(ExecutorType execType, Connection connection) {
return openSessionFromConnection(execType, connection);
} @Override
public Configuration getConfiguration() {
return configuration;
} private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
final Executor executor = configuration.newExecutor(tx, execType);
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;
}
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
final Transaction tx = transactionFactory.newTransaction(connection);
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
} private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
if (environment == null || environment.getTransactionFactory() == null) {
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.
}
}
} }

DefaultSqlSessionFactory除了实现了SqlSessionFactory的9个接口,还有一个构造方法,也就是SqlSessionFactoryBuilder中调用的那个,然后还有4个私有方法;

可以看出实现的8个创建SqlSession对象的接口最终都是调用了openSessionFromDataSource()或是openSessionFromConnection()两个方法

依openSessionFromDataSource为例,源码如下:

 private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();//根据Configuration获取环境参数对象
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);//根据环境参数对象获取事务工厂对象
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);//根据事务工厂创建新的事务对象
final Executor executor = configuration.newExecutor(tx, execType);//根据Configuration获取执行器对象
return new DefaultSqlSession(configuration, executor, autoCommit);//根据3个参数创建DefaultSqlSession对象
} 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();
}
}

该方法共有三个参数

ExecutorType:执行器类型

TransactionIsolationLevel:事务隔离级别

autoCommit:自动提交标识

由源码可知,最终是创建了一个DefaultSqlSession对象,很明显是SqlSession接口的默认实现类;

openSessionFromConnection方法和openSessionFromDataSource的区别就是参数不同,效果是一样的,最终也是返回一个DefaultSqlSession对象

而具体的Sql的执行都是通过DefaultSqlSession对象去执行的。具体怎么执行的后续再了解;

总结:

1.先获取mybatis的配置文件,解析成流对象(字符流和字节流都可以)Reader和InputStream都可以

2.通过SqlSessionFactoryBuilder根据mybatis的配置文件流创建一个Configuration对象

3.SqlSessionFactoryBuilder根据Configuration对象创建一个DefaultSqlSessionFactory(SqlSessionFactory的默认实现类)

4.DefaulatSqlSessionFacotry根据传入的参数,创建一个DefaultSqlSession对象(SqlSession的默认实现类)

mybatis源码解析2---SqlSessionFactoryBuilder、SqlSessionFactory解析的更多相关文章

  1. mybatis源码分析之02配置文件解析

    该篇正式开始学习mybatis的源码,本篇主要学习mybatis是如何加载配置文件mybatis-config.xml的, 先从测试代码入手. public class V1Test { public ...

  2. 浩哥解析MyBatis源码(十一)——Parsing解析模块之通用标记解析器(GenericTokenParser)与标记处理器(TokenHandler)

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6724223.html 1.回顾 上面的几篇解析了类型模块,在MyBatis中类型模块包含的 ...

  3. mybatis源码阅读-MappedStatement各个属性解析过程(八)

    调用方 类org.apache.ibatis.builder.xml.XMLMapperBuilder private void configurationElement(XNode context) ...

  4. myBatis源码学习之SqlSessionFactoryBuilder

    SqlSessionFactoryBuilder通过类名就可以看出这个类的主要作用就是创建一个SqlSessionFactory,通过输入mybatis配置文件的字节流或者字符流,生成XMLConfi ...

  5. mybatis源码学习:从SqlSessionFactory到代理对象的生成

    目录 一.根据XML配置文件构建SqlSessionFactory 二.通过SqlSessionFactory创建SqlSession 三.getMapper获取动态代理对象 一.根据XML配置文件构 ...

  6. Mybatis源码分析之Mapper文件解析

    感觉CSDN对markdown的支持不够友好,总是伴随各种问题,很恼火! xxMapper.xml的解析主要由XMLMapperBuilder类完成,parse方法来完成解析: public void ...

  7. MyBatis源码 核心配置解析 properties元素

    XMLConfigBuilder的parseConfiguration(XNode)方法,用于解析配置文件 XMLConfigBuilder的propertiesElement(XNode)方法,用于 ...

  8. Mybatis源码阅读-配置文件及映射文件解析

    Mybatis源码分析: 1.配置文件解析: 1.1源码阅读入口: org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(); 功能:解析全局配置文 ...

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

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

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

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

随机推荐

  1. 前端 HTML form表单标签 select标签 option 下拉框

    <select></select> select里面通常跟option配合使用 <!DOCTYPE html> <html lang="en&quo ...

  2. RzCheckTree基本使用

    procedure TForm1.Button1Click(Sender: TObject); var i: Integer; begin //循环读取勾选节点代码及内容 //StateIndex 1 ...

  3. 网络传输--TCP

    TCP网络编程 一.TCP简介 二.TCP网络程序--客户端 三.TCP网络程序--服务端 四.TCP知识总结 五.文件下载案例 六.3次握手和4次挥手 回到顶部 一.TCP简介TCP 1.TCP的简 ...

  4. Linux命令:tar命令批量解压方法总结

    tar命令批量解压方法总结 (2010-05-24 17:48:46) 转载▼ 标签: tar 批量解压 杂谈 分类: linux学习 由于linux的tar命令不支持批量解压,所以很多网友编写了好多 ...

  5. 二叉树df

    二叉树 最有搜索算法 打印偶节点 不要用递归

  6. [LeetCode] 154. Find Minimum in Rotated Sorted Array II_Hard

    Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...

  7. CentOS6.5安装RHive

    1.安装RServe软件包(各个节点都要安装) [root@Hadoop-NN-01 mysofts] # R CMD INSTALL Rserve_1.7-2.tar.gz 2.设置环境变量 [ro ...

  8. Entity Framework学习初级篇2

    Entity Framework 学习初级篇2--ObjectContext.ObjectQuery.ObjectStateEntry.ObjectStateManager类的介绍 本节,简单的介绍E ...

  9. Node.js进击基础一(5-11事件模块)

    res.on res有on方法. 在nodejs中不存在浏览器里的冒泡捕获等行为,集成了一个模块events,对外暴露一个对象EventEmitter ,EventEmitter作用只有2个事件的发射 ...

  10. Mac为python2.7.10安装pip

    首先下载get-pip.py https://bootstrap.pypa.io/get-pip.py alias python="/usr/bin/python2.7" pyth ...