Mybatis源码解析-2通过SqlSessionFactory获取一个SqlSession

1.入口

整个程序的demo在放一下:

    public static void main(String[] args) {
    	//获取配置文件信息流
    	InputStream stream = Demo.class.getClassLoader().getResourceAsStream("mybatis.xml");
    	
        //使用SqlSessionFactory构建器,读取配置文件构建出一个sessionFactory
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(stream);
        
        //通过sessionFactory开启一个Session
        SqlSession sqlSession = sessionFactory.openSession(true);

        //调用selectOne方法查询数据
        User user = sqlSession.selectOne("org.demo.bean.UserMapper.getUser", 1);
        //输出
        System.out.println(user);
        
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user2 = mapper.getUser(1L);
        System.out.println(user2);
    }

第一步,通过读取配置文件构建一个SqlSessionFactory上文已经说过,这里看一下如何通过SqlSessionFactory构建一个session

2.sessionFactory.openSession

SqlSessionFactory中提供了多个openSession方法,如下:

  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);

从上文中知道我们构建出来的SqlSessionFactory是一个DefaultSqlSessionFactory对象,那么我们来看一下DefaultSqlSessionFactory中是如何实现这个方法的:

  /**
   * openSession 调用openSessionFromDataSource方法执行
   */
  @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);
  }

我们可以看到,这里主要是通过openSessionFromDataSource和openSessionFromConnection两个方法实现的,前者是通过DataSource数据源构建一个SqlSession,后者是通过一个Connection链接构建的SqlSession。

3.openSessionFromDataSource

我们详细看一下openSessionFromDataSource这个方法的实现

  /**
   * 开启一个session
   * @param execType	执行器类型
   * @param level	事务级别
   * @param autoCommit	是否自动提交事务
   * @return SqlSession
   */
  private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      //获取environment信息
      final Environment environment = configuration.getEnvironment();
      //根据environment获取对应事务工厂
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      //创建一个新的事务
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      //创建一个执行器 参数是一个事务,一个执行器类型
      final Executor executor = configuration.newExecutor(tx, execType);
      //创建DefaultSqlSession并给定参数configuration,executor,autoCommit
      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();
    }
  }

3.1 参数解析

其中execType是指执行器的类型这里主要分三种,是用枚举来定义的

public enum ExecutorType {
  SIMPLE, REUSE, BATCH
}

level是事务的隔离级别,这里也是通过枚举来定义的

public enum TransactionIsolationLevel {
  NONE(Connection.TRANSACTION_NONE),	//无事务
  READ_COMMITTED(Connection.TRANSACTION_READ_COMMITTED),	//读已提交
  READ_UNCOMMITTED(Connection.TRANSACTION_READ_UNCOMMITTED),	//读未提交
  REPEATABLE_READ(Connection.TRANSACTION_REPEATABLE_READ),	//可重复读
  SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE);	//串行化

  private final int level;

  TransactionIsolationLevel(int level) {
    this.level = level;
  }

  public int getLevel() {
    return level;
  }
}

其具体的值是在Connection中定义的,而Connection是一个interface接口,参数默认是static类型的,所以才可以直接通过Connection类名获取对应值

    int TRANSACTION_NONE             = 0;


    int TRANSACTION_READ_UNCOMMITTED = 1;


    int TRANSACTION_READ_COMMITTED   = 2;


    int TRANSACTION_REPEATABLE_READ  = 4;


    int TRANSACTION_SERIALIZABLE     = 8;

最后一个参数autoCommit代表是事务是否自动提交。

3.2 方法解析

1.获取environment信息

configuration是我们在构建SqlSessionFactory的时候读取配置文件生成的,具体参照上文。而getEnvironment方法就是获取其environment属性,对应xml中的environment节点:

  public Environment getEnvironment() {
    return environment;
  }

2.根据environment获取对应事务工厂

直接上源码

  /**
   * 获取事务工厂
   */
  private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
    if (environment == null || environment.getTransactionFactory() == null) {
      return new ManagedTransactionFactory();	//为空时默认返回ManagedTransactionFactory对象
    }
    return environment.getTransactionFactory();	//返回对应事务工厂
  }

3.创建一个新的事务

这里看一下ManagedTransactionFactory中创建事务,就是直接创建对象,也没什么好说的

  /**
   * 创建一个事务
   */
  @Override
  public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
    return new ManagedTransaction(ds, level, closeConnection);
  }



  public ManagedTransaction(DataSource ds, TransactionIsolationLevel level, boolean closeConnection) {
    this.dataSource = ds;
    this.level = level;
    this.closeConnection = closeConnection;
  }

4.创建一个执行器

这里就是根据类型创建不同的执行器对象,然后根据是否开启二级缓存的配置判断是否需要将执行器包装成CachingExecutor,最后返回执行器

  /**
   * 创建一个执行器
   * @param transaction	事务
   * @param executorType 执行器类型
   */
  public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
	//若executorType为null 则设置成defaultExecutorType也就是ExecutorType.SIMPLE
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor executor;
    //根据类型生成对应的执行器对象
    if (ExecutorType.BATCH == executorType) {	//BATCH类型
      executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {	//REUSE类型
      executor = new ReuseExecutor(this, transaction);
    } else {	//默认的SIMPLE类型
      executor = new SimpleExecutor(this, transaction);
    }
    if (cacheEnabled) {	//是否开启缓存
      //通过CachingExecutor对生成的执行器executor进行包装
      executor = new CachingExecutor(executor);
    }
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;	//返回执行器
  }

CachingExecutor执行器只是对执行器进行了一个包装,其中有一个执行器的属性,对执行器的方法是新都是调用这个执行器属性来实现的,只不过在调用之前会先加上二级缓存相关的逻辑处理,其类定义如下:

public class CachingExecutor implements Executor {

  private final Executor delegate;
  private final TransactionalCacheManager tcm = new TransactionalCacheManager();

  public CachingExecutor(Executor delegate) {
    this.delegate = delegate;
    delegate.setExecutorWrapper(this);
  }
}

5.创建DefaultSqlSession

也就是new一个对象返回。

猜你喜欢

转载自blog.csdn.net/luo_mu_hpu/article/details/108053432