转载自https://www.jianshu.com/p/4e268828db48(添加小部分笔记)感谢作者!
还没看完
在上篇文章中,我们讲解了MyBatis的启动流程,以及启动过程中涉及到的组件,在本篇文中,我们继续探索SqlSession,SqlSessionFactory,SqlSessionFactoryBuilder的关系。SqlSession作为MyBatis的核心组件,可以说MyBatis的所有操作都是围绕SqlSession来展开的。对SqlSession理解透彻,才能全面掌握MyBatis。
1. SqlSession初识#
SqlSession在一开始就介绍过是高级接口,类似于JDBC操作的connection对象,它包装了数据库连接,通过这个接口我们可以实现增删改查,提交/回滚事物,关闭连接,获取代理类等操作。SqlSession是个接口,其默认实现是DefaultSqlSession。SqlSession是线程不安全的,每个线程都会有自己唯一的SqlSession,不同线程间调用同一个SqlSession会出现问题,因此在使用完后需要close掉。

SqlSession的方法
2. SqlSession的创建#
SqlSessionFactoryBuilder的build()方法使用建造者模式创建了SqlSessionFactory接口对象,SqlSessionFactory接口的默认实现是DefaultSqlSessionFactory。SqlSessionFactory使用实例工厂模式来创建SqlSession对象。SqlSession,SqlSessionFactory,SqlSessionFactoryBuilder的关系如下(图画得有点丑…):

类图
DefaultSqlSessionFactory中openSession是有两种方法一种是openSessionFromDataSource,另一种是openSessionFromConnection。这两种是什么区别呢?从字面意义上将,一种是从数据源中获取SqlSession对象,一种是由已有连接获取SqlSession。SqlSession实际是对数据库连接的一层包装,数据库连接是个珍贵的资源,如果频繁的创建销毁将会影响吞吐量,因此使用数据库连接池化技术就可以复用数据库连接了。因此openSessionFromDataSource会从数据库连接池中获取一个连接,然后包装成一个SqlSession对像。openSessionFromConnection则是直接包装已有的连接并返回SqlSession对像。
openSessionFromDataSource 主要经历了以下几步:
- 从获取configuration中获取Environment对象,Environment包含了数据库配置
- 从Environment获取DataSource数据源
- 从DataSource数据源中获取Connection连接对象
- 从DataSource数据源中获取TransactionFactory事物工厂
- 从TransactionFactory中创建事物Transaction对象
- 创建Executor对象
- 包装configuration和Executor对象成DefaultSqlSession对象
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();
}
}3. SqlSession的使用#
SqlSession 获取成功后,我们就可以使用其中的方法了,比如直接使用SqlSession发送sql语句,或者通过mapper映射文件的方式来使用,在上两篇文章中我们都是通过mapper映射文件来使用的,接下来就介绍第一种,直接使用SqlSession发送sql语句。




