什么是缓存:
缓存(cache),数据交换的缓冲区,当应用程序需要读取数据时,先从数据库中将数据取出,放置在缓冲区中,应用程序从缓冲区读取数据。
特点:数据库取出的数据保存在内存中,具备快速读取和使用。
限制:读取时无需再从数据库获取,数据可能不是最新的。
MyBatis 缓存的功能:减少 Java Application 与数 据库的交互次数,从而提升程 序的运行效率。
缓存的适用性:
适合使用缓存:
1.经常查询并且不经常改变的
2.数据的正确与否对最终结果影响不大的
比如:一个公司的介绍,新闻等
不适合用于缓存:
1.经常改变的数据
2.数据的正确与否对最终结果影响很大
比如商品的库存,股市的牌价等
MyBatis 缓存分类:
一级缓存:会话 session 级别的缓存,针对一 次会话操作内;
二级缓存:映射器级别的缓存,针对不同 Namespace 的映射器;
自定义缓存:根据各类不同的缓存机制,自定义缓存的实现方式。
一级缓存:
Mybatis对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓存,一级缓存只是相对于同一个SqlSession而言。所以在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用一个Mapper方法,往往只执行一次SQL,因为使用SelSession第一次查询后,MyBatis会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新,并且缓存没有超时的情况下,SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库。
注意:当调用sqlsession的修改,添加,删除,commit(),close() 等方法是, 就会清空一级缓存
一级缓存失效情况:
不同SqlSession对应不同的一级缓存
同一个SqlSession单查询条件不同
同一个SqlSession两次查询期间执行了任何一次增删改操作
同一个SqlSession两次查询期间手动清空了缓存
二级缓存:
Mybatis默认对二级缓存是关闭的,一级缓存默认开启,如果需要开启只需在mapper上加入配置就好了。Executor是执行查询的最终接口,它有两个实现类一个是BaseExecutor另外一个是CachingExecutor。CachingExecutor(二级缓存查询),一级缓存因为只能在同一个SqlSession中共享,所以会存在一个问题,在分布式或者多线程的环境下,不同会话之间对于相同的数据可能会产生不同的结果,因为跨会话修改了数据是不能互相感知的,所以就有可能存在脏数据的问题,正因为一级缓存存在这种不足,需要一种作用域更大的缓存,这就是二级缓存。
一个事务方法运行时,数据查询出来,缓存在一级缓存了,但是没有到二级缓存,当事务提交后(sqlSession.commit()),数据才放到二级缓存。查询的顺序是,先查二级缓存再查一级缓存然后才去数据库查询。一级缓存作用域是SqlSession级别,所以它存储的SqlSession中的BaseExecutor之中,但是二级缓存目的要实现作用范围更广,所以要实现跨会话共享,MyBatis二级缓存的作用域是namespace,专门用了一个装饰器来维护,这就是:CachingExecutor。
二级缓存失效:
所有的update操作(insert,delete,uptede)都会触发缓存的刷新,从而导致二级缓存失效,所以二级缓存适合在读多写少的场景中开启。二级缓存针对的是同一个namespace,所以建议是在单表操作的Mapper中使用,或者是在相关表的Mapper文件中共享同一个缓存。
二级缓存总结:
1.Mybatis 的二级缓存相对于一级缓存来说,实现了缓存数据的共享,可控性也更强;
2.极大可能会出现错误数据,有设计上的缺陷,安全使用的条件比较苛刻;
3.分布式环境下,必然会出现读取到错误数据,所以不推荐使用;