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 ...
随机推荐
- $(document).ready()方法和window.onload有什么区别?
①.window.onload 方法是在网页中所有的元素(包括元素的所有关联文件)完全加载到浏览器后才执行的: ②.$(document).ready()方法可以在DOM载入就绪时就对其进行操纵,并调 ...
- 【JMeter】插件安装
安装插件的方法有两种,一种是传统的方式,即官网下载,本地配置,重启jmeter.现在有一种快捷的方法可以自定义安装插件-插件管理器 JMeter 插件管理器的使用方法很简单:不要手动安装各种插件,它提 ...
- 【托业】【新托业TOEIC新题型真题】学习笔记11-题库六-P7
1.scam [skæm] n.骗局; 诡计; <美俚>诓骗; 故事;vt.欺诈; 诓骗; 2.interpersonal adj.人与人之间的; 人际的; 人与人之间的关系的; 涉及人与 ...
- mv 命令
[root@localhost soft]# .txt [root@localhost soft]# [root@localhost soft]# ls .txt [root@localhost so ...
- MySQL大表DROP删除小技巧(转)
在日常工作中,经常会遇到历史大表从主库上迁移到备份机,以便腾出主库空间,那么如果你直接drop table 后,可能会引起数据库抖动,连接数升高等问题,从而影响业务. 那么用一个小技巧,即可轻松平滑的 ...
- DataTable 指定位置添加列
dt.Columns.Add("id").SetOrdinal(指定位置);
- 主成分分析(PCA)原理详解
一.PCA简介 1. 相关背景 在许多领域的研究与应用中,往往需要对反映事物的多个变量进行大量的观测,收集大量数据以便进行分析寻找规律.多变量大样本无疑会为研究和应用提供了丰富的信息,但也在一定程度上 ...
- Nginx解析PHP的原理 | CGI、FastCGI及php-fpm的关系
Nginx解析PHP的原理,CGI/FastCGI以及PHP-Fpm的关系. 一.PHP+Nginx应运而生的场景.随着互联网的发展,用户对此接受面广,数据流的增大使得Web端的运行承载压力日益增大, ...
- [js]纯css强制不换行
要加在li上 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...
- Linux下samba服务搭建
参考: https://www.cnblogs.com/lxyqwer/p/7271369.html https://www.cnblogs.com/liulipeng/p/3406352.html ...