mybatis一级缓存二级缓存
一级缓存
mybatis中的一级缓存也就是SqlSession级别的缓存(也就是作用域在SqlSession中),在没有配置的情况下,它会默认的开启一级缓存。也就是在操作数据库的时候需要构造一个SqlSession,在这个对象中有一个HashMap用于储存缓存数据,不同的SqlSession之间的缓存区域是相互不影响的。
一、
一级缓存的作用域在SqlSession中,当SqlSession 执行两次查询操作的时候,第一次的时候它会从数据库中查询写到缓存(内存)中
第二次查询的时候,它会先根据 Cachekey 对象查找缓存 ,而不是从数据库中查找,从而提高了性能。
注意:当SqlSession 关闭或执行 insert、delete、update 的时候会清空缓存中的数据。
二、
1、MyBatis在开启一个数据库会话时,会 创建一个新的SqlSession对象,SqlSession对象中会有一个新的Executor对象。Executor对象中持有一个新的PerpetualCache对象;当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉。
2、如果SqlSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用。
3、如果SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍可使用。
4、SqlSession中执行了任何一个update操作(update()、delete()、insert()) ,都会清空PerpetualCache对象的数据,但是该对象可以继续使用
mybatis认为,对于两次查询,如果以下条件都完全一样,那么就认为它们是完全相同的两次查询。
1、 传入的statementId
2、 查询时要求的结果集中的结果范围
3、 这次查询所产生的最终要传递给JDBC java.sql.Preparedstatement的Sql语句字符串(boundSql.getSql() )
4 、传递给java.sql.Statement要设置的参数值
扩展:
Executor 是 Mybatis 的核心接口之一,其中定义了数据库操作的基本方法。在实际应用中经常涉及的SqlSession接口的功能,都是基于Executor接口实现的
PerpetualCache:一级缓存最终会保存在PerpetualCache维护的一个Map中
public abstract class BaseExecutor implements Executor {
protected PerpetualCache localCache;
public class PerpetualCache implements Cache {
private Map<Object, Object> cache = HashMap<Object, Object>();
二级缓存
mybatis中的二级缓存是mapper级别的缓存也和一级缓存一样,第一次执行完毕会将数据库中查询的数据写到缓存,第二次查询会从缓存中获取数据,不再去底层数据库查询,从而提高效率。
二级缓存的区域是按照namespace分的,如果两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同 的二级缓存区域中
而和一级缓存的区别 在于,二级缓存的范围更大,多个SqlSession可以共用一个mapper缓存区域。
mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓存。
在核心配置文件SqlMapConfig.xml中加入
在核心配置文件SqlMapConfig.xml中加入
<!-- 全局配置参数,需要时再设置 -->
<settings>
<!-- 打开延迟加载 的开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 将积极加载改为消极加载即按需要加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
在UserMapper.xml中开启二缓存,UserMapper.xml下的sql执行完成会存储到它的缓存区域(HashMap)
<mapper>
<cache/> ---> //这个就是开启二级缓存
</mapper>
二级缓存应用场景
对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。
实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。
二级缓存局限性
mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存
第三方 缓存 框架 ehcache
在分布式开发上,mybatis是无法进行分布式缓存的,需要和其他的缓存框架进行整合 而这里使用 ehcache
1、需要加入jar包 ehcache 和 mybatis-ehcache 整合包
2、需要创建ehcache.xml 配置文件
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore path="F:\develop\ehcache" />
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
3、配置mapper中的cache中的type为ehcache对cache接口的实现类型
<!-- 开启本mapper的namespace下的二缓存
type:指定cache接口的实现类的类型,mybatis默认使用PerpetualCache
要和ehcache整合,需要配置type为ehcache实现cache接口的类型
-->
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>