mybatis框架架构和源码学习笔记01

本文讲解 MyBatis 四大核心概念(SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession、Mapper。
了解了这四大核心,可知 MyBatis 。
SqlSessionFactoryBuilder
从命名上可以看出,这个是一个 Builder 模式的,用于创建 SqlSessionFactory 的类。SqlSessionFactoryBuilder 根据配置来构造 SqlSessionFactory。
SqlSessionFactory
是用于生产 SqlSession 的工厂。
SqlSession
即可发送SQL执行返回结果,又可获取mapper的接口。相当于一个数据库连接对象,可以在一个事务里面执行多条SQL,通过commit、rollback进行提交或回滚事务。
SQL Mapper
由一个Java接口和XML文件(或注解)构成。根据编写的SQL和映射规则,实现对数据库的访问,并返回结果。存活于一个请求中,一但请求完毕后,就会废弃。

mybatis框架架构和源码学习笔记01_第1张图片
. 1.mybatis配置文件
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信
息。
Mapper.xml,此文件作为mybatis的sql映射文件,文件中配置了操作数据库的sql语句。此
文件需要在SqlMapConfig.xml中加载。
2. SqlSessionFactory
通过mybatis环境等配置信息构造SqlSessionFactory,即会话工厂。
3. sqlSession
通过会话工厂创建sqlSession即会话,程序员通过sqlsession会话接口对数据库进行增删改查操
作。
4. Executor执行器
mybatis底层自定义了Executor执行器接口来具体操作数据库,Executor接口有两个实现,一个是
基本执行器(默认)、一个是缓存执行器,sqlsession底层是通过executor接口操作数据库的。
5. Mapped Statement
它也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文
件中一个select\insert\update\delete标签对应一个Mapped Statement对象,
select\insert\update\delete标签的id即是Mapped statement的id。
Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通
过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中
对preparedStatement设置参数。
Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通
过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc
编程中对结果的解析处理过程。

mybatis框架架构和源码学习笔记01_第2张图片
我们在使用 MyBatis 时,第一步要做的事情一般是根据配置文件构建 SqlSessionFactory对象。我们首先会使用 MyBatis 提供的工具类 Resources 加载配置文件,得到一个输入流。然后再通过 SqlSessionFactoryBuilder 对象的 build 方法构建 SqlSessionFactory 对象。这里的 build 方法是我们分析配置文件解析过程的入口方法。

mybatis框架架构和源码学习笔记01_第3张图片
mybatis框架架构和源码学习笔记01_第4张图片

下面我们来看一下这个方法的代码:

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);
// 调用 parse 方法解析配置文件,生成 Configuration 对象
return build(parser.parse());
} catch (Exception e) {
     
throw ExceptionFactory.wrapException("……", e);
} finally {
     
ErrorContext.instance().reset(); try {
     
inputStream.close();
} catch (IOException e) {
     }
}
}


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

public XMLConfigBuilder(Reader reader) {
     
    this(reader, null, null);
  }

  public XMLConfigBuilder(Reader reader, String environment) {
     
    this(reader, environment, null);
  }

  public XMLConfigBuilder(Reader reader, String environment, Properties props) {
     
    this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props);
  }

  public XMLConfigBuilder(InputStream inputStream) {
     
    this(inputStream, null, null);
  }

  public XMLConfigBuilder(InputStream inputStream, String environment) {
     
    this(inputStream, environment, null);
  }

  public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
     
    this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
  }

  private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
     
    super(new Configuration());//调用父类的构造方法
    ErrorContext.instance().resource("SQL Mapper Configuration");
    this.configuration.setVariables(props);
    this.parsed = false;
    this.environment = environment;
    this.parser = parser;
  }
public Configuration parse() {
     
    if (parsed) {
     //判断Configuration是否解析过,Configuration是全局变量,只需要解析创建一次即可
      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    parsed = true;
    parseConfiguration(parser.evalNode("/configuration"));//调用下面的方法,parser.evalNode("/configuration")解析XML配置的configuration节点的内容,得到XNode对象
    return configuration;
  }
  //根据root中存储的是configuration节点的内容
  private void parseConfiguration(XNode root) {
     
    try {
     
      Properties settings = settingsAsPropertiess(root.evalNode("settings"));//设置settings配置
      //issue #117 read properties first
      propertiesElement(root.evalNode("properties"));//设置properties配置
      loadCustomVfs(settings);
      typeAliasesElement(root.evalNode("typeAliases"));//设置typeAliases配置
      pluginElement(root.evalNode("plugins"));//设置plugins配置
      objectFactoryElement(root.evalNode("objectFactory"));//设置objectFactory配置
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));//设置objectWrapperFactory配置
      reflectorFactoryElement(root.evalNode("reflectorFactory"));//设置reflectFactory配置
      settingsElement(settings);
      // read it after objectFactory and objectWrapperFactory issue #631
      environmentsElement(root.evalNode("environments"));//设置environments配置
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));//设置databaseIdProvider配置
      typeHandlerElement(root.evalNode("typeHandlers"));//设置typeHandlers配置
      mapperElement(root.evalNode("mappers"));//设置mappers配置
    } catch (Exception e) {
     
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }

mybatis框架架构和源码学习笔记01_第5张图片

sqlsession执行
制定sqlsession接口和api方法
创建SqlSession
创建Sqlsession需要先创建SqlSessionFactory,通过SqlSessionFactoryBuilder使用构
建者模式来创建,此时需要Configuration对象去创建SqlSessionFactory
执行sqlsession:参数有两个(statementId和参数对象)
根据statementId,去Configuration中的MappedStatement集合中查找对应的
MappedStatement对象。
取出MappedStatement中的SQL信息
取出MappedStatement中的statementType,用来创建Statement对象
取出MappedStatement中的Configuration对象,通过Configuration对象,获取
DataSource对象,通过DataSource对象,创建Connection,通过Connection创
建Statement对象。
设置参数
执行preparedStatement.setInt(1,value);

mybatis框架架构和源码学习笔记01_第6张图片

遍历List集合(参数名称、属性类型、顺序)
判断是否是集合类型、8种基本类型、String类型、引用类型
基本类型的话,传过来的参数就是SQL的参数值
引用类型的话,根据参数名称,获取引用类型对应的属性值
调用setXXX方法赋值
执行Statement
executeQuery方法,获取ResultSet结果集
处理结果集
遍历结果集ResultSet
取出ResultSet中的所有列的名称和值和类型,存储到一个集合中
取出MappedStatement中的resultTypeClass,反射进行实例化。
遍历上面的集合,根据集合中的列的名称给属性赋值

public final class MappedStatement {
     
    private String resource;
    private Configuration configuration;
    private String id;
    private Integer fetchSize;
    private Integer timeout;
    private StatementType statementType;
    private ResultSetType resultSetType;
    private SqlSource sqlSource;
    private Cache cache;
    private ParameterMap parameterMap;
    private List<ResultMap> resultMaps;
    private boolean flushCacheRequired;
    private boolean useCache;
    private boolean resultOrdered;
    private SqlCommandType sqlCommandType;
    private KeyGenerator keyGenerator;
    private String[] keyProperties;
    private String[] keyColumns;
    private boolean hasNestedResultMaps;
    private String databaseId;
    private Log statementLog;
    private LanguageDriver lang;
    private String[] resultSets;

    MappedStatement() {
     
    }

你可能感兴趣的:(mybatisplus)