构建SqlSession工厂,看一下它的接口:
//构建SqlSession的工厂.工厂模式,8个方法可以用来创建SqlSession实例
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();
}
它有两个实现类,我们走默认的这个。(也就是第一篇中,new出来的configuration封装类)
在DefaultSqlSessionFactory中,有6个openSession会调用openSessionFromDataSource()方法
还要2个openSession会调用openSessionFromConnection()方法。
我们走的是无参数的,所以是第一种:
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
(说明:configuration类,是很多内容的,有900行,有很多解析xml出来的结果,对应很多 字段-get/set方法)
看第一个参数:它是一个枚举
//默认为简单执行器
protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
public enum ExecutorType {
//ExecutorType.SIMPLE
//这个执行器类型不做特殊的事情。它为每个语句的执行创建一个新的预处理语句。
//ExecutorType.REUSE
//这个执行器类型会复用预处理语句。
//ExecutorType.BATCH
//这个执行器会批量执行所有更新语句,如果SELECT在它们中间执行还会标定它们是必须的,来保证一个简单并易于理解的行为。
SIMPLE, REUSE, BATCH
}
进入具体实现方法:
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);
//然后产生一个DefaultSqlSession
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();
}
}
说明:
1.获得配置类中的环境字段
2.创建 事务工厂类:
private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
//如果没有配置事务工厂,则返回托管事务工厂
if (environment == null || environment.getTransactionFactory() == null) {
return new ManagedTransactionFactory();
}
return environment.getTransactionFactory();
}
这里的environment是有值的:
我们看一下Environment类的内容:
//决定加载哪种环境(开发环境/生产环境)
public final class Environment {
//环境id
private final String id;
//事务工厂
private final TransactionFactory transactionFactory;
//数据源
private final DataSource dataSource;
}
3.通过事务工厂获得一个事务
首先我们看一下事务工厂接口:(这个事务工厂 真的简单)
//事务工厂
public interface TransactionFactory {
//设置属性
void setProperties(Properties props);
//根据Connection创建Transaction
Transaction newTransaction(Connection conn);
//根据数据源和事务隔离级别创建Transaction
Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);
}
它的实现类:还是分为两个,我们使用第一个
它的实现也是极为简单
public class JdbcTransactionFactory implements TransactionFactory {
@Override
public void setProperties(Properties props) {
}
@Override
public Transaction newTransaction(Connection conn) {
return new JdbcTransaction(conn);
}
@Override
public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
return new JdbcTransaction(ds, level, autoCommit);
}
}
这个工厂就生成一个产品,只不过有两种参数模式。。。
我们看一下啊JdbcTransaction类,(走的第二种实例化方法),看这个构造方法和字段,也是很容易理解。
public class JdbcTransaction implements Transaction {
private static final Log log = LogFactory.getLog(JdbcTransaction.class);
protected Connection connection;
protected DataSource dataSource;
protected TransactionIsolationLevel level;
protected boolean autoCommmit;
public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
dataSource = ds;
level = desiredLevel;
autoCommmit = desiredAutoCommit;
}
public JdbcTransaction(Connection connection) {
this.connection = connection;
}
}
再看一下这个事务的 方法:
结构明显,三个commit,rollback,close操作方法,两个构造方法,还有get/set方法。
4.生成一个执行器
Configuration类中,根据前期设置的执行器类型,实例化执行器(前期设置的Simple类型)
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
//这句再做一下保护,囧,防止粗心大意的人将defaultExecutorType设成null?
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
//然后就是简单的3个分支,产生3种执行器BatchExecutor/ReuseExecutor/SimpleExecutor
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
//如果要求缓存,生成另一种CachingExecutor(默认就是有缓存),装饰者模式,所以默认都是返回CachingExecutor
if (cacheEnabled) {
executor = new CachingExecutor(executor); //最终还是走的这里
}
//此处调用插件,通过插件可以改变Executor行为
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
看一下CachingExecutor 二级缓冲的结构:
5.返回DefaultSqlSession
这个的结构和之前的jdbctransactioni很像,也是四个字段
//默认SqlSession实现
public class DefaultSqlSession implements SqlSession {
private Configuration configuration;
private Executor executor;
private boolean autoCommit; //是否自动提交
private boolean dirty;
public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
this.configuration = configuration;
this.executor = executor;
this.dirty = false;
this.autoCommit = autoCommit;
}
...
}
默认的sqlSession里面带了很多很多的操作方法
总结,注意着五层方法,都是递进关系:
由第一步的 环境,生成事务工厂,
由事务工厂生成事务,
由事务生成执行器,
由执行器生成sqlSession 会话!