大家好,又见面了,我是你们的朋友全栈君。
mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。mybaits提供一级缓存和二级缓存。
一级缓存
一级缓存是sqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。
一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。Mybatis默认开启一级缓存。
二级缓存
二级缓存是mapper级别的缓存,多个sqlSession去操作同一个Mapper的sql语句,操作数据库得到数据会存在二级缓存区域。多个sqlSession可以共用二级缓存,二级缓存是跨sqlSession的。
二级缓存是多个sqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。Mybatis默认没有开启二级缓存,需要在setting全局参数中配置开启二级缓存。
Spring 中的缓存
Spring与MyBatis整合时,MyBatis的一级缓存在没有事务存在的时候失效。
在未开启事务的情况之下,每次查询,spring都会关闭旧的sqlSession而创建新的sqlSession,因此此时的一级缓存是没有启作用的。
在开启事务的情况之下,spring使用threadLocal获取当前资源绑定同一个sqlSession,因此此时一级缓存是有效的。
SpringBoot中默认帮我们全局开启了二级缓存,如果想要使用二级缓存还需要在mapper上注明。
注解版使用@CacheNamespace注解(为给定的命名空间(比如类)配置缓存,对应xml<cache>)在该mapper上使用二级缓存。
@CacheNamespace
@CacheNamespace注解主要用于mybatis二级缓存,等同于<cache>属性。默认情况下,MyBatis 3 没有开启二级缓存,要开启二级缓存,需要在SQL 映射文件(mapper.xml)中添加一行:
代码语言:javascript复制<mapper namespace="cn.mybatis.mydemo.mapper.StudentMapper">
<cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"></cache>
</mapper>
当然,前提还需要在全局配置文件中开启缓存:
代码语言:javascript复制<setting name="cacheEnabled" value="true"/>
CacheNamespace是注解,其源码如下所示:
代码语言:javascript复制@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface CacheNamespace {
Class<? extends org.apache.ibatis.cache.Cache> implementation() default PerpetualCache.class;
Class<? extends org.apache.ibatis.cache.Cache> eviction() default LruCache.class;
long flushInterval() default 0;
int size() default 1024;
boolean readWrite() default true;
boolean blocking() default false;
Property[] properties() default {};
}
配置文件和接口注释配合使用时,需要在xml配置文件中配置<cache>属性, 同时在接口中修改注释为@CacheNamespaceRef。
@CacheNamespaceRef
Java里面没有指针,但是Java里面有引用,CacheNamespaceRef就是一个引用。它是谁的引用呢?请看源码注释:
A namespace type to reference a cache (the namespace name become a FQCN of specified type) FQCN = Full Qualified Class Name
上面的意思就是想说明:CacheNamespaceRef当做CacheNamespace的短链接、快捷键,它是CacheNamespace的引用。
代码语言:javascript复制@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface CacheNamespaceRef {
/**
* A namespace type to reference a cache (the namespace name become a FQCN of specified type)
*/
Class<?> value() default void.class;
/**
* A namespace name to reference a cache
* @since 3.4.2
*/
String name() default "";
}
查看注解源码,value就是当前类,name是使用的Mapper接口的全限定名,以下三种写法都可以:
CacheNamespaceRef的作用:
我们知道,MyBatis分为一级缓存和二级缓存。一级缓存是会话(session)级别的,二级缓存是应用(application)级别的。但是,MyBatis并不是简单地对整个Application就只有一个Cache缓存对象,它将缓存划分的更细,即是Mapper级别的,即每一个Mapper都可以拥有一个Cache对象,具体如下: (1)为每一个Mapper分配一个Cache缓存对象(使用<cache>节点配置或者 @CacheNamespace注解 ); (2)多个Mapper共用一个Cache缓存对象(使用<cache-ref>节点配置或者本文所提到的@CacheNamespaceRef注解);
Mybatis 二级缓存示意图:
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/143416.html原文链接:https://javaforall.cn