mybatis查询缓存

查询缓存

Mybatis的查询缓存机制根据作用域的不同,可以分为一级缓存的二级缓存。

Mybatis究竟缓存什么

一个 **** 有id决定其唯一性,对于一个查询sql而言,可以直接缓存查询出来的结果,下一次相同查询时,直接将查询出来的结果返回即可。也可以缓存sql语句的id(即上面的xxx)。那么Mybatis是缓存查询出来的结果还是缓存sql语句的id呢?

缓存sql语句的id!Hibernate缓存的是查询出来的结果。

可以用以下示例证明:


<select id="selectId1" resultType="Student">
	select * from student where id=#{id}
select>
<select id="selectId2" resultType="Student">
	select * from student where id=#{id}
select>


@Test
public void test() {
	int id = 5;
	Student student1 = dao.selectId1(id);
	System.out.println(student1);

	Student student2 = dao.selectId2(id);	
	System.out.println(student2)
}

分析:如果Mybatis缓存的是查询出来的结果,那么上面的示例中,日志里面只会有一条预编译sql日志记录,因为它们只是sql标签的id不相同,查询的是同一个对象。但是试验输出的是两条预编译sql日志记录:

[DEBUG] ==>  Preparing: select * from student where id=?
[DEBUG] ==> Parameters: 5(Integer)
[DEBUG] <==      Total: 1
Student [id=5, firstName="smantle", lastName="wang", fullName="smantle wang"]
[DEBUG] ==>  Preparing: select * from student where id=?
[DEBUG] ==> Parameters: 5(Integer)
[DEBUG] <==      Total: 1
Student [id=5, firstName="smantle", lastName="wang", fullName="smantle wang"]

无论是一级缓存还是二级缓存,底层都是使用HashMap实现:key为sql标签的id,value是从数据库查询出来的结果。如果sql标签的id在缓存中,直接通过id到HashMap中查找对应的value,而不需要到DB中查找。

从Mybatis缓存的是sql标签的id也可以看出:Mybatis的缓存并不是为了在查询之间共享数据(否则的话直接缓存查询结果效果更好),而Hibernate的缓存是为了数据共享。Mybatis的缓存是为了延长该查询的保存时间。

无论是一级缓存还是二级缓存,增、删、改sql操作无论最终结果是commit还是rollback,都会刷新缓存。

一级缓存

Mybatis的一级缓存是基于org.apache.ibatis.cache.impl.PerpetualCache类的HashMap本地缓存,作用域是SqlSession。即在同一个SqlSession范围内,执行两次相同的sql语句,第一次执行完毕后,会将查询结果缓存本地,下一次直接从本地缓存中获取。一级缓存在Mybatis中是默认开启的,且无法关闭。

二级缓存

二级缓存的作用域是mapper文件的namespace,不同的namespace互相不干扰。

二级缓存开启必须满足两个条件:

  • POJO对象实现Serializable接口,如果该对象存在父类或者属性是自定义对象,父类和自定义对象也需要实现Serializable接口
  • 在对应dao层的mapper.xml中加入:标签

标签还支持自定义相关配置:

<mapper namespace="xxx">
	<cache eviction="FIFO" flushInterval="3600000" readOnly="true" size="512" />
mapper>
  • eviction:逐出策略,当二级缓存中对象达到最大值时,需要通过对应的逐出策略移除对象,常用的策略与:LRU、FILO
  • flushInterval:刷新缓存的间隔,单位毫秒,一般不指定,而是通过增、删、该来自动刷新
  • readOnly:设置缓存数据是否可读,默认false
  • size:二级缓存中最多可以存放多少个对象,默认1024个

二级缓存的使用建议:

  • 只在一个namespace下使用二级缓存:二级缓存本省作用域就是namespace,由namespace进行隔离。如果多个namespace同时对一个表进行操作,可能各个namespace中出现数据不一致情况
  • 只在单表中使用二级缓存:如果一个表和其它表有关联,也可能存在多个namespace同时操作一个表,出现缓存不一致问题
  • 查询远多于修改时使用二级缓存:任何修改操作(增、删、改)都会刷新二级缓存,频繁改操作导致缓存频繁刷新从而降低性能。

更多资料参考

你可能感兴趣的:(学习笔记)