表面上我们的就是Sql语句和我们的java对象进行映射,然后Mapper代理然后调用方法来操作数据库
底层的话我们就涉及到Sqlsession和Configuration
首先说一下SqlSession, 它可以被视为与数据库交互的一个会话,用于执行 SQL 语句(Executor执行器) 、获取映射器(Mapper) 、管理事务等操作
然后还有个全局配置Configuration,Configuration是Mybatis的核心配置类,里面有所有的配置信息,映射文件内容,甚至数据库连接池配置
SqlSession
也就是说我们的通过SqlSession来操作我们的数据库,SqlSession里面的执行器Executor来执行我们的具体的sql语句
我们的Executor其实有三种SimpleExecutor简单执行器,ReuseExecutor可重用执行器, BatchExecutor批量执行器
一个是每次使用都创建一个Statement对象,一个是可以以sql作为Key在Map<String,Statement>内查找我们的statement对象进行重用,一个是将所有的sql语句添加到批处理等待逐一执行
Configuration
很简单,就是一个mybatis的核心配置类,我们的主要的配置信息例如数据库连接池配置就在里面
再深入一点就讲一下我们的Mybatis的一二级缓存实现原理
一级缓存(在Sqlsession对象了里面):
我们有的话就用Executor执行器,从LocalCache里面查询,没有的话就从数据库中查然后放到我们的LocalCache里面
在分布式或者多个Sqlsession的情况下,可能会导致脏读问题
我们查询的时候会从Sqlsession的缓存里面查,那要是我们此时用SqlSession1和SqlSession2,我们要的数据在SqlSession2的缓存里面怎么办?我们一级缓存不能实现跨SqlSession,只能查不到然后查数据库
所以为了进一步优化多个SqlSession问题,我们就有了二级缓存
二级缓存(在Configuration里面):
在一级缓存查询之前,我们先通过CachingExecutor从二级缓存中进行查询
开启二级缓存之后呢,会被多个Sqlsession共享,所以它是一个全局的缓存
所以查询流程变成了:先查二级缓存,再查一级缓存,再查数据库
二级缓存对比一级缓存,它实现了Sqlsession之间的缓存数据的 共享
既然二级缓存可以优化查询?那为什么不默认用二级缓存?
数据一致性问题
- 问题描述:二级缓存是跨SqlSession的,多个SqlSession共享同一个缓存。如果某个SqlSession更新了数据库,其他SqlSession可能仍然使用缓存中的旧数据,导致数据不一致。
- 解决方案 :可以通过配置缓存的刷新策略(如
flushInterval
)或在更新操作后手动清除缓存来缓解。
2. 缓存失效问题
- 问题描述 :当执行增删改操作时,MyBatis会清除相关缓存。但如果 其他系统或程序 直接修改了数据库,MyBatis无法感知,导致缓存中的数据与实际数据库不一致。
- 解决方案:需要结合其他机制(如数据库触发器或消息队列)来通知缓存失效。
3. 内存占用问题
- 问题描述 :二级缓存默认存储在内存中,如果缓存的数据量过大,可能导致内存溢出(OOM)。
- 解决方案:可以通过配置缓存实现(如Ehcache、Redis)将缓存存储到磁盘或分布式缓存中。
4. 序列化问题
- 问题描述 :二级缓存默认需要缓存对象实现 Serializable****接口 ,以便序列化存储。如果对象未实现序列化接口,会导致缓存失败。
- 解决方案 :确保所有缓存对象实现
Serializable
接口,或使用自定义的缓存实现。
5. 缓存粒度问题
- 问题描述 :二级缓存的粒度是Mapper级别的,即一个Mapper的缓存会被所有查询共享。如果某个Mapper的查询结果差异较大,可能导致缓存命中率低,甚至缓存污染。
- 解决方案:可以通过自定义缓存键或使用更细粒度的缓存策略来优化。
6. 分布式环境下的问题
- 问题描述 :在分布式环境中,默认的二级缓存是 本地缓存,不同节点之间的缓存无法共享,可能导致数据不一致。
- 解决方案:使用分布式缓存(如Redis、Memcached)替换默认的本地缓存。
7. 缓存配置复杂
- 问题描述 :二级缓存的配置相对复杂,需要根据业务场景调整缓存策略(如缓存清除策略、缓存刷新间隔等),配置不当可能导致性能下降或数据不一致。
- 解决方案:仔细评估业务需求,合理配置缓存参数。
8. 不适合高并发写场景
- 问题描述 :在高并发写场景下,频繁的增删改操作会导致 缓存频繁失效 , 反而降低性能。
- 解决方案:在高并发写场景下,建议禁用二级缓存,或使用更高效的缓存策