MyBatis3源码阅读(一)2020-12-24

认识 SqlSessionFactoryBuilder、SqlSessionFactory 和 SqlSession

 

Step1: SqlSessionFactoryBuilder.build();

SqlSessionFactoryBuilder里重写了build方法,传入的参数不同,调用的是同一个方法,如下

SqlSessionFactory build(Reader reader)
SqlSessionFactory build(Reader reader, String environment)
SqlSessionFactory build(Reader reader, Properties properties)
SqlSessionFactory build(Reader reader, String env, Properties props)

SqlSessionFactory build(InputStream inputStream)
SqlSessionFactory build(InputStream inputStream, String environment)
SqlSessionFactory build(InputStream inputStream, Properties properties)
SqlSessionFactory build(InputStream inputStream, String env, Properties props)

SqlSessionFactory build(Configuration config)

Reader,InputStream,Configuration   通过三种方式得到配置信息,前面两种通过文件路径,读取文件,后一种通过配置类对象设置信息。

从下面的代码可知,第一段代码和第二段代码唯一的不同之处就是在解析XML文件的方法参数类型不同,一个是Reader,另一个是InputStream

  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.
      }
    }
  }

/**
 *上面两段代码读取XML文件内容后转换成Configuration对象,最终调用下面的方法
**/

  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }

Step2: 接下来进入DefaultSqlSessionFactory,使用构造器DefaultSqlSessionFactory(config)

构造方法代码如下:DefaultSqlSessionFactory里有openSession的重写方法,到这里就已经创建好了SqlSessionFactory对象,接下来是调用SqlSessionFactory.openSession();

private final Configuration configuration;

public DefaultSqlSessionFactory(Configuration configuration) {
    this.configuration = configuration;
  }

在DefaultSqlSessionFactory里openSession重写方法实现主要有以下两种方式,首先代码大体上不同,所以我们来挨个分析下

/*
  首先第一个是执行器类型是这样得到的 configuration.getDefaultExecutorType()
  第二个参数是事务隔离级别,不懂得话自己补
  第三个参数是 boolean类型,表示是否自动提交事务。有手动和自动之分
  内容:代码总体上来说就是根据传递的三个参数,创建了一个事务对象,通过事务对象得到执行器 
  Executor ,最后通过 DefaultSqlSession(configuration, executor, autoCommit)来得到 
  sqlSession对象
*/
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();
    }
  }




/*
  通过创建的连接对象Connection ,默认自动提交,生成事务对象,通过事务对象得到执行器 
  Executor ,最后通过 DefaultSqlSession(configuration, executor, autoCommit)来得到 
  sqlSession对象
*/
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();
    }
  }


/*
  总结:两种方法最后都是通过new DefaultSqlSession(configuration, executor, autoCommit)
  来获取SqlSession,只是得到的初始参数不同,有点殊途同归的味道。在读源码的时候不一定每一处
  都要百分百理解,要从宏观上理解框架的设计思想,而不是去看懂每一行代码,最后给自己加油,奥利 
  给。
*/

Step3: 接下来进入DefaultSqlSession,使用构造器new DefaultSqlSession(configuration, executor, autoCommit);

好像到这里就结束了,我在捋一捋啊

  /*
    给类变量赋值
  */

  private final Configuration configuration;
  private final Executor executor;

  private final 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;
  }

step 4 :这里是通过SqlSessionFactoryBuilder读取XML配置信息,生成SqlSessionFactory对象实例,最后在调用sqlSessionFactory.openSession();便可得到sqlSession实例

    final String resource = "conf.xml";
    Reader reader;
    try{
      reader = Resources.getResourceAsReader(resource);
      SqlSessionFactory sqlSessionFactory= new SqlSessionFactoryBuilder().build(reader);
    }catch (IOException e){
      e.printStackTrace();
    }

测试代码

  public static void exampleTest1(){
    SqlSession session = sqlFactory.openSession();
    Users user = new Users();
    user.setUserName("king");
    UserMapper u = session.getMapper(UserMapper.class);
    Users user1 = u.getUser(user);
    System.out.println(user1);
    session.commit();  //这里便是手动提交,如果配置自动提交的话不用写
    session.close();   //一定要关闭,切记,和关闭数据库的Connection一个道理
  }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值