为什么要用缓存?
将数据存放在程序内存(缓存)中,用于减轻数据查询的压力,提升读取数据的速度,提高性能。
一级缓存
Mybatis一级缓存实际上就是一个依赖于SqlSession的缓存对象。
具体来说就是将查询到的结果以Map(K,V)的形式存在于缓存区中。
public class PerpetualCache implements Cache {
private final String id;
private Map<Object, Object> cache = new HashMap<Object, Object>();
}
一级缓存默认开启状态。
举例:
@Test
void select(){
Start st=t.selectById(1);
System.out.println("第一次查询:");
System.out.println(st);
Start s=t.selectById(1);
System.out.println("第二次查询:");
System.out.println(s);
}
第一次查询:
17:21:32.483 [main] DEBUG com.example.mytest01.dao.t_tempDao.selectById - ==> Preparing: select * from t_emp where username=?
17:21:32.605 [main] DEBUG com.example.mytest01.dao.t_tempDao.selectById - ==> Parameters: 1(Integer)
17:21:32.695 [main] DEBUG com.example.mytest01.dao.t_tempDao.selectById - <== Total: 1
com.sun.proxy.$Proxy80
Start{username='01', name='123', password='1234', sex='男', birthday='2004-02-01', hire_date='2000-03-05', position='主管', qualification='本科', experience='null', currentPage=0, flag='2', super_id='null'}
第二次查询:
com.sun.proxy.$Proxy80
Start{username='01', name='123', password='1234', sex='男', birthday='2004-02-01', hire_date='2000-03-05', position='主管', qualification='本科', experience='null', currentPage=0, flag='2', super_id='null'}
注意:
如果SqlSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用;
如果SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍可使用;
SqlSession中执行了任何一个update操作(update()、delete()、insert()) ,都会清空PerpetualCache对象的数据,但是该对象可以继续使用
二级缓存
二级缓存,数据仍是以Map集合形式保存。
二级缓存的生命周期是整个应用的周期。
二级缓存开启条件
1.实体类需要实现序列化接口Serializable
2.打开二级缓存的开关
- 总开关(mybatis.xml中需要设置cacheEnable值为true)
- 局部开关(mapper.xml中需要设置
<case/>
标签) - 细节开关——针对某一个方法(查询标签中的useCase属性,默认为false)
当开启二级缓存后,数据的查询执行的流程就是二级缓存-> 一级缓存 -> 数据库
@Test
void select(){
System.out.println("第一次查询:");
Start st=t.selectById(1);
System.out.println(st);
System.out.println("第二次查询:");
Start s=t.selectById(1);
System.out.println(s);
}
第一次查询:
22:50:28.141 [main] DEBUG com.example.mytest01.dao.t_tempDao - Cache Hit Ratio [com.example.mytest01.dao.t_tempDao]: 0.0
22:50:29.187 [main] DEBUG com.example.mytest01.dao.t_tempDao.selectById - ==> Preparing: select * from t_emp where username=?
22:50:29.222 [main] DEBUG com.example.mytest01.dao.t_tempDao.selectById - ==> Parameters: 1(Integer)
22:50:29.247 [main] DEBUG com.example.mytest01.dao.t_tempDao.selectById - <== Total: 1
Start{username='01', name='123', password='1234', sex='男', birthday='2004-02-01', hire_date='2000-03-05', position='主管', qualification='本科', experience='null', currentPage=0, flag='2', super_id='null'}
第二次查询:
22:50:29.402 [main] DEBUG com.example.mytest01.dao.t_tempDao - Cache Hit Ratio [com.example.mytest01.dao.t_tempDao]: 0.5
Start{username='01', name='123', password='1234', sex='男', birthday='2004-02-01', hire_date='2000-03-05', position='主管', qualification='本科', experience='null', currentPage=0, flag='2', super_id='null'}
第一次查询时,会从缓存区中进行查找,由于缓存区没有,命中率为零。
第二次查询时,从缓存区中查找到值,命中率变为50%。