-
缓存
缓存(即cache)的作用是为了减去数据库的压力,提高数据库的性能。缓存实现的原理是从数据库中查询出来的对象在使用完后不销毁,而是存储在内存(缓存)中,当再次需要获取该对象时,直接从内存中获取,不再向数据库执行select语句,减少对数据库的查询次数,提高了数据库的性能。缓存是使用Map集合存储数据,mybatis默认两级缓存,一级缓存,和二级缓存。
-
一级缓存的作用域是同一个SqlSession,在同一个SqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库查询的数据写到缓存(内存),第二次会从缓存中获取数据而不进行数据库查询,大大提高了查询效率。当一个SqlSession结束后该SqlSession中的一级缓存也就不存在了。MyBtais默认开启一级缓存。
MyBatis开启一个数据库会话时,会创建一个新的SqlSession对象,其中有一个新的Executor对象。Executor对象中持有一个新的PerpetualCache对象,当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象会一并释放掉。
-
缓存失效
- 当SqlSession调用close()方法时,SqlSession对象关闭,直接会释放掉一级缓存PerpetualCache对象,一级缓存将不可用。
- 如果SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是SQlSession对象还可以用。
- SqlSession中执行了任何一个update(修改)、delete(删除)、insert(新增)操作,都会清空PerpetualCache对象中的数据,但是SqlSession对象仍然可用。
-
二级缓存(全局缓存)
-
二级缓存的作用域是SqlSessionFactory级别,整个应用程序只有一个。二级缓存区域是根据mapper的namespace划分的,相同的namespace的mapper查询的数据缓存在同一个区域,如果使用mapper代理方法每一个mapper的namespace都不同,此时可以理解为二级缓存区域是根据mapper进行划分的。
-
每次查询都会先从缓存区域查找,如果找不到则从数据库进行查询,并将查询到的数据写入缓存。MyBtais内部缓存使用HashMap,key为hashCode+sqlid+sql语句,value为从查询出来映射生成的java对象。SqlSession执行任何一个update(修改)、delete(删除)、insert(新增)操作commit提交后都会清空缓存区域,防止脏读。
-
二级缓存默认是不开启的,需要进行相应的配置,在Mybatis-config.xml中配置setting, name="cacheEnabled" value="true"
-
POJO序列化,将所有的POJO类(bean)实现序列化接口java.io.Serializable。
-
在Mapper.xml映射文件中添加cache标签,表示次mapper开启二级缓存,也有cache的相应配置。
-
-
不同缓存策略介绍
- FIFO(First In First Out):这种策略是按照对象进入缓存的顺序来移除它们。最早进入的对象会最先被移除。
- LRU(Least Recently Used):最近最少使用的对象会被首先移除。这种策略是基于对象被访问的次数和频率,适用于大部分缓存场景。
- 软引用(Soft Reference):在这种策略下,对象会被封装在软引用中。当JVM内存不足时,这些对象可能会被垃圾回收器回收。
- 弱引用(Weak Reference):类似于软引用,但生命周期更短。在JVM进行垃圾回收时,这些对象更有可能被回收。
-
处理业务时,先去看二级缓存中有没有,再看一级缓存中有没有,如果都没有再去查询数据库,MyBatis 的一级缓存 二级缓存都不建议使用,它们只适用于单体项目,现在基本都是分布式或者微服务 框架使用的话会存在数据不一致问题。
-
mybatis自定义缓存:可以集成很多三方中间件来做缓存
- 添加依赖:
<dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-redis</artifactId> <version>xxx</version> </dependency>
- 配置开启缓存:mybatis-plus.configuration.cache-enabled=true
- 在mapper.xml文件中添加: