- 浏览: 179488 次
- 性别:
- 来自: 重庆
最新评论
-
way_super:
请问楼主,地图都可以下载了,就是你这里面没有的添加标记的功能, ...
googleMap本地化(离线) -
way_super:
gaoxiangky 写道你好,这个经纬度我解决了,但是我将这 ...
googleMap本地化(离线) -
foreach1025:
...
java源程序加密解决方案(基于Classloader解密) -
cuishuailingcsl:
写的很好,学习了~
java源程序加密解决方案(基于Classloader解密) -
liuchao123:
“保存文件并使用命名source /etc/profile重新 ...
windows上hadoop安装(cygwin等)
mybatis二级缓存工作机制
在mybatis的主配置文件中,启动二级缓存配置
这个配置会再以后生成Executor的时候使用CachingExecutor而非 BaseExecutor
然后在映射的xml配置文件如UserMapper.xml中 对该实体启用缓存,简单点写直接添加
<cache/>
即可。至此配置完成。
在完成以上配置之后,对缓存进行测试
测试的核心代码
理论上将,这种方式查询数据请求,在mybatis中肯定是可以直接从二级缓存中取数据的。
请看如下的图(网上找的,觉得还不错)。
其中CachingExecutor类的query方法
查询请求来的时候,会首先从MappedStatement中取出缓存实例Cache,若开启了二级缓存的,则先从二级缓存中查找数据,找到即直接返回结果,若没有找到,则使用delegate(叫做代理业好,装饰器也好)所代理的查询(此处为BaseExecutor)来进行查询,代理的具体查询就不说了,不是本文的重点。结合上图以及代码,可以看出tcm.putObject(cache, key, list);这句话是将查询处理的结果放入缓存,其中tcm是在CachingExecutor中定义的private TransactionalCacheManager tcm = new TransactionalCacheManager();
然后我们查看TransactionalCacheManager的putObject(cache, key, list)方法,如下
继续查看TransactionalCache的源码,可以看到,在TransactionalCache的putObject(Object key, Object object)方法中,并不是直接将结果集合放入缓存中,而是加入到一个队列中,这个队列会再发起这次请求的SqlSession提交(commit)或关闭(close)的时候,调用到TransactionalCache的commit方法,从而调用到内部类AddEntry的commit方法,将结果集合存放到缓存中。
下图为将结果集合存入缓存的过程。
在mybatis的主配置文件中,启动二级缓存配置
<settings> <setting name="cacheEnabled" value="true"/> </settings>
这个配置会再以后生成Executor的时候使用CachingExecutor而非 BaseExecutor
然后在映射的xml配置文件如UserMapper.xml中 对该实体启用缓存,简单点写直接添加
<cache/>
即可。至此配置完成。
在完成以上配置之后,对缓存进行测试
测试的核心代码
SqlSession session = sqlSessionFactory.openSession(); List<User> allUsers = session.selectList("com.test.model.User.queryUserByName", "%test%", new RowBounds(1, 1)); session.commit(); List<User> allUsers3 = sqlSessionFactory.openSession().selectList("com.test.model.User.queryUserByName", "%test%", new RowBounds(1, 1));
理论上将,这种方式查询数据请求,在mybatis中肯定是可以直接从二级缓存中取数据的。
请看如下的图(网上找的,觉得还不错)。
其中CachingExecutor类的query方法
public List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { if (ms != null) { Cache cache = ms.getCache(); if (cache != null) { flushCacheIfRequired(ms); cache.getReadWriteLock().readLock().lock(); try { if (ms.isUseCache() && resultHandler == null) { CacheKey key = createCacheKey(ms, parameterObject, rowBounds); final List cachedList = (List) cache.getObject(key); if (cachedList != null) { return cachedList; } else { List list = delegate.query(ms, parameterObject, rowBounds, resultHandler); tcm.putObject(cache, key, list); return list; } } else { return delegate.query(ms, parameterObject, rowBounds, resultHandler); } } finally { cache.getReadWriteLock().readLock().unlock(); } } } return delegate.query(ms, parameterObject, rowBounds, resultHandler); }
查询请求来的时候,会首先从MappedStatement中取出缓存实例Cache,若开启了二级缓存的,则先从二级缓存中查找数据,找到即直接返回结果,若没有找到,则使用delegate(叫做代理业好,装饰器也好)所代理的查询(此处为BaseExecutor)来进行查询,代理的具体查询就不说了,不是本文的重点。结合上图以及代码,可以看出tcm.putObject(cache, key, list);这句话是将查询处理的结果放入缓存,其中tcm是在CachingExecutor中定义的private TransactionalCacheManager tcm = new TransactionalCacheManager();
然后我们查看TransactionalCacheManager的putObject(cache, key, list)方法,如下
public class TransactionalCacheManager { private Map<Cache, TransactionalCache> transactionalCaches = new HashMap<Cache, TransactionalCache>(); public void putObject(Cache cache, CacheKey key, Object value) { getTransactionalCache(cache).putObject(key, value); } }
继续查看TransactionalCache的源码,可以看到,在TransactionalCache的putObject(Object key, Object object)方法中,并不是直接将结果集合放入缓存中,而是加入到一个队列中,这个队列会再发起这次请求的SqlSession提交(commit)或关闭(close)的时候,调用到TransactionalCache的commit方法,从而调用到内部类AddEntry的commit方法,将结果集合存放到缓存中。
public class TransactionalCache implements Cache { private Cache delegate; private Map<Object, AddEntry> entriesToAddOnCommit; public void putObject(Object key, Object object) { entriesToRemoveOnCommit.remove(key); entriesToAddOnCommit.put(key, new AddEntry(delegate, key, object)); } public void commit() { delegate.getReadWriteLock().writeLock().lock(); try { if (clearOnCommit) { delegate.clear(); } else { for (RemoveEntry entry : entriesToRemoveOnCommit.values()) { entry.commit(); } } for (AddEntry entry : entriesToAddOnCommit.values()) { entry.commit(); } reset(); } finally { delegate.getReadWriteLock().writeLock().unlock(); } } private static class AddEntry { private Cache cache; private Object key; private Object value; public AddEntry(Cache cache, Object key, Object value) { this.cache = cache; this.key = key; this.value = value; } public void commit() { cache.putObject(key, value); } } }
下图为将结果集合存入缓存的过程。
评论
2 楼
xussen
2013-03-15
还有似乎3.1.1开始,CachingExecutor将读写锁放到了delegate.query操作之前,
理由是为了防止死锁,// issue #578. Query must be not synchronized to prevent deadlocks
可以这样会不会有线程安全问题呢
理由是为了防止死锁,// issue #578. Query must be not synchronized to prevent deadlocks
可以这样会不会有线程安全问题呢
1 楼
xussen
2013-03-15
能否解释一下为何不把结果集直接放进缓存,而是放入队列当中,延迟缓存。
除了可以减少频繁的get,set的操作,是否还有跟线程安全有关系?
除了可以减少频繁的get,set的操作,是否还有跟线程安全有关系?
发表评论
-
java基于filter的应用缓存框架
2012-08-10 17:34 3621java web 基于filter的缓存 ... -
hadoop未修复bug6287的解决办法(ttprivte to 0700的bug、setPermission failed)
2012-04-06 17:31 3787hadoop-0.20.2以上版本,若在windows下使用c ... -
windows上hadoop安装(cygwin等)
2012-04-05 19:32 9870hadoop运行方式 1、本机方式:不做任何配置 2、伪分布式 ... -
云计算的理解
2012-03-30 15:19 1558分布式系统,解决的问 ... -
js获取get方式传递的参数
2012-01-05 12:48 3065String.prototype.GetValue= f ... -
Tomcat_Broken pipe
2011-12-31 10:10 4700这个异常是由于以下几个原因造成。 1、客户端再发起请求后没有等 ... -
linux1024下端口安全性问题
2011-11-13 09:55 1414Linux下认为1024以下的端口都是不安全的,所以打开102 ... -
Parameters Invalid chunk '' ignored警告
2011-11-07 09:59 1480Parameters Invalid chunk '' ign ... -
hql语句中支持的本地时间函数
2011-11-01 16:17 11714hql语句中支持的本地时间函数 1、UNIX_TIMES ... -
ckeditor等在线编辑器于struts结合无法上传图片问题
2011-10-21 08:32 2574ckeditor与struts结合的时候,需要注意Struts ... -
java的server模式
2011-10-21 08:30 1398The Java HotSpotTM Server VM is ... -
linux top命令中各cpu占用率含义
2011-10-20 08:24 16400.3% us 用户空间占用CPU百分比 1.0% sy 内核 ... -
iframe自适应高度
2011-10-19 17:34 988<script> function dyni ... -
tomcat部署为服务器注意事项
2011-10-19 08:57 1183(1)使用内存 在启动脚本 catalina.sh或 ... -
model driven 更新实体 外键集合丢失问题
2011-06-15 21:55 1016在使用ssh框架开发web的时候,有的时候使用model dr ... -
spring aop 日志记录
2011-05-28 13:21 4628spring aop 日志记录 需要日志记录,将所有 ... -
jotm跨数据库事务 spring + hibernate
2011-04-26 13:39 2080jotm跨数据库 spring + hibernate 软 ... -
jpa/hibernate继承注解
2011-03-24 23:08 9303hibernate继承映射 以下测试是在mysql中进行的。 ... -
<转>hibernate中get方法和load方法的根本区别
2011-03-24 10:28 1122hibernate中get方法和load方 ... -
java基于线程的分布式
2011-03-12 11:30 5011java基于线程的分布式 1. 引言 ...
相关推荐
一级缓存和二级缓存都是MyBatis提供的缓存机制,它们可以帮助提高应用程序的性能。但是,二级缓存的作用范围更大,可以被多个SqlSession共用,是一种更强大的一种缓存机制。 在实际开发中,MyBatis通常和Spring进行...
二级缓存是 Mapper 级别的缓存,可以跨 SqlSession 工作。它将数据存储在一个全局区域,多个 SqlSession 可以共享。二级缓存默认是关闭的,需要在 MyBatis 配置文件或 Mapper 映射文件中开启。开启二级缓存后,相同...
标题中的“mybatis二级缓存”指的是MyBatis框架中的一个重要特性,它是MyBatis缓存机制的一部分,用于提升数据库查询效率。MyBatis一级缓存是SqlSession级别的,而二级缓存则是在整个Mapper配置范围内的全局缓存,...
在大型系统中,为了提高数据访问效率,MyBatis提供了二级缓存机制。本文将深入探讨如何对MyBatis的二级缓存进行扩展,并将其与Redis集成,以充分利用分布式缓存的优势。 MyBatis的二级缓存是基于全局的,它允许不同...
MyBatis的二级缓存机制允许我们将执行过的SQL查询结果存储在内存中,以供后续相同的查询直接使用,从而避免了重复的数据库访问。二级缓存可以配置在Mapper级别或全局级别,通过XML配置文件或注解进行设置。在实现二...
缓存是MyBatis性能优化的重要手段,分为一级缓存和二级缓存。在这篇文章中,我们将深入探讨这两个级别的缓存机制及其工作原理。 **一级缓存** 一级缓存是SqlSession级别的缓存,也称为局部缓存。当你执行一个查询...
"深入了解MyBatis二级缓存" MyBatis是一种流行的Java持久层框架,它提供了强大的缓存机制以提高应用...通过了解MyBatis二级缓存的工作原理、配置方法和使用场景,可以更好地使用MyBatis二级缓存提高应用程序的性能。
在 MyBatis 中,一级缓存和二级缓存是两个重要的性能优化手段,它们可以有效减少对数据库的访问,提高系统的响应速度。下面将详细阐述这两个缓存机制。 ### 一级缓存 一级缓存是 MyBatis 默认开启的本地会话缓存,...
本文将深入探讨MyBatis的二级缓存机制,旨在帮助开发者更好地理解和利用这一功能。 首先,我们需要了解什么是缓存。缓存是一种存储技术,用于暂时保存经常访问的数据,以便快速获取,减少对数据库的直接访问,从而...
本篇将详细介绍如何在MyBatis3中启用二级缓存,并深入解析其工作原理和配置步骤。 **一、MyBatis缓存概念** MyBatis的缓存分为一级缓存和二级缓存。一级缓存是SqlSession级别的,同一个SqlSession内的相同SQL语句...
MyBatis二级缓存的实现代码 MyBatis是当前Java领域中最流行的持久层框架之一,将SQL映射到Java对象的技术称为ORM(Object-Relational Mapping)。MyBatis提供了三级缓存机制,一级缓存是Session级别的缓存,二级...
为了解决这个问题,Mybatis-plus提供了基于Redis的二级缓存机制,能够大幅度提高应用程序的性能。 在Mybatis-plus中,二级缓存是指在应用程序中使用Redis作为缓存层,存储查询结果,以便下次查询时直接从缓存中获取...
本篇文章将详细探讨MyBatis的缓存机制,包括一级缓存和二级缓存,以及如何将MyBatis与第三方缓存EhCache进行整合。 首先,我们来了解一级缓存。一级缓存是SqlSession级别的,也称为本地缓存。当我们在一个...
MyBatis的二级缓存机制允许开发者自定义缓存实现,这就为我们使用Redis这样的分布式缓存系统提供了可能。Redis是一个高性能的键值存储系统,适合存储大量的字符串、列表、集合、哈希表等数据结构,并支持丰富的操作...
为了解决这个问题,MyBatis提供了二级缓存机制。一级缓存是SqlSession级别的,同一个SqlSession内的多次查询会复用已缓存的结果;而二级缓存则是Mapper级别的,可以在多个SqlSession之间共享,跨越了单一事务的限制...
作为一名 IT 行业大师,我将对 Mybatis-Plus 缓存机制进行详细的解释,帮助读者深入了解缓存的概念、Mybatis-Plus 缓存机制的工作原理、一级缓存和二级缓存的配置和使用、缓存的优点和缺点等。 缓存是什么? 缓存是...
但是,MyBatis 的二级缓存机制存在一些缺陷,例如不支持集群模式、缓存数据不易管理等问题。因此,本文将介绍如何使用 Redis 集群来替换 MyBatis 的二级缓存机制,提高缓存机制的可扩展性和性能。 知识点1:Spring ...
MyBatis一二级缓存介绍 MyBatis是一款流行的Java持久层框架,它...MyBatis的一二级缓存机制可以大大提高数据库操作的性能,减少数据库查询的次数。但是,需要合理地配置缓存机制,避免缓存溢出和数据不一致的问题。
本文重点介绍的是如何结合SpringMVC框架、MyBatis以及Redis实现一个高效的二级缓存机制。 #### 二、Redis作为二级缓存实现 Redis是一个开源的高性能键值存储系统,它具有内存存储、低延迟和丰富的数据结构等特点,...
同时,MyBatis二级缓存对细粒度的数据级别的缓存实现不好,需要在业务层根据需求对数据有针对性缓存。 MyBatis关于二级缓存问题的解决方案提供了强大的缓存机制来提高应用程序的性能,但需要根据实际情况选择合适的...