MyBatis 源码分析-end-知识点总结

Version :

  • MyBatis : 3.5.5

  • 项目地址 :MyBatis-source-learn

  • PS: 若文章字体偏大或者偏小,建议通过 ctrl键+鼠标滑轮 进行修改,以提升阅读效果.(带来不便,请谅解!)

本文将分享自己的源码阅读技巧以及MyBatis 相关知识的总结.

  • PS: 若文章字体偏大或者偏小,建议通过 ctrl键+鼠标滑轮 进行修改,以提升阅读效果.(带来不便,请谅解!)

源码如何阅读

我自己的阅读方式是: 通过maven 将 mybatis-source.jar 下载下来,然后 解压到文件夹mybatis-source中, 再利用IDEA 中project structure -> library 更换source 文件的方式将 maven下载的jar包换掉,然后自己就可以愉快的阅读源码, 加注释,自己进行修改了.

image-20210325005925098

注意: 由于源码不是自己编译的,所以在添加注释时,需要与源码原来的行号保持对齐,不然就等着debug时候哭

Mybatis 内容整理

生成MappedStatement

**原文地址: ** MyBatis 源码分析-01-解析SQL

image-20210325143114110

解析XML 生成 mappedStatement:
解析xml 文件
	-> 解析 <mapper/> 标签
    	-> 解析 单个节点
    		->生成SQL (1.处理方法参数) 生成类似于  select * from blog where id =? 
    		-> 处理主键
    		-> 处理 statement 类型
    		-> 处理 resultset
    		-> 生成 mappedstatement
解析Annotation 生成mappedstatement:

遍历接口 的每一个方法 ,通过解析注解的形式生成mappedstatement

获取SqlSession

原文地址: MyBatis 源码分析-02-生成实例MapperProxy 代理对象

image-20210325150253542

1. 创建事务 transaction( 利用 TransactionFactory 创建)
2. 创建 Executor ( 默认SimpleExecutor -> CachingExecutor (原因 :mybatis中cacheEnabled的默认值为true))
3. 创建sqlsession

生成MapperProxy

没啥好说的, 利用JDK 代理生成 MapperProxy.

MyBatis 查询流程:

**原文地址: **MyBatis 源码分析-03 - MyBatis 方法执行流程分析

img

  • MyBatis 在不修改默认配置项时, 其查询顺序为:

二级缓存 CachingExecutor.cache -> 一级缓存 Executor.localCache -> DB

  • 一级缓存 LocalCache: localCacheScope= session( default), 建议修改为 statement ,session 存在脏读现象
  • 二级缓存 Cache: cacheEnabled=true(default), 对应xxxMapper.xml 添加 即可使用,使用二级缓存,可以有效避免在单表查询时出现的脏读现象,但是在多表查询时,极大可能出现脏数据,存在缺陷.

Mybatis 生成 statement:

**原文地址: **MyBatis 源码分析-04-MyBatis Statement 的生成流程

image-20210322114548948

流程描述:
1. 生成 statementHandelr(resultSethandler,) 
   1. StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
2. 生成 Statement
   1. stmt = prepareStatement(handler, ms.getStatementLog());//对statement 进行处理,绑定参数到sql中
      1. 获取Connection :  getConnection(statementLog)
      2. 生成Statement , 绑定 方法参数
         1. 实例化Statement: stmt = handler.prepare(connection, transaction.getTimeout());
            结果: stmt = com.mysql.cj.jdbc.ClientPreparedStatement: select * from Blog where id = ** NOT SPECIFIED **
         2. 处理方法参数 : handler.parameterize(stmt);// 处理参数 绑定 sql - java type
            结果:  stmt= com.mysql.cj.jdbc.ClientPreparedStatement: select * from Blog where id = 1

Mybatis 处理ResultSet:

image-20210325162100794

原文地址:MyBatis 源码分析-05 - MyBatis ResultSet 处理流程分析

处理行数据rowValue 流程:

1 . 实例化 resultObject

  1. 将 数据表字段与JavaBean 属性名称 相互绑定
  2. 利用 反射生成 setter 方法 进行赋值

MyBatis 一级缓存:

  1. MyBatis一级缓存的生命周期和SqlSession一致。
  2. MyBatis一级缓存内部设计简单,只是一个没有容量限定的HashMap,在缓存的功能性上有所欠缺。
  3. MyBatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,数据库写操作会引起脏数据,建议设定缓存级别为Statement。

Mybatis 二级缓存:

在分布式系统中不建议使用, 缓存可以通过redis 等形式实现, 因为 二级缓存在 多表联合查询时会存在脏读现象

参考:

https://tech.meituan.com/2018/01/19/mybatis-cache.html