Mybatis的缓存
Posted -杨杨杨-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis的缓存相关的知识,希望对你有一定的参考价值。
1.缓存是什么
在 Mybatis 里面,所谓的缓存就是将已经查询过的记录放在内存的缓冲区或文件上,这样如果再次查询,可以通过配置的策略,命中已经查询过的记录,从而提高查询的效率。
Mybatis 的缓存分为一级缓存和二级缓存。
2.一级缓存
一级缓存:所谓的一级缓存就是会话级别的缓存,就是同一个会话,如果已经查询过的数据会保存一份在内存中,如果会话没有关闭,再次调用同样的方法查询,不会再查询数据库,,而是直接从缓存中取出之前查询的数据.。一级缓存默认是打开的,而且是关闭不了的。一下代码,调用了 5 次 findAll 方法,但执行只查询了一次数据库。说明默认一级缓存是打开的。
@Test public void findAll(){ try { //1.获得操作对象 SqlSession session = DbUtils.getSession(); //2.使用 session.获得映射接口的代理对象,这个代理对象是 mybatis 通过StudentMapper.xml 创建的 StudentMapper studentMapper = session.getMapper(StudentMapper.class); List<Student> list = studentMapper.findAll(); List<Student> list1 = studentMapper.findAll(); List<Student> list2 = studentMapper.findAll(); List<Student> list3 = studentMapper.findAll(); List<Student> list4 = studentMapper.findAll(); for(Student s:list4){ System.out.print("姓名:"+s.getSname()); System.out.print(",年龄:"+s.getAge()); System.out.println(",生日:"+s.getBirthday()); } session.commit(); session.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
--重点查看控制台输出了多少条 SQL,来分析一级缓存是存在。
结论:调用了五次方法,查询了五次相同数据。但后台输出的是一条 SQL 语句,说明默
认就支持一级缓存的。
2.1如何清空一级缓存
1.关闭会话.close()
2.进行了操作(增删改),提交了 commit();
3.手工清除缓存 clearCache() 一下代码,手工清除了一次缓存,操作数据一次,所以会查询三次数据库
@Test public void findAll(){ try { SqlSession session = DbUtils.getSession(); StudentMapper studentMapper = session.getMapper(StudentMapper.class); List<Student> list = studentMapper.findAll(); //清除一级缓存 session.clearCache(); List<Student> list1 = studentMapper.findAll(); //操作数据库,一级缓存会清除 studentMapper.deleteByIds(3); List<Student> list2 = studentMapper.findAll(); List<Student> list3 = studentMapper.findAll(); List<Student> list4 = studentMapper.findAll(); for(Student s:list4){ System.out.print("姓名:"+s.getSname()); System.out.print(",年龄:"+s.getAge()); System.out.println(",生日:"+s.getBirthday()); } session.commit(); session.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
3.二级缓存
所谓二级缓存其实就是文件级别的缓存。 有效范围就是同一个映射文件,即使关闭会话都不会清空的缓存!
内置二级缓存的配置
1.在映射文件增加一个二级缓存的配置
2.二级缓存需要将Java 的对象序列化到本地。实体类要增加一个序列化接口Serializable所谓的序列化(串行化),就是将对象变成一个流格式。这样对象就可以完成保存到本地或者网络传递!
public class Student implements Serializable { private Integer sid; private Integer aid; private String sname; private String sex; private Date birthday; private Integer age; public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public Integer getSid() { return sid; } public void setSid(Integer sid) { this.sid = sid; } public Integer getAid() { return aid; } public void setAid(Integer aid) { this.aid = aid; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
3.新版本已经默认支持开启二级缓存.可以不改
<settings> <!-- 默认支持骆驼命名法 --> <setting name="mapUnderscoreToCamelCase" value="true"/> <!-- 启动缓存,新版本已经默认支持了,可以不配置 --> <setting name="cacheEnabled" value="true"/> </settings>
结果:内置的二级缓存发现缓存的命中率很低,基本不起作用
那么如何解决这个缺陷?
使用第三方的缓存 ehcache,而ehcache 需要 slf4j 这个日志包支持
3.1ehcache 的整合配置
1.导入包
2.配置第三方缓存
<cache type="org.mybatis.caches.ehcache.EhcacheCache" > <!--最大的空闲时间 --> <property name="timeToIdleSeconds" value="10000"/> <!-- 最大的在线时间 --> <property name="timeToLiveSeconds" value="20000"/> <!-- 内存的大小 b 字节 m1 =1024k 1k=1024b --> <property name="maxEntriesLocalHeap" value="2000000"/> <!-- 文件的大小 b 字节--> <property name="maxEntriesLocalDisk" value="20000000"/> <!-- 算法 LRU:最少使用优先, "LFU" or "FIFO:先进先出 --> <property name="memoryStoreEvictionPolicy" value="LRU"/> </cache>
结果:命中率 100%
什么是命中率,就是已经查询的数据,在找到的几率。使用同样的方法时,可以匹配原来的数据的概率;就是第二次以后的查询,找回第一查询的数据的概率,数据少的时候基本都是 100%。
以上是关于Mybatis的缓存的主要内容,如果未能解决你的问题,请参考以下文章