详解Mybatis是如何解析配置文件的
作者:诺浅 发布时间:2023-10-15 23:23:40
缘起
经过前面三章的入门,我们大概了解了Mybatis的主线逻辑是什么样子的,在本章中,我们将正式进入Mybatis的源码海洋。
Mybatis是如何解析xml的
构建Configuration
我们调用new SqlSessionFactoryBuilder().build()方法的最终目的就是构建 Configuration对象,那么Configuration何许人也?Configuration对象是一个配置管家, Configuration对象之中维护着所有的配置信息。
Configuration的代码片段如下
public class Configuration {
//环境
protected Environment environment;
protected boolean safeRowBoundsEnabled;
protected boolean safeResultHandlerEnabled = true;
protected boolean mapUnderscoreToCamelCase;
protected boolean aggressiveLazyLoading;
protected boolean multipleResultSetsEnabled = true;
protected boolean useGeneratedKeys;
protected boolean useColumnLabel = true;
protected boolean cacheEnabled = true;
protected boolean callSettersOnNulls;
protected boolean useActualParamName = true;
protected boolean returnInstanceForEmptyRow;
//日志信息的前缀
protected String logPrefix;
//日志接口
protected Class<? extends Log> logImpl;
//文件系统接口
protected Class<? extends VFS> vfsImpl;
//本地Session范围
protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION;
//数据库类型
protected JdbcType jdbcTypeForNull = JdbcType.OTHER;
//延迟加载的方法
protected Set<String> lazyLoadTriggerMethods = new HashSet<String>(
Arrays.asList(new String[] { "equals", "clone", "hashCode", "toString" }));
//默认执行语句超时
protected Integer defaultStatementTimeout;
//默认的执行器
protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
//数据库ID
protected String databaseId;
//mapper注册表
protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
// * 链
protected final InterceptorChain interceptorChain = new InterceptorChain();
//类型处理器
protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();
//类型别名
protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();
//语言驱动
protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry();
//mapper_id 和 mapper文件的映射
protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>(
"Mapped Statements collection");
//mapper_id和缓存的映射
protected final Map<String, Cache> caches = new StrictMap<Cache>("Caches collection");
//mapper_id和返回值的映射
protected final Map<String, ResultMap> resultMaps = new StrictMap<ResultMap>("Result Maps collection");
//mapper_id和参数的映射
protected final Map<String, ParameterMap> parameterMaps = new StrictMap<ParameterMap>("Parameter Maps collection");
//资源列表
protected final Set<String> loadedResources = new HashSet<String>();
未完.......
}
构建MappedStatement
在Configuration中,有个mappedStatements的属性,这是个MappedStatement对象Map的集合,其key是这个mapper的namespace+对应节点的id,而value是一个MappedStatement对象。
在构建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);
}
}
上诉代码段倒数第三行mapperElement(root.evalNode("mappers"));
就是解析mappers处就是把我们的mapper文件封装成MappedStatement对象,然后保存到Configuration的mappedStatements属性中,其中key是这个mapper的namespace+对应节点的id,而value是一个MappedStatement对象。保存的地方关键代码如下
configuration.addMappedStatement(statement);
addMappedStatement()方法代码如下
protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>(
"Mapped Statements collection");
public void addMappedStatement(MappedStatement ms) {
mappedStatements.put(ms.getId(), ms);
}
那么这个MappedStatement的又是何许人也?我们可以简单的把MapperStatement理解为对sql的一个封装,在MappedStatement中保存着一个SqlSource对象,其中就存有SQL的信息。相关代码如下
public final class MappedStatement {
private SqlSource sqlSource;
}
SqlSource 代码如下
public interface SqlSource {
BoundSql getBoundSql(Object parameterObject);
}
BoundSql代码如下
public class BoundSql {
private final String sql;
private final List<ParameterMapping> parameterMappings;
}
关于二级缓存
我们在Configuration中看到了一个caches属性
protected final Map<String, Cache> caches = new StrictMap<>("Caches collection");
这个东西的作用是什么呢?其实是关于Mybatis的二级缓存的。在解析配置文件的过程中,如果用到了二级缓存,便会把这个ID和对象也保存到configuration的caches中,相关代码如下
public void addCache(Cache cache) {
caches.put(cache.getId(), cache);
}
构建SqlSessionFactory
在Configuration对象构建完毕之后,就该依赖Configuration对象去构建SqlSessionFactory对象了,相关代码如下
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
我们暂且把SqlSessionFactory称为SqlSession工厂吧,SqlSessionFactory中有两个方法,openSession()和getConfiguration()
SqlSessionFactory代码如下
public interface SqlSessionFactory {
SqlSession openSession();
//其余openSession重载方法略…
Configuration getConfiguration();
}
构建SqlSession
openSession()方法会返回一个SqlSession对象,SqlSession又是何许人也?SqlSession可以理解为程序与数据库打交道的一个工具,通过它,程序可以往数据库发送SQL执行。
SqlSession代码如下
public interface SqlSession extends Closeable {
<T> T selectOne(String statement);
<T> T selectOne(String statement, Object parameter);
<E> List<E> selectList(String statement);
<E> List<E> selectList(String statement, Object parameter);
//其余增删查改方法略…
}
来源:https://blog.csdn.net/qq32933432/article/details/104351587
猜你喜欢
- 本文实例为大家分享了Android购物分类效果展示的具体代码,供大家参考,具体内容如下SecondActivity.javapublic c
- 大致分为以下几个方面:一些查询指令整理使用SQL语句进行特殊查询检测表字段是否存在数据库升级数据库表字段赋初始值一、查询指令整理1.链式执行
- WPF换肤的设计原理,利用资源字典为每种皮肤资源添加不同的样式,在后台切换皮肤资源文件。截图上图中,第一张图采用规则样式,第二张图采用不规则
- 1.过滤器 (Filter)过滤器的配置比较简单,直接实现Filter 接口即可,也可以通过@WebFilter注解实现对特定URL拦截,看
- 不废话了,直接给大家贴代码了。class term { String str; int id; &
- 本文实例讲述了java实现的RSA加密算法。分享给大家供大家参考,具体如下:一、什么是非对称加密1、加密的密钥与加密的密钥不相同,这样的加密
- 1、添加一个App.config配置文件。2、配置服务http://Lenovo-PC:80/EvisaWS/WharfService?ws
- 一、树的概念和结构1.1 树的概念树是一种非线性的数据结构,它是由 n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因
- 如何打印GC日志排查问题在工作当中,有时候我们会需要打印GC的相关信息来定位问题。该如何做呢?先来看个示例public static voi
- 1.Action中的validate()方法Struts2提供了一个Validateable接口,这个接口中只存在validat
- 导入thymeleaf<dependency> <groupId>org.springframework
- 安卓开发网络请求可谓是安卓开发的灵魂,如果你不会网络请求,那么你开发的应用软件就是一具没有灵魂的枯骨。在安卓开发中进行网络请求和java中的
- 问题在本地启动dubbo时,服务注册在本地的zookeeper ,但是注册IP却不是本地的iP。产生问题,导致consumer 找不到pro
- 在我们平时的工作中,查询列表在我们的系统中基本随处可见,那么我们如何使用jpa进行多条件查询以及查询列表分页呢?下面我将介绍两种多条件查询方
- 关于“标签PDF文件(Tagged PDF)标签PDF文件包含描述文档结构和各种文档元素顺序的元数据,是一种包含后端提供
- 一、理解slf4j(Simple Logging Facade for Java),表示为java提供的简单日志门面,更底层一点说就是接口。
- [java]public static Bitmap getBitmapFromServer(String imagePath) { &nb
- 前言:在Java8支持Lambda表达式以后,为了满足Lambda表达式的一些典型使用场景,JDK为我们提供了大量常用的函数式接口。它们主要
- 求一个n阶行列式,一个比较简单的方法就是使用全排列的方法,那么简述以下全排列算法的递归实现。首先举一个简单的例子说明算法的原理,既然是递归,
- java文件输出流是一种用于处理原始二进制数据的字节流类。为了将数据写入到文件中,必须将数据转换为字节,并保存到文件。package com