Mybatis源码阅读笔记

193 阅读2分钟

SqlSession下的四大对象

Executor:执行器

StatementHandler:封装jdbc的statement执行Sql

ParameterHandler:Sql参数处理

ResultHandler:结果封装

前期准备

mybatis的起始操作都是在操作SqlSession,阅读源码时,以此为突破口。

1、获取Mapper对象

工程启动时将扫描到的mybatis mapper接口添加到map集合里

2、将解析好的MapperMethod,添加到map集合methodCache中

3、使用autowired或者其他方式触发装载时,将mapper接口从map中取出并实例化为一个MapperProxy对象。

4、将xml中的方法解析成MappedStatement对象放入mappedStatements 注意:无法对mapper的接口方法进行重载,xml中方法的定位时根据类名+方法名定位的

SqlSession 执行

1、执行mapper的方法即为执行代理MapperProxy的invoke方法

2、取出对应的MapperMethod方法

3、执行MapperMethod方法

发现中途执行了代理类

找到代理类的初始化位置

再找到下一个执行位置:DefaultSqlSession的SelectList方法

4、根据id(类名+方法名)找到xml中方法封装成的MappedStatement对象

5、调用Executor执行查询

6、SQL参数处理

7、使用Statement执行sql

8、使用ResultHandler封装结果集

利用反射通过构造函数构造生成实例

在没有在xml中显示使用构造函数的情况下,默认使用无参构造函数创建实例,若没有无参构造函数会抛出异常

赋值根据反射获取属性的set方法赋值,没有set方法抛出异常

延迟加载

延迟加载只适用使用association和collection的嵌套查询,关联查询不会触发延迟加载。

lazyLoadingEnabled:true

aggressiveLazyLoading: false 侵入式延迟加载:
使用任何数据包括主数据就会触发查询。

aggressiveLazyLoading: true 深度延迟加载:
只有使用到关联数据才会触发查询。

使用动态代理封装返回结果,在调用get,clone,equals,toString等方法时,判断是否已经加载过,未加载过则执行sql查询

缓存

一级缓存(本地缓存)

localCacheScope:session/statement

一次sql会话中,执行多次完全完全相同的sql,会命中一级缓存

mbatis默认开启一级缓存,默认级别为session,在分布式环境下可能会产生脏数据,建议使用statement。

BaseExecutor.localCache HashMap维护 key:CacheKey 根据类名+方法名+偏移量offset+limit+sql组成

在执行Insert、Update、Delete后会清空缓存

二级缓存

CachingExecutor

多个sqlSession在同一个namespace之间共享缓存,也可以通过cache-ref关联 其他的namespace

只有sqlsession提交后才会进入缓存,表空间中涉及任何的delete\update\insert操作提交都会清除缓存。

不同表空间操作同一个表的数据容易产生脏数据。