1.创建SqlSessionFactoryBuilder对象,调用build方法读取并解析配置文件,返回SqlSessionFactory对象。方法中还会调用重载方法parse(),parse()方法又会去调用parseConfigation()方法,在该方法中可以看到读取了各个标签内容并封装到Configuration对象的的属性中并返回。该对象中有两个重要的Map,mappedStatementsMap:key:是全限定名+方法名,value:sql语句;还有一个map是用来存储代理类对象的,key:接口的字节码对象 value:此接口对应的MapperProxyFactory对象
所以解析xml就是给Configuration对象的属性复制的
2.由SqlSessionFactory调用opensession()方法创建SqlSession 对象,SqlSession对象是MyBatis中用于和数据库交互的顶层类,主要有两个重要属性,Configation,Executor。
3.创建完sqlsession对象后,调用SqlSession中的api,根据传入的全限定名+方法名从configuration对象的mappedStatementsMap集合中取出MappedStatement对象,一个MappedStatement对象对应着一条sql语句,
4.然后调用executor的query()方法或者update()方法,去执行sql,该方法中还有二级缓存的实现过程。
//在创建XMLConfigBuilder时,它的构造方法中解析器XPathParser已经读取了配置文件
//3. 进入XMLConfigBuilder 中的 parse()方法。
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
//parser是XPathParser解析器对象,读取节点内数据,<configuration>是MyBatis配置文件中的顶层标签
parseConfiguration(parser.evalNode("/configuration"));
//最后返回的是Configuration 对象
return configuration;
}
//4. 进入parseConfiguration方法
//此方法中读取了各个标签内容并封装到Configuration中的属性中。
private void parseConfiguration(XNode root) {
try {
//issue #117 read properties first
propertiesElement(root.evalNode("properties"));
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
loadCustomLogImpl(settings);
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
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);
}
}
缓存
一级缓存:sqlsession级别,是默认开启的,同一条sql语句第二次查询将直接从缓存中取,不会执行sql语句,当两次查询中做了cud操作的话,缓存将被清除,第二次也会执行sql语句
二级缓存:namespace级别,多个SqlSession之间可以共享缓存,会使用CachingExecutor装饰Executor,进入一级缓存的查询流程前,会先在CachingExecutor进行二级缓存的查询。所以数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。