Mybatis SqlSession创建过程

98 阅读2分钟

SqlSession对象的获取

InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = factory.openSession();

SqlSession对象创建的过程

配置文件的解析

InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);

主要是在build方法中对配置文件进行的解析,主要完成配置文件的解析成对象,还有就是读取配置文件中的mapper, 尽量在一次IO操作中完成对对象的封装,减少IO调用。

XML的解析

XML解析有三种方式

  1. DOM
  2. SAX
  3. XPath (Mybatis)

与熟悉的ORM相对的就是OXM,java的核心思想,一切皆对象,OXM就是Object和xml的映射。 Mybatis中把xml中的配置封装成Configuration对象,通过XpathParser解析成XNode对象,再进一步封装成Configuration对象。

XPathParser xpathParser = new XPathParser(inputStream);  
xpathParser.evalNodes("/xxxxx") ----> XNode ---> 标签的名字  标签的属性 标签内容
封装Configuration
build() --> parseConfiguration(parser.evalNode("/configuration"));
封装MapperStatement
xPathParser XNode ---> MappedStatement ---> namespace.id                                        parseConfiguration-->mapperElement(root.evalNode("mappers"));  
    XMLMapperBuilder mapperParser = new XMLMapperBuilder();  
      mapperParser.parse();                              
          configurationElement(parser.evalNode("/mapper"));  
             statementParser.parseStatementNode();  
                builderAssistant.addMappedStatement  
                  MappedStatement statement = statementBuilder.build();
                      configuration.addMappedStatement(statement);

上边是封装的主要流程,最后把MappedStatment 存放在了 Configuration 中

SqlSessionFactory工厂的创建

XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
return build(parser.parse());

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

直接通过build方法,入参是Configuration对象,直接创建了默认的DefaultSQLSessionFactory进行返回,也就是说这个是工厂的默认实现

再看SqlSession对象的获取

SqlSession sqlSession = sqlSessionFactory.openSession();

猜测一下openSession里边的过程,首先可以知道的是肯定需要把Executor交给SqlSession,因为底层都是Executor来进行操作的,然后可能还需要MapperStatement

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

获取了Environment对象,得到相关的连接池信息。创建了Executor交给SqlSession用于后边的执行,还赋值了Configuration对象,其中就包括了从配置文件解析、封装并存入Configuration对象中的MapperStatement对象,而且创建的是DefaultSqlSession

SqlSession执行sql的主要流程

SqlSession.getMapper() -> 动态代理 -> DAO接口的实现类

MapperProxyFactory(JDK创建的代理对象)
 |- InvocationHandler -> MapperProxy
     |- SqlCommand
         |- type [insert|update|delete|select]
         |- name namespace.id -类的全路径.方法名
     |- MethodSingnature
         |- 方法的返回值、参数
         |- sqlSession.update()
             |- Executor(SimpleExecutor|ReUseExecutor|BatchExecutor)
                 |- StatementHandler
                     |- ParameterHandler ResultSetHandler
                         |- TypeHandlder
         |- sqlSession.select()
         |- sqlSession.delete()