Ibaitsnet源码解读(4)--DataMapper的Cache
来源:互联网 发布:淘宝自动回复优美语句 编辑:程序博客网 时间:2024/04/30 03:26
Ibatis有自己的灵活的,可扩展的Cache支持。其内置的Cache类型有三种:基于内存的,LRU(最近最少使用算法)和FIFO(先进先出)。
一.基本概念
在配置文件中Cache的配置如下:
<flushonexecute statement="insertProduct"/> <flushonexecute statement="updateProduct"/> <flushonexecute statement="deleteProduct"/>
id 用于唯一标志该cacheModel。
implementation 为ICacheController的具体实现类的全限定名或者框架内部定义的别名--LRU,FIFO,MEMORY。
缓存的flush就是重新使缓存和数据库同步,Ibatis的默认实现是清空缓存。
flushInterval 指定了cache的同步(flush)时间,单位可以指定hours,minutes,seconds等,或不指定(从不flush)。
flushOnExecute 指定在所指定的statement执行后flush缓存。比如对于一个查询语句,当执行插入,更新,删除等操作时缓存就可能存在脏数据,应该被flush。Ibatis会在DomSqlMapBuilder构造CacheModel时,将flushOnExecute中指定的statement通过foreach语句注册Trigger:cacheModel.RegisterTriggerStatement(mappedStatement),而该方法就是通过mappedStatement.Execute +=new ExecuteEventHandler(FlushHandler)为flushOnExecute中指定的statement注册了FlushHandler,也就是在执行后同步(刷新)该CacheModel。
property 指定了具体的ICacheController控制器需要的其他参数属性。
二.基本使用
使用缓存的配置如下:
select * from PRODUCT where PRD_CAT_ID = #value#
缓存是和具体的statement一起使用的,也就是可以为需要缓存的可执行语句指定缓存,也可以不指定。这样增加了缓存的灵活性。
一个比较基本的概念:只有查询的结果需要缓存,所以缓存一定是和select语句一起出现的(说的绝对了点,基本上吧)。而缓存的查询结果在执行了其他与该数据相关的写数据的操作后,就有可能存在脏数据。
现在还没有完全明确的是,如果引起缓存中出现脏数据的mappedSatatement不在当前的配置文件中,是否可以通过全限定名来访问该mappedSatatement(理论上应该可以,需要试验)。
三.原理
对于三种算法:
1.基于内存
基于内存的利用了WeakReference,也就是弱引用。同时,Ibatis自己构造了StrongReference类型,java中还有SOFT类型(.NET中不支持)。内存缓存适用于简单应用和服务器物理内存紧张的环境。它的将对象放入缓存和从缓存中取出对象的算法如下:
public object this[object key] { get { object value = null; object reference = _cache[key]; if (reference != null) { if (reference is StrongReference) { value = ((StrongReference)reference).Target; } else if (reference is WeakReference) { value = ((WeakReference)reference).Target; } } return value; } set { object reference = null; if (_cacheLevel.Equals(MemoryCacheLevel.Weak)) { reference = new WeakReference(value); } else if (_cacheLevel.Equals(MemoryCacheLevel.Strong)) { reference = new StrongReference(value); } _cache[key] = reference; } }
也就是,区分了是弱引用还是强引用。cacheLevel默认为WEAK,可以在配置文件中配置。
2.LRU
对于LRU算法,实现如下:
public object this[object key] { get { _keyList.Remove(key); _keyList.Add(key); return _cache[key]; } set { _cache[key] = value; _keyList.Add(key); if (_keyList.Count > _cacheSize) { object oldestKey = _keyList[0]; _keyList.Remove(0); _cache.Remove(oldestKey); } } }
也就是,每次取一次缓存都会将该键首先删除然后加入的键list最后,设置缓存对象时,如果缓存大小大于预定大小,将会删除键list的第0个键值。这样就实现了LRU。
3.FIFO
对于FIFO,算法就比较简单了,只是省去了在LRU中获取缓存对象时在存放键(key)的列表中,先删除再添加到list最后的步骤:
_keyList.Remove(key);
_keyList.Add(key);
其他 与LRU一样,所以就是先进先出(永远是最先加入的最先被删除)。
CacheModel是Cache的Facade,CacheModel负责通过配置文件实例并初始化具体的Cache控制器(实现了ICacheController的类),同时提供public void RegisterTriggerStatement(IMappedStatement mappedStatement)方法,为那些执行后可能会产生脏数据的语句注册触发器,让他们在执行后同步缓存。
SqlMapper提供了最外层的缓存管理和访问的方法:internal void AddCache(CacheModel cache) ,internal CacheModel GetCache(string name) ,这两个方法在通过DomSqlMapBuilder构造SqlMapper实例时调用。另外两个方法public void FlushCaches() ,public string GetDataCacheStats() 提供给客户端调用。
四.扩充
Ibatis的cache框架是可扩展的,必须要遵循的是我们必须自定义一个实现ICacheController接口缓存控制器,实现自己的缓存算法,然后相关的配置在xml配置文件中指定就可以。
五.总结
Ibatia的缓存框架还是比较灵活,可扩充的,但同时,框架本身提供的缓存实现类还比较简单。比如flush时将会清空缓存,这样可能不够强大。有可能按需要实现自己的缓存控制器实现。
- Ibaitsnet源码解读(4)--DataMapper的Cache
- Ibatisnet源码解读(2)—DataMapper
- IbatisNet源码解读 - DataMapper
- IbatisNet源码解读 - DataMapper
- IBatis.Net DataMapper 1.6.2源码解读
- AMPS:Cache模块源码解读
- DataMapper
- Caffe源码解读(二):Blob类的源码解读
- Caffe源码解读(三):Layer类的源码解读
- SGI STL中string的源码解读(4)
- flask-cache 缓存Jinja2模板之源码解读
- caffe 源码的解读(2)DataStructure
- caffe 源码的解读(2)lossFunction
- struts2源码的解读
- struts2源码的解读 .
- HashMap的源码解读
- 解读AtomicStampedReference的源码
- CodeIgniter的源码解读
- ubuntu下卸载nginx方法
- 关于PASCAL 和 FAR
- SAP进销存难点分析及对策
- 简单截图代码win32 MFC
- 判断日期与当前日期之差是否超过90天
- Ibaitsnet源码解读(4)--DataMapper的Cache
- javscript实现元素拖动
- java 深克隆和浅克隆区别
- 8086 CPU 寄存器简介
- FreeBSD修改可执行文件路径和库文件路径
- 发布应用“猜手势(Guess Gesture)”,欢迎拍砖^_^
- MATLAB基础7-MATLAB绘图功能
- 19个三维GIS软件对比
- JAVA基础 之 异常