如何实现缓存
一级高速缓存
辅助缓存
判例的实际技巧
1 .一级缓存
基于PerpetualCache的HashMap本地缓存。 mybatis内部实现了一个cache接口,其存储范围为Session,在Session flush或close之后,该Session中的所有cache都为空。
2 .二级高速缓存
l1缓存机制相同,默认情况下是使用PerpetualCache的HashMap存储,但存储范围为mapper(namespace ),可以自定义存储源,如Ehcache
对于缓存数据更新机制,在执行范围[主缓存会话/辅助缓存Namespaces的C/R/U/D操作时,默认情况下,该范围下的所有选择的缓存都将被清除
打开辅助缓存时,首先从辅助缓存中查询数据,如果位于辅助缓存中,则从辅助缓存中检索数据。 如果不在辅助缓存中,则查找主缓存中是否存在缓存数据;如果不在主缓存中,则查询数据库。
3.l2缓存限制
我的总线l2缓存不适用于细粒度数据级缓存,需要缓存商品信息。 虽然访问商品信息的次数很多,但每次都被要求访问最新的商品信息。 在这种情况下,使用“我的公共汽车”的l2高速缓存,当一个商品发生变化时,不能只更新该商品的高速缓存信息,而不更新其他商品的信息。 由于mybaits的二级缓存区域以映射器为单位进行分隔,因此当一个商品信息发生变化时,所有商品信息的缓存数据都将为空
4.l1缓存(默认打开) ) ) ) ) )。
默认情况下,Mybatis提供一级缓存,缓存范围为sqlSession。 在同一个SqlSession上,运行同一sql查询两次,第二次不再从数据库中查询。
原理:主缓存采用Hashmap存储,当mybatis执行查询时,它从缓存中执行查询,如果缓存中没有来自数据库的查询。 如果SqlSession执行clearCache ()提交或添加删除更改操作,请清除缓存。
默认存在,知道观察结果即可
a .缓存存在情况(会话未提交) ) ) ) ) ) ) ) ) )。
@Test
公共语音te st01 (
sqlsessionsqlsession=sqlsessionfactory.open session (;
accountdaoaccountdao=SQL session.get mapper (account Dao.class );
帐户帐户=帐户Dao.queryaccountbyid (1;
系统. out.println (account );
accountDao.queryaccountbyid(1;
}
日志中只打印一个sql
b .高速缓存闪存
在Session提交时更新缓存数据
@Test
公共语音测试02 (
sqlsessionsqlsession=sqlsessionfactory.open session (;
accountdaoaccountdao=SQL session.get mapper (account Dao.class );
帐户帐户=帐户Dao.queryaccountbyid (1;
系统. out.println (account );
sqlSession.clearCache (;
accountDao.queryaccountbyid(1;
}
效果:
5 .二级高速缓存
l1缓存位于同一sqlSession中,l2缓存位于同一namespace中,因此可以在同一namespace的不同sqlSession中使用l2缓存。
使用场景
建议对查询频率高、更改频率低的数据使用l2缓存。
如果用户对访问次数较多的查询请求且对查询结果的实时性要求不高,可以采用mybatis二级缓存技术减少数据库访问次数并提高访问速度。 例如,耗时的统计分析sql、电话发票查询sql等业务场景。
全局文件配置(mybatis.xml )
在Mapper.xml中添加:以打开mapper的l2缓存
che标签的通用属性
eviction='FIFO '
flushInterval='60000 '
size='512 '
只读=' true ' /
说明:
将缓存映射语句文件中的所有select语句。
映射文档中的一切
insert,update 和 delete 语句会刷新缓存。缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。
缓存会根据指定的时间间隔来刷新.
缓存会存储 1024 个对象
PO 对象必须支持序列化
public class User implements Serializable {
}
关闭 Mapper 下的具体的 statement 的缓存
使用 useCache:默认为 true
useCache="false">
SELECT * FROM user WHERE id=#{id}
刷新二级缓存
操作 CUD 的 statement 时候,会强制刷新二级缓存 即默认 flushCache="true" ,如果想关闭设定为 flushCache="false"即可 ,不建议关闭刷新,因为操作更新删除修改,关闭后容易获取脏数据。
二级缓存测试:
@Test
public void test03() {
SqlSession sqlSession=sqlSessionFactory.openSession();
AccountDao accountDao=sqlSession.getMapper(AccountDao.class);
Account account=accountDao.queryAccountById(1);
System.out.println(account);
sqlSession.close();
SqlSession sqlSession2=sqlSessionFactory.openSession();
AccountDao accountDao2=sqlSession2.getMapper(AccountDao.class);
accountDao2.queryAccountById(1);
sqlSession.close();
}
效果:
扩展
分布式缓存 ehcache
如果有多条服务器 ,不使用分布缓存,缓存的数据在各个服务器单独存储,不方便系统开发。所以要使用分布式缓存对缓存数据进行集中管理。因此可是使用 ehcache memcached redis
mybatis 本身来说是无法实现分布式缓存的,所以要与分布式缓存框架进行整合。 EhCache 是一个纯 Java 的进程内缓存框架,具有快速、精干等特点;Ehcache 是一种广泛 使用的开源 Java 分布式缓存。主要面向通用缓存,Java EE 和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个 gzip 缓存 servlet 过滤器,支持 REST 和 SOAP api 等特点。
Jar 依赖
net.sf.ehcache
ehcache-core
2.4.4
org.mybatis.caches
mybatis-ehcache
1.0.3
缓存接口配置
在 src 下 加入 ehcache.xml(不是必须的没有使用默认配置)
xsi:noNamespaceSchemaLocation="../mgdrs/ehcache.xsd">
测试:
@Test
public void test04() {
SqlSession sqlSession=sqlSessionFactory.openSession();
AccountDao accountDao=sqlSession.getMapper(AccountDao.class);
Account account=accountDao.queryAccountById(1);
System.out.println(account);
sqlSession.close();
SqlSession sqlSession2=sqlSessionFactory.openSession();
AccountDao accountDao2=sqlSession2.getMapper(AccountDao.class);
accountDao2.queryAccountById(1);
sqlSession.close();
}
效果:
Cache Hit Ratio [com.xxx.dao.AccountDao]:0.5