Mybatis思维导图

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 前置准备既然要读MyBatis的源码,那么我们就要先弄清楚MyBatis的入口在哪。这里我们直接写一个标准的MyBatis使用程序,以此来寻找入口分析源码://第一步:读取mybatis-config.xml配置文件InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");//第二步:构建SqlSessionFactorySqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputSt

前置准备
既然要读MyBatis的源码,那么我们就要先弄清楚MyBatis的入口在哪。这里我们直接写一个标准的MyBatis使用程序,以此来寻找入口分析源码:

//第一步:读取mybatis-config.xml配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");

//第二步:构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

//第三步:打开SqlSession
SqlSession session = sqlSessionFactory.openSession();

//第四步:获取Mapper接口对象
UUserInfoMapper uUserInfoMapper = session.getMapper(UUserInfoMapper.class);

//第五步:调用Mapper接口对象的方法操作数据库;
UUserInfo uUserInfo = uUserInfoMapper.selectByPrimaryKey(1);

//第六步:业务处理
log.info("查询结果: " + uUserInfo.getId() + "--" + uUserInfo.getPhone());

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
通过类加载器读取配置文件流

这个地方你替换成为这个也是可以的;

//第一步:读取mybatis-config.xml配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//InputStream inputStream = App.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
1
2
3
或者

Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatisConfig.xml")
1
这个方法更加通用,在web环境和java环境下均可以使用

创建sqlSessionFactory
//第二步:构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
1
2
这个地方使用了建造者模式。build方法返回的实际上是一个DefaultSqlSessionFactory对象(实现了SqlSessionFactory)并持有一个Configuration的引用:

完整过程如下:

总结:

千层饼读法:

第一层:

new SqlSessionFactoryBuilder().build(InputStream)创建了一个SqlSessionFactory对象
第二层:

创建XMLConfigBuilder 对象:new XMLConfigBuilder(Reader reader, String environment, Properties props)
XMLConfigBuilder.parse():解析xml文件获得Configuration对象
new DefaultSqlSessionFactory(Configuration):new 了一个DefaultSqlSessionFactory传入了刚才解析出来的Configuration对象,然后返回这个SqlSessionFactory对象
第三层:解析new XMLConfigBuilder(Reader reader, String environment, Properties props)方法

new XMLMapperEntityResolver():创建了一个XML映射器实体解析器
new XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver):传入XML映射器实体解析器,构造出XPathParser
通过XMLConfigBuilder(XPathParser parser, String environment, Properties props)构造器返回XMLConfigBuilder对象
解析:
XPathParser:XPathParser核心功能是封装了XPath,对表达式进行解析,并转化成为指定的数据类型,其属性如下;

private Document document;
private boolean validation;
private EntityResolver entityResolver;
private Properties variables;
private XPath xpath;

1
2
3
4
5
document:要解析的xml文件被转化成的Document对象。
validation:获取document时是否要开启校验,开启校验的话会根据xml配置文件中定义的dtd文件校验xml格式,默认不开启校验。
entityResolver:实体解析器,用于从本地工程目录中引入dtd文件,而不是根据网络URL去加载校验文件。
variables:mybatis-config.xml配置文件中,节点引入或定义的属性。
xpath:封装的XPath对象,用来解析表达式。
所有构造函数做的事都如下所示:

public XPathParser(InputStream inputStream, boolean validation, Properties variables) {
    commonConstructor(validation, variables, null);
    this.document = createDocument(new InputSource(inputStream));
}

1
2
3
4
commonConstruct()方法初始化了除Document之外的其他类属性,XPath是通过XPathFactory创建的
createDocument用来初始化document

// 将InputSource对象转化为Document对象
private Document createDocument(InputSource inputSource) {
    try {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setValidating(validation);   // 是否要校验由外界传入的值确定
        factory.setNamespaceAware(false);    // 如果要使用mybatis的XSD Schema,此处必须设为true,但源码里是false,说明官方默认用dtd来做校验,舍弃了XSD Schema
        factory.setIgnoringComments(true);   // 默认忽略注释
        factory.setIgnoringElementContentWhitespace(false);  // 只有开启校验才能去除xml中的空白节点,但是不知是否开启校验,所以这里设为了false
        factory.setCoalescing(false);
        factory.setExpandEntityReferences(true);    // 默认开启使用扩展实体引用

        DocumentBuilder builder = factory.newDocumentBuilder();
        builder.setEntityResolver(entityResolver);  // 使用传入的EntityResolver对象
        builder.setErrorHandler(new ErrorHandler() {  // 定义解析xml文档的错误处理器,如果发生了错误或致命错误则直接抛出异常,如果是警告默认不做处理
            @Override
            public void error(SAXParseException exception) throws SAXException {
                throw exception;
            }

            @Override
            public void fatalError(SAXParseException exception) throws SAXException {
                throw exception;                    
            }               

            @Override
            public void warning(SAXParseException exception) throws SAXException {}
        });
        return builder.parse(inputSource);  //开始解析
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
要解析一个xml文件为Document,需要DocumentBuilder类的支持,实际上DocumentBuilder本身就支持多种形式的xml的解析,这里之所以先统一转成InputSource,大概是为了代码简洁一点吧!
DocumentBuilder对象由DocumentBuilderFactory创建,DocumentBuilderFactory可以设置是否校验、是否开启命名空间、是否忽略注释空白节点等,详细可以看上面源码注释。
如果开启了xml格式校验,DocumentBuilder就要设置实体解析器,这里使用了构造函数传入的实体解析器,如果解析xml过程中检测到格式不对或者其他报错,则需要抛出异常信息,所以这里又设置了错误处理器ErrorHandler,对于错误和致命错误直接抛出异常,对于警告则忽略。
MyBatis解析配置文件的本质就是为了获得Configuration对象;
Configuration 对象可以理解是mybatis的XML配置文件在程序中的化身,是MyBatis非常重要的一个对象,里面封装了MyBatis的整个配置信息

建造者模式的使用
DefaultSqlSessionFactory 类的有参构造需传入 Mybatis 核心配置类 Configuration 的对象作为参数,而 Configuration 内容很多,初始化比较麻烦,因此使用了专门的建造者 XMLConfigBuilder 进行创建

把源码看过一遍之后我们大概可以看出来建造者模式的使用结构:

在Mybatis环境的初始化过程中,SqlSessionFactoryBuilder会调用XMLConfigBuilder读取所有的MybatisMapConfig.xml和所有的Mapper.xml文件,构建Mybatis运行的核心对象Configuration对象,然后将该Configuration对象作为参数构建一个SqlSessionFactory对象。
其中XMLConfigBuilder在构建Configuration对象时,也会调用XMLMapperBuilder用于读取*Mapper文件
而XMLMapperBuilder会使用MapperAnnotationBuilder(注解开发)或者XMLStatementBuilder(xml开发)来读取和build所有的SQL语句。
其中在XMLConfigBuilder中的parseConfiguration方法中对Configuration的属性进行装配:

这里就对应了xml配置文件

通过以上源码,我们就能看出,在mybatis的配置文件中:

configuration节点为根节点。
在configuration节点之下,我们可以配置10个子节点, 分别为:properties、typeAliases、plugins、objectFactory、objectWrapperFactory、settings、environments、databaseIdProvider、typeHandlers、mappers。顺序遵从dtd文件约束,解析配置文件完成了之后,都会装配到configuration
Configuration作用:mybatis核心的配置文件内容 ,使用xml转换bean
我们debug到这个方法,可以看到configuration对象的内部结构:

总结一下:

XMLConfigBuilder 类负责创建复杂对象 Configuration,可以视为具体建造者角色,而SqlSessionFactoryBuilder则是以封装式构建 SqlSessionFactory 实例,相当于简化的建造者模式。

打开SqlSession
第一层:

//第三步:打开SqlSession
SqlSession session = sqlSessionFactory.openSession();
1
2
第二层:

调用openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)返回SqlSession 对象
第三层:

configuration.getEnvironment():从configuration配置对象中获取环境environment信息

相当于我们xml文件中的

java中的模型类:

getTransactionFactoryFromEnvironment(environment):根据环境environment信息获取事务工厂TransactionFactory

transactionFactory.newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit):根据数据源、事务隔离级别、是否自动提交来创建事务。其本质就是new了一个JDBC事务

Executor Configuration.newExecutor(Transaction transaction, ExecutorType executorType):根据执行器类型和事务创建执行器Executor对象

默认使用ExecutorType.SIMPLE型
如果配置了二级缓存,则会将执行器进行包装:executor = new CachingExecutor(executor)

将执行器加入拦截器链,循环遍历执行拦截器

这个interceptors是在xml文件中配置的

DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit):根据configuration和Executor创建一个默认的DefaultSqlSession对象并返回。

然后我们来看看详细过程:

获取Mapper接口对象
//第四步:获取Mapper接口对象
UUserInfoMapper uUserInfoMapper = session.getMapper(UUserInfoMapper.class);
1
2
详细过程如下:

执行Mapper接口方法
List stus = mapper.selectSome(1);
1

未完待续。。。
————————————————
版权声明:本文为CSDN博主「十八岁讨厌编程」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zyb18507175502/article/details/129413125

目录
相关文章
|
SQL Java 数据库连接
MyBatis 思维导图,让 MyBatis 不再难懂(一)
MyBatis 思维导图,让 MyBatis 不再难懂(一) 写在前面 与 Hibernate 相比,我无疑更喜欢 Mybatis,就因为我觉得它真的好用,哈哈: 1、它简单上手和掌握; 2、sql语句和代码分开,方便统一管理和优化; 3、当然缺点也有:sql工作量很大,尤其是字段多、关联表多时,更是如此。
1380 0
|
Java 数据库连接 mybatis
mybatis 思维导图,让 mybatis 不再难懂(二)
上一篇文章写了mybatis的基本原理和配置文件的基本使用,这一篇写mybatis的使用,主要包括与sping集成、动态sql、还有mapper的xml文件一下复杂配置等。
1210 0
|
SQL Java 数据库连接
mybatis思维导图整理
MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。
2623 0
|
2月前
|
Java 数据库连接 Maven
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和MyBatis Generator,使用逆向工程来自动生成Java代码,包括实体类、Mapper文件和Example文件,以提高开发效率。
139 2
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
|
2月前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
67 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
|
2月前
|
前端开发 Java Apache
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
本文详细讲解了如何整合Apache Shiro与Spring Boot项目,包括数据库准备、项目配置、实体类、Mapper、Service、Controller的创建和配置,以及Shiro的配置和使用。
473 1
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
|
2月前
|
SQL Java 数据库连接
mybatis使用二:springboot 整合 mybatis,创建开发环境
这篇文章介绍了如何在SpringBoot项目中整合Mybatis和MybatisGenerator,包括添加依赖、配置数据源、修改启动主类、编写Java代码,以及使用Postman进行接口测试。
25 0
mybatis使用二:springboot 整合 mybatis,创建开发环境
|
2月前
|
Java 数据库连接 API
springBoot:后端解决跨域&Mybatis-Plus&SwaggerUI&代码生成器 (四)
本文介绍了后端解决跨域问题的方法及Mybatis-Plus的配置与使用。首先通过创建`CorsConfig`类并设置相关参数来实现跨域请求处理。接着,详细描述了如何引入Mybatis-Plus插件,包括配置`MybatisPlusConfig`类、定义Mapper接口以及Service层。此外,还展示了如何配置分页查询功能,并引入SwaggerUI进行API文档生成。最后,提供了代码生成器的配置示例,帮助快速生成项目所需的基础代码。
138 1
|
3月前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)