mybatis源码---SqlSession构建

构建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 会话!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值