这篇文章主要给大家介绍了关于MyBatis一级缓存避坑的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
一级缓存概念
当我们使用mybatis进行数据库的操作时候,会创建一个sqlsession来进行一次数据库的会话,会话结束则关闭sqlsession对象。那么一个sqlsession的生命周期即对应于mybatis的一次会话。在mybatis的一次会话中,我们很有可能多次查询完全相同的sql语句,如果不采取措施的话,每一次查询都查询一次数据库。而一次会话时间一般都是极短的,相同sql的查询结果极有可能完全相同。由于查询数据库代价是比较大的,这会导致系统的资源浪费。
为了解决这个问题,mybatis对每一次会话都添加了缓存操作。这个缓存的作用域为一次会话中。缓存随着会话(sqlsession)的创建而产生,随着会话结束而释放。对一次会话的查询操作,总是先查看缓存中是否存在查询结果,如果存在则直接取缓存中的结果,不存在则查询数据库。这样的话,一次会话中的完全相同的查询则只会查询一次,节省了系统资源。
引言
mybatis 一级缓存(mybaits 称其为 local cache)无法关闭,但是有两种级别可选:package org.apache.ibatis.session;
/**
* @author eduardo macarron
*/
public enum localcachescope {
session, //session 级别的缓存 statement //statement 级别的缓存
} 1)session 级别的缓存
在同一个 sqlsession 内,对同样的查询将不再查询数据库,直接从缓存中。
验证代码:
[public static void main(string[] args) throws ioexception { inputstream inputstream = new classpathresource("mybatis.xml").getinputstream(); sqlsessionfactory sqlsessionfactory = new sqlsessionfactorybuilder().build(inputstream); sqlsession sqlsession = sqlsessionfactory.opensession(); userdao mapper = sqlsession.getmapper(userdao.class); system.out.println(mapper.get(1l)); system.out.println("-------------------"); system.out.println(mapper.get(1l));} 输出:
日志输出可以看到,第一次查询通过数据库查询,第二次则没有,直接通过缓存读取。
坑:这种缓存策略有一个坑,在服务集群时就会出现问题。
假设现在有一个服务集群,有两个节点。
首先,两个节点都进行了同样的查询,两个节点都有自己的一级缓存,后续同样的查询,两个节点将不再查询数据库。
如果此时节点 1 执行了 update 语句,那么节点 1 的一级缓存会被刷新,而节点 2 的一级缓存不会改变。
2)statement 级别的缓存
避坑: 为了避免这个问题,可以将一级缓存的级别设为 statement 级别的,这样每次查询结束都会清掉一级缓存。mybatis 源码如下:
在 mybatis 的配置文件中,添加以下配置:
验证代码和上面的一样不变。
输出:
可以看到,即使是同样的查询,每次查询都是直接读取数据库了。
避坑完毕。
缓存是不可能不要缓存的,这个时候,就需要使用缓存中间件了,由缓存中间件管理缓存。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对CodeAE代码之家的支持。
原文链接:http://www.cnblogs.com/justmehyp/p/10025288.html
|