MyBatis源码解析系列之二:深入理解SqlSessionFactory和SqlSession

MyBatis源码解析系列之二:深入理解SqlSessionFactory和SqlSession

欢迎大家回到我的MyBatis源码解析系列。在上一期中,我们初步了解了MyBatis的整体架构和核心组件。这篇文章将深入解析 SqlSessionFactorySqlSession 的源码,帮助大家更好地理解它们的实现原理。

一、SqlSessionFactory的创建过程

SqlSessionFactory 是MyBatis的核心工厂类,用于创建 SqlSession 实例。SqlSessionFactory 的创建过程通常分为以下几个步骤:

  1. 读取配置文件
  2. 解析配置文件
  3. 创建Configuration对象
  4. 构建SqlSessionFactory实例

我们以 SqlSessionFactoryBuilder 类为例,来看一下具体的创建过程。

1. 读取配置文件

配置文件通常是一个XML文件,包含了数据库连接信息、映射文件等。SqlSessionFactoryBuilder 会读取该文件并构建一个 InputStream

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
2. 解析配置文件

SqlSessionFactoryBuilder 使用 XMLConfigBuilder 类来解析XML配置文件。XMLConfigBuilder 会解析XML文件中的各个节点,并将解析结果存储在 Configuration 对象中。

public SqlSessionFactory build(InputStream inputStream) {
  return build(inputStream, null, null);
}

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
  try {
    XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
    Configuration config = parser.parse();
    return build(config);
  } 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.
    }
  }
}
3. 创建Configuration对象

XMLConfigBuilder 解析XML文件后,会创建并初始化一个 Configuration 对象,该对象包含了MyBatis的所有配置信息。

public Configuration parse() {
  if (parsed) {
    throw new BuilderException("Each XMLConfigBuilder can only be used once.");
  }
  parsed = true;
  parseConfiguration(parser.evalNode("/configuration"));
  return configuration;
}

private void parseConfiguration(XNode root) {
  try {
    propertiesElement(root.evalNode("properties"));
    Properties settings = settingsAsProperties(root.evalNode("settings"));
    loadCustomVfs(settings);
    typeAliasesElement(root.evalNode("typeAliases"));
    pluginElement(root.evalNode("plugins"));
    objectFactoryElement(root.evalNode("objectFactory"));
    objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
    reflectorFactoryElement(root.evalNode("reflectorFactory"));
    settingsElement(settings);
    environmentsElement(root.evalNode("environments"));
    databaseIdProviderElement(root.evalNode("databaseIdProvider"));
    typeHandlerElement(root.evalNode("typeHandlers"));
    mapperElement(root.evalNode("mappers"));
  } catch (Exception e) {
    throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
  }
}
4. 构建SqlSessionFactory实例

最后,SqlSessionFactoryBuilder 使用 Configuration 对象来构建一个 DefaultSqlSessionFactory 实例。

public SqlSessionFactory build(Configuration config) {
  return new DefaultSqlSessionFactory(config);
}
二、SqlSession的创建与使用

SqlSession 是MyBatis中用于执行SQL语句和管理事务的核心接口。SqlSession 的创建通常由 SqlSessionFactory 完成。

1. 创建SqlSession

SqlSessionFactory 提供了多种创建 SqlSession 的方法,最常用的是 openSession() 方法。

public SqlSession openSession() {
  return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}

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();
  }
}
2. 使用SqlSession

SqlSession 提供了一系列执行SQL语句的方法,如 selectOneselectListinsertupdatedelete。这些方法内部会通过 Executor 来执行具体的SQL语句。

try (SqlSession session = sqlSessionFactory.openSession()) {
  Blog blog = session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
}
三、总结

在本篇文章中,我们深入解析了 SqlSessionFactorySqlSession 的创建与使用过程。通过源码的解析,相信大家对MyBatis的核心组件有了更深入的理解。下一篇文章中,我们将进一步探讨 ExecutorMappedStatement 的内部实现原理,敬请期待。

希望大家继续关注我的系列文章,点赞、收藏和分享就是对我最大的支持。如果有任何问题或建议,欢迎在评论区留言讨论。


如需获取更多MyBatis源码解析的详细内容,请持续关注我的CSDN博客,更多精彩内容等着你!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿里渣渣java研发组-群主

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值