mybatis源码解析2---SqlSessionFactoryBuilder、SqlSessionFactory解析
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解析的更多相关文章
- mybatis源码分析之02配置文件解析
该篇正式开始学习mybatis的源码,本篇主要学习mybatis是如何加载配置文件mybatis-config.xml的, 先从测试代码入手. public class V1Test { public ...
- 浩哥解析MyBatis源码(十一)——Parsing解析模块之通用标记解析器(GenericTokenParser)与标记处理器(TokenHandler)
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6724223.html 1.回顾 上面的几篇解析了类型模块,在MyBatis中类型模块包含的 ...
- mybatis源码阅读-MappedStatement各个属性解析过程(八)
调用方 类org.apache.ibatis.builder.xml.XMLMapperBuilder private void configurationElement(XNode context) ...
- myBatis源码学习之SqlSessionFactoryBuilder
SqlSessionFactoryBuilder通过类名就可以看出这个类的主要作用就是创建一个SqlSessionFactory,通过输入mybatis配置文件的字节流或者字符流,生成XMLConfi ...
- mybatis源码学习:从SqlSessionFactory到代理对象的生成
目录 一.根据XML配置文件构建SqlSessionFactory 二.通过SqlSessionFactory创建SqlSession 三.getMapper获取动态代理对象 一.根据XML配置文件构 ...
- Mybatis源码分析之Mapper文件解析
感觉CSDN对markdown的支持不够友好,总是伴随各种问题,很恼火! xxMapper.xml的解析主要由XMLMapperBuilder类完成,parse方法来完成解析: public void ...
- MyBatis源码 核心配置解析 properties元素
XMLConfigBuilder的parseConfiguration(XNode)方法,用于解析配置文件 XMLConfigBuilder的propertiesElement(XNode)方法,用于 ...
- Mybatis源码阅读-配置文件及映射文件解析
Mybatis源码分析: 1.配置文件解析: 1.1源码阅读入口: org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(); 功能:解析全局配置文 ...
- mybatis源码学习(一) 原生mybatis源码学习
最近这一周,主要在学习mybatis相关的源码,所以记录一下吧,算是一点学习心得 个人觉得,mybatis的源码,大致可以分为两部分,一是原生的mybatis,二是和spring整合之后的mybati ...
- mybatis源码学习:一级缓存和二级缓存分析
目录 零.一级缓存和二级缓存的流程 一级缓存总结 二级缓存总结 一.缓存接口Cache及其实现类 二.cache标签解析源码 三.CacheKey缓存项的key 四.二级缓存TransactionCa ...
随机推荐
- (4.20)sql server中 len 与datalength 的区别
len是任意字符均为一个占位符字节.datalength是根据字符集不同判断占用,如一个中文占用2个字节.
- 微信和WeChat合并月活跃数达8.89亿,移动支付月活跃账户超过6亿
3月22日,腾讯公布2016年年度业绩报告,微信和WeChat合并月活跃用户数达8.89亿,同比增长28%:2016年12月,腾讯移动支付的月活跃账户及日均支付交易笔数均超过6亿.腾讯主席兼首席执行官 ...
- 防止SQL注入的6个要点
SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.防止SQL注入,我们可以从以下6个要点来进行: 1.永远不要信任用户的输入 ...
- UVA 1379 - Pitcher Rotation(DP + 贪心)
题目链接:option=com_onlinejudge&Itemid=8&page=show_problem&problem=4125" rel="nofo ...
- UIKIT_EXTERN和define定义常量
看过我其他的博客的人都知道,我喜欢用define定义常量,最近看了一个开源的轮子,使用UIKIT_EXTERN这个定义的常量,了解了一下,发现使用宏定义的常量会在内存中临时开辟一份内存空间,而使用UI ...
- UIBezierPath使用
效果图,Demo的例子是我自己做的,下面曲线的代码是从别处copy过来的 copy地址 -(void)touchesBegan:(NSSet<UITouch *> *)touches wi ...
- CentOS安装Docker CE
安装Docker CE(免费版) docker EE企业版您可以根据需要以不同方式安装Docker CE: 大多数用户 设置Docker的存储库并从中进行安装,以便于安装和升级任务.这是推荐的方法. ...
- Emmagee——开源Android性能测试工具
工具:Emmagee作者:孔庆云 网易(杭州)质量保证部 开源地址:https://github.com/NetEase/Emmagee Wiki:https://github.com/NetEase ...
- Python3学习之路~6.1 编程范式:面向过程 VS 面向对象
编程范式 编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程,一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现一个任务的方式有很多种 ...
- sap QG3搜索
先创建一个QG3系统,创建一个用户. 1: 进入搜索模板 2: 选择软件组件,点击执行 3: 设置过滤条件. 4: 选择在哪一列 设置过滤条件. 5: 定义搜索值 6: 设置值 可以将搜索的结果删除. ...