mybatis之缓存

缓存的重要性是不言而喻的。 使用缓存, 我们可以避免频繁的与数据库进行交互, 尤其是在查询越多、缓存命中率越高的情况下, 使用缓存对性能的提高更明显。

mybatis 也提供了对缓存的支持, 分为一级缓存和二级缓存。 但是在默认的情况下, 只开启一级缓存(一级缓存是对同一个 SqlSession 而言的)。

一级缓存:sqlsession级别的缓存

                  在操作数据库时,需要构造sqlsession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据

                  不同的sqlsession之间的缓存区域是互相不影响的。

一级缓存工作原理:

 

 

操作过程:

第一次发起查询sql查询用户id为1的用户,先去找缓存中是否有id为1的用户,如果没有,再去数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。

如果sqlsession执行了commit操作(插入,更新,删除),会清空sqlsession中的一级缓存,避免脏读

第二次发起查询id为1的用户,缓存中如果找到了,直接从缓存中获取用户信息

mybatis默认支持一级缓存。

虽然一级缓存时自动开启的,但是和spring整合后就会出现问题。

如果已经和spring整合了,mybatis的一级缓存就会失效,因为spring会自动关闭session,所以一级缓存比较鸡肋。

二级缓存

二级缓存实现原理:

 

 

spring boot+mybatis+ehcache(缓存)整合的简单实例

 

 

 

 

 

 

 

 

 

 

maojianyun2018-06-02 18:30:37

spring boot+mybatis+ehcache(缓存)整合的简单实例

项目描述

spring boot整合mybatis并且加入缓存

运行环境

jdk8+mysql+eclipse+maven

项目技术(必填)

spring boot+mybatis+ehcache缓存

数据库文件

数据库在mybatis/mapper/user.sql中

jar包文件

maven管理

是否原创(转载必填原文地址)

原创

项目截图(必填)

spring boot+mybatis+ehcache(缓存)整合的简单实例

 

spring boot+mybatis+ehcache(缓存)整合的简单实例spring boot+mybatis+ehcache(缓存)整合的简单实例

spring boot+mybatis+ehcache(缓存)整合的简单实例

运行截图(必填)

spring boot+mybatis+ehcache(缓存)整合的简单实例

 

注意事项

1.查询的时候如果是第一次查询会打印出从数据库中查询,进行第二次查询没有答应出说明缓存起作用

2.添加用户成功后,查询添加的用户时没有打印查询数据库说明添加用户时的缓存起作用

2.更新用户成功后,进行查询更新的用户,如果是我们更新的内容说明更新缓存正确

4.删除用户成功后,查询删除的用户会会打印出从数据库中查询数据且没有查到数据说明删除用户时删除缓存起作用了

该代码全部测试通过上面的四个步骤(有的可能需要使用接口调用工具postMain来辅助完成)

 

但是这种二级缓存同样也存在问题:

如果查询和修改一个表中数据的方法不在一个mapper类中,在修改前查询并且在修改后查询时会发现查询出来的数据没有被修改,但是实际上数据库中的数据已经被修改了。
但是如果查询和修改一个表中数据的方法在一个mapper类中,就不会发生上面的问题。
这是因为二级缓存的存储是有命名空间的,这个命名空间的名字就是类全名,不同的命名空间的缓存是有隔离的。

所以在更新缓存的数据时只会更新同一命令名空间的数据,查询出来的数据也是存储在自己的命名空间的缓存中。

所以mybatis的二级缓存也没什么用,通常会使用第三方框架缓存

 

spring mybatis一级缓存失效的具体分析
mybatis和spring整合后以及缓存会失效

这是因为spring会将mybatis的mapper对象放入容器,并且真正的对象其实是一个factroybean对象,只不过返回的是mapper对象的代理对象

 

而且真正执行mapper中的方法时,使用的是一个sqlsession的代理对象去执行的数据库方法,这个对象在执行完mapper中方法的逻辑后会将session关闭

在通过debug模式下进入查询语句时会发现进入的是一个代理对象,这个代理对象正是在容器中对应的一个factroybean对象返回的真正对象

底层依然是原生的mybatis的数据库查询

 

 

接着会到一个SqlSessionTemplate的包装类,执行其中的代理对象的查询方法

 

 

 

 

在查询过后会将session关闭,这也是为什么一级缓存失效的直接原因

 

 

原生mybatis的调用链和spring mybatis的调用链的区别

mybatis–→sqlSession–→defaultSqlSession–→defaultSqlSession.selectList–→sql

spring mybatis–→sqlSession–→sqlSessionTemplate–→sqlSessionTemplate.selectList–→sqlSessionPorxy.select

这里至于为什么要关闭session,是因为sqlSession是已经被spring管理的,并没有暴露给使用者,所以我们是关不了的,这样spring就帮我们管理了,就关闭了。

而在原生的mybatis中我们是很容易拿到sqlSession,所以我们可以手动关闭session。

至于为什么spring不把sqlSession暴露给使用者,也许是太过麻烦,也许是一级缓存太过鸡肋。 


原文链接:https://blog.csdn.net/qq_35262405/article/details/100705567

     http://www.zuidaima.com/share/3917421981895680.htm


 

posted @ 2020-03-05 17:51  你猜lovlife  阅读(119)  评论(0)    收藏  举报