MyBatis框架的使用及源码分析(五) DefaultSqlSessionFactory和DefaultSqlSession
我们回顾<MyBatis框架中Mapper映射配置的使用及原理解析(一) 配置与使用> 一文的示例
private static SqlSessionFactory getSessionFactory() {
SqlSessionFactory sessionFactory = null;
String resource = "mybatisConfig.xml";
try {
sessionFactory = new SqlSessionFactoryBuilder().build(Resources
.getResourceAsReader(resource));
} catch (IOException e) {
e.printStackTrace();
}
return sessionFactory;
}
@Test
public void findUserById() {
SqlSessionFactory sqlSessionFactory = getSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.selectByPrimaryKey(1l);
System.out.println(user.getId() + " / " + user.getName());
}
SqlSessionFactoryBuilder 创建出SqlSessionFactory,然后从SqlSessionFactory中得到SqlSession,最后通过SqlSession得到Mapper接口对象进行数据库操作。
我们跟踪SqlSessionFactoryBuilder的源代码:
package org.apache.ibatis.session;
public class SqlSessionFactoryBuilder {
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.
}
}
}
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.
}
}
}
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
}
我们可以看到这个类用很多的构造方法,但主要分为三大类:
1、通过读取字符流(Reader)的方式构件SqlSessionFactory。
2、通过字节流(InputStream)的方式构件SqlSessionFacotry。
3、通过Configuration对象构建SqlSessionFactory。
第1、2种方式是通过配置文件方式,第3种是通过Java代码方式。
build方法返回SqlSessionFactory接口的实现对象DefaultSqlSessionFactory。
我们继续跟踪DefaultSqlSessionFactory的openSession()方法:
package org.apache.ibatis.session.defaults; /**
* @author Clinton Begin
*/
public class DefaultSqlSessionFactory implements SqlSessionFactory { private final Configuration configuration; public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
} public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
} public SqlSession openSession(boolean autoCommit) {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, autoCommit);
} public SqlSession openSession(ExecutorType execType) {
return openSessionFromDataSource(execType, null, false);
} public SqlSession openSession(TransactionIsolationLevel level) {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), level, false);
} 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;
} 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.
}
}
} }
这么多的openSession重载方法,都是通过传入不同的参数构造SqlSession实例,有通过设置事务是否自动提交"autoCommit",有设置执行器类型"ExecutorType"来构造的,还有事务的隔离级别等等。
最后一个方法就告诉我们可以通过SqlSessionFactory来获取Configuration对象。
mybatis创建sqlsession经过了以下几个主要步骤:
1. 从核心配置文件mybatis-config.xml中获取Environment(这里面是数据源);
2. 从Environment中取得DataSource;
3. 从Environment中取得TransactionFactory;
4. 从DataSource里获取数据库连接对象Connection;
5. 在取得的数据库连接上创建事务对象Transaction;
6. 创建Executor对象(该对象非常重要,事实上sqlsession的所有操作都是通过它完成的);
7. 创建sqlsession对象。
从源码中可以知道DefaultSqlSession是SqlSession的实例。
new DefaultSqlSession(configuration, executor, autoCommit);
那么通过此文,我们就清楚的知道了SqlSessionFactory和SqlSession具体的创建过程,知道了他们的实现类是DefaultSqlSessionFactory和DefaultSqlSession。
MyBatis框架的使用及源码分析(五) DefaultSqlSessionFactory和DefaultSqlSession的更多相关文章
- MyBatis框架的使用及源码分析(十一) StatementHandler
我们回忆一下<MyBatis框架的使用及源码分析(十) CacheExecutor,SimpleExecutor,BatchExecutor ,ReuseExecutor> , 这4个Ex ...
- MyBatis框架的使用及源码分析(九) Executor
从<MyBatis框架的使用及源码分析(八) MapperMethod>文中我们知道执行Mapper的每一个接口方法,最后调用的是MapperMethod.execute方法.而当执行Ma ...
- MyBatis框架的使用及源码分析(八) MapperMethod
从 <MyBatis框架中Mapper映射配置的使用及原理解析(七) MapperProxy,MapperProxyFactory> 文中,我们知道Mapper,通过MapperProxy ...
- MyBatis框架的使用及源码分析(六) MapperRegistry
我们先Mapper接口的调用方式,见<MyBatis框架中Mapper映射配置的使用及原理解析(一) 配置与使用>的示例: public void findUserById() { Sql ...
- MyBatis框架的使用及源码分析(四) 解析Mapper接口映射xml文件
在<MyBatis框架中Mapper映射配置的使用及原理解析(二) 配置篇 SqlSessionFactoryBuilder,XMLConfigBuilder> 一文中,我们知道mybat ...
- MyBatis框架的使用及源码分析(二) 配置篇 SqlSessionFactoryBuilder,XMLConfigBuilder
在 <MyBatis框架中Mapper映射配置的使用及原理解析(一) 配置与使用> 的demo中看到了SessionFactory的创建过程: SqlSessionFactory sess ...
- MyBatis框架的使用及源码分析(十) CacheExecutor,SimpleExecutor,BatchExecutor ,ReuseExecutor
Executor分成两大类,一类是CacheExecutor,另一类是普通Executor. 普通类又分为: ExecutorType.SIMPLE: 这个执行器类型不做特殊的事情.它为每个语句的执行 ...
- MyBatis框架的使用及源码分析(七) MapperProxy,MapperProxyFactory
从上文<MyBatis框架中Mapper映射配置的使用及原理解析(六) MapperRegistry> 中我们知道DefaultSqlSession的getMapper方法,最后是通过Ma ...
- MyBatis框架的使用及源码分析(三) 配置篇 Configuration
从上文<MyBatis框架中Mapper映射配置的使用及原理解析(二) 配置篇 SqlSessionFactoryBuilder,XMLConfigBuilder> 我们知道XMLConf ...
随机推荐
- JS判断是IOS还是Android以及如何解决h5打包后在ios下内容与状态栏重叠问题
h5打包后在ios下内容与状态栏重叠问题: 1:知道设备的类型: var u = navigator.userAgent, app = navigator.appVersion; var isAndr ...
- Python中from module import *语法
from module import *的语法在Python 3.X和Python 2.X中的使用稍有区别: 在Python 3.X中,from module import *无法在函数里面使用,而在 ...
- 20145214 《Java程序设计》第8周学习总结
20145214 <Java程序设计>第8周学习总结 教材学习内容总结 日志API 使用日志的起点是Logger类,Logger类的构造函数标示为protected,不是java.util ...
- c# throw抛出上一个异常
catch(exception e) { throw; } 不仅抛出这次的异常,也抛出之前的异常. 用法示例:函数A调用函数B,A用到此throw时,B中发生的异常也会继承过来. catch(exce ...
- 利用SqlServer的作业定时清除过期数据
有时候我们的数据库中可能会有那么些存放动态数据的表,比如一些每天定时发出的消息通知信息等数据.这些数据我们只需要临时保存,一些老旧的数据需要定时去清除掉,不然时间一长的话单表数据堆积非常严重.导致数据 ...
- css那些事儿3 列表与浮动
一 列表 列表默认为行内块元素,具有宽高,当一个非块元素是无法应用宽高的,比如a 1 有序列表 有ol li组成,其中li为列表项,列表的ol子元素务必为li元素标签,li子内容支持列表任意嵌套,有 ...
- 《Effective C#》快速笔记(三)- 使用 C# 表达设计
目录 二十一.限制类型的可见性 二十二.通过定义并实现接口替代继承 二十三.理解接口方法和虚方法的区别 二十四.用委托实现回调 二十五.用事件模式实现通知 二十六.避免返回对内部类对象的引用 二十七. ...
- Mybatis笔记二
一对一查询 案例:查询所有订单信息,订单信息中显示下单人信息. 注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询.如果从用户信息出发查询用户下的订单信息则 ...
- Keil MDK中Image~~RW_IRAM1~~ZI~~Limit(~表示$)
ARM程序的组成 此处所说的“ARM程序”是指在ARM系统中正在执行的程序,而非保存在ROM中的bin映像(image)文件,这一点清注意区别. 一个ARM程序包含3部分:RO, ...
- 当重写了 httpservlet重写了GenericServlet的init方法时候 必须显示调用GenericServlet的init方法时候 才能在别的方法(父类创建config实例) 例如 doget里面使用servletContext对象 不重写init 则可以直接使用