一个Hibernate缓冲署理的简单实现
一个Hibernate缓冲代理的简单实现??? 有的人很奇怪,Hibernate已经为我们提供了良好的缓存机制,还有必要在
一个Hibernate缓冲代理的简单实现
??? 有的人很奇怪,Hibernate已经为我们提供了良好的缓存机制,还有必要在应用程序的层面上进行缓存吗?这就好比CPU已经有了一级缓存,还要给它来个二级缓存,甚至还需要硬盘的缓存,光驱的缓存,总之,缓存无所不在,它们通常是比父一级的缓存机制更有针对性,更富有效率。
??? 和大多数人一样,不喜欢写太多的注释。下面的几个类要简单说明一下,其中的Department、Menu、Role等是几个被缓冲的类, CommonDao和PersistenceService是被封装的Hibernate数据操作类。在这里,CommonDao实例主要用来读数据, PersistenceService实例主要用来进行持久化。
??? 接下来就看看它是怎么实现的吧,有问题请大家多多指点。
java 代码?
- /**?
- ?*??
- ?*/??
- //package?com.company.project;??
- ??
- import?java.util.ArrayList;??
- import?java.util.HashMap;??
- import?java.util.List;??
- import?java.util.Map;??
- ??
- import?org.apache.commons.logging.Log;??
- import?org.apache.commons.logging.LogFactory;??
- ??
- import?com.etong.common.persistence.CommonDao;??
- import?com.etong.system.domain.Menu;??
- import?com.etong.system.domain.Role;??
- import?com.etong.system.service.PersistenceService;??
- import?com.etong.>
- ??????
- ????private?static?final?Log?log?=?LogFactory.getLog(HibernateBuffer.class);??
- ??????
- ????private?static?long?count;??
- ????private?static?HibernateBuffer?cache?=?null;??
- ????private?CommonDao?cdao?=?CommonDao.getInstance();??
- ????private?PersistenceService?ps?=?ServiceFactory.createPersistenceService();??????
- ??????
- ????private?int?objCount;??
- ????private?boolean[]?listChanged;??
- ????private?Map?cachedIndex;??
- ????private?Map[]?objMap;??
- ????private?List[]?objList;??
- ??????
- ????/**?
- ?????*?注册需要缓冲的类和对应的类获取ID的方法名称。?
- ?????*/??
- ????private?Class[]?objClass?=?{??
- ????????????Menu.class,???
- ????????????Role.class,??
-
??????????? Department.class??
- ????????};??
- ??????
- ????private?String[]?getIDMethod?=?{??
- ????????????"getMenuID",??
- ????????????"getRoleID",??
- ??????????? "getDeptId"??
- ????????};??
- ??????
- ????/**?
- ?????*?通过类反射和方法反射,将数据库中的对象初始化到相应的Map和List中?
- ?????*/??
- ????private?HibernateBuffer(){??
- ????????count?=?0;//计数器清零??
- ????????objCount?=?objClass.length;??
- ????????listChanged?=?new?boolean[objCount];??
- ????????cachedIndex?=?new?HashMap();??
- ????????objMap?=?new?HashMap[objCount];??
- ????????objList?=?new?ArrayList[objCount];??
- ??????????
- ????????for(int?i=0;i
- ????????????//将每个类对应的Index映射到Map中??
- ????????????cachedIndex.put(objClass[i],i);??
- ????????????objList[i]?=?cdao.findPersistenceObjects(objClass[i]);??
- ????????????objMap[i]?=?new?HashMap();??
- ????????????int?size?=?objList[i].size();??
- ????????????for(int?j=0;j
- ????????????????Object?obj?=?objList[i].get(j);??
- ????????????????try?{??
- ????????????????????Object?objID?=?obj.getClass().getMethod(getIDMethod[i],??
- ????????????????????????????new?Class[0]).invoke(obj,new?Object[]?{});??
- ????????????????????objMap[i].put(objID,?obj);??
- ????????????????}catch(Exception?e)?{??
- ????????????????????String?msg?=?"注册类"?+?objClass[i].getName()?+?"的方法"?+?getIDMethod[i]?+??
- ????????????????????????????"()调用时产生异常,可能是方法不存在或参数有误。";??
- ????????????????????log.error(msg, e);??
- ????????????????????throw?new?RuntimeException(msg);??
- ????????????????}??
- ????????????}??
- ????????????listChanged[i]?=?false;??
- ????????}??
- ????????if(log.isInfoEnabled())?{??
- ????????????StringBuffer?info?=?new?StringBuffer("已缓冲的类有:\n");??
- ????????????for(int?i=0;i
- ????????????????info.append("\t\t");??
- ????????????????info.append(objClass[i].getName());??
- ????????????}??
- ????????????log.info(info);??
- ????????}??
- ????}??
- ??
- ????/**?
- ?????*?获取Hibernate代理的一个共享实例?
- ?????*?@return?
- ?????*/??
- ????public?static?HibernateBuffer?getInstance()?{??
- ????????if(cache==null)?{??
- ????????????cache?=?new?HibernateBuffer();??
- ????????}??
- ????????if(log.isDebugEnabled())?{??
- ????????????log.debug("HibernateBuffer产生了第"?+?(++count)?+?"个共享实例");??
- ????????}??
- ????????return?cache;??
- ????}??
- ??
- ????private?int?getIndexByClass(Class?cls)?{??
- ????????Object?value?=?cachedIndex.get(cls);??
- ????????if(value==null)return?-1;
- ????????return?((Integer)value).intValue();??
- ????}??
- ??????
- ????/**?
- ?????*?从数据库中获取指定ID的对象实例。如果该实例不存在将抛出一个异常。?
- ?????*?@param?cls?
- ?????*?@param?id?
- ?????*?@return?
- ?????*/??
- ????public?Object?findPersistenceObjByID(Class?cls,?Long?id)?{??
- ????????int?index?=?getIndexByClass(cls);??
- ????????if(index<0)return?cdao.findPersistenceObjByID(cls,id);??
- ????????return?objMap[index].get(id);??
- ????}??
- ??????
- ????/**?
- ?????*?从数据库中获取指定ID的对象实例。如果该实例不存在将返回空。?
- ?????*?@param?cls?
- ?????*?@param?id?
- ?????*?@return?
- ?????*/??
- ????public?Object?getPersistenceObjByID(Class?cls,?Long?id)?{??
- ????????int?index?=?getIndexByClass(cls);??
- ????????if(index<0)return?cdao.getPersistenceObjByID(cls,?id);??
- ????????try?{??
- ????????????return?objMap[getIndexByClass(cls)].get(id);??
- ????????}catch(Exception?e)?{??
- ????????????return?null;??
- ????????}??
- ????}??
- ??????
- ????/**?
- ?????*?从数据库中获取指定对象的集合。?
- ?????*?@param?cls?
- ?????*?@return?
- ?????*/??
- ????public?List?findPersistenceObjects(Class?cls)?{??
- ????????int?index?=?getIndexByClass(cls);??
- ????????if(index<0)return?cdao.findPersistenceObjects(cls);??
- ????????if(listChanged[index])?{??
- ????????????objList[index]?=?cdao.findPersistenceObjects(cls);??
- ????????????listChanged[index]?=?false;??
- ????????}??
- ????????return?objList[index];??
- ????}??
- ??????
- ????/**?
- ?????*?持久化一个对象实例。?
- ?????*?@param?obj?
- ?????*/??
- ????public?void?makePersistent(Object?obj)?{??
- ????????//持久化后会使该对象自动获得一个ID??
- ????????ps.makePersistent(obj);??
- ????????int?index?=?getIndexByClass(obj.getClass());??
- ????????if(index<0)return;??
- ????????try?{??
- ????????????//获取持久化对象的ID,以便在objMap中建立缓冲。??
- ????????????Long?id?=?(Long)obj.getClass().getMethod(getIDMethod[index],?new?Class[0]).invoke(obj,new?Object[]?{});??
- ????????????objMap[index].put(id,?obj);??
- ????????????listChanged[index]?=?true;??
- ????????}catch(Exception?e)?{??
- ????????????String?msg?=?"注册类"?+?objClass[index].getName()?+?"的方法"?+?getIDMethod[index]?+??
- ????????????????????"()调用时产生异常,可能是方法不存在或参数有误。";??
- ????????????log.error(msg, e);??
- ????????????throw?new?RuntimeException(msg);??
- ????????}??
- ??
- ????}??
- ??????
- ????/**?
- ?????*?删除数据库中一个对象的全部实例。?
- ?????*?@param?cls?
- ?????*/??
- ????public?void?makeTransient(Class?cls)?{??
- ????????ps.makeTransient(cls);??
- ????????int?index?=?getIndexByClass(cls);??
- ????????if(index<0)return;??
- ????????objMap[index].clear();??
- ????????objList[index].clear();??
- ????????listChanged[index]?=?false;??
- ????}??
- ??????
- ????/**?
- ?????*?删除一个对象指定ID的实例?
- ?????*?@param?cls?
- ?????*?@param?id?
- ?????*/??
- ????public?void?makeTransient(Class?cls,?Long?id)?{??
- ????????ps.makeTransient(cls,id);??
- ????????int?index?=?getIndexByClass(cls);??
- ????????if(index<0)return;??
- ????????objMap[index].remove(id);??
- ????????listChanged[index]?=?true;??
- ????}??
- ??????
- ????/**?
- ?????*?删除一个对象一组指定ID的实例?
- ?????*?@param?cls?
- ?????*?@param?ids?
- ?????*/??
- ????public?void?makeTransient(Class?cls,?Long[]?ids)?{??
- ????????ps.makeTransient(cls,ids);??
- ????????int?index?=?getIndexByClass(cls);??
- ????????if(index<0)return;??
- ????????for(Long?id:ids)?{??
- ????????????objMap[index].remove(id);??
- ????????}??
- ????????listChanged[index]?=?true;??
- ????}??
- ??????
- ????/**?
- ?????*?一个简单的监视代理状态的方法。?
- ?????*/??
- ????public?static?void?monitor()?{??
- ????????new?Thread()?{??
- ????????????long?mins?=?0;??
- ????????????public?void?run()?{??
- ????????????????while(true)?{??
- ????????????????????try{??
- ????????????????????????Thread.sleep(60000);??
- ????????????????????????log.info("HibernateBuffer监控线程已运行"+(++mins)+"分钟,当前已产生"+count+"个共享实例");??
- ????????????????????}catch(InterruptedException?e){??
- ????????????????????????if(log.isInfoEnabled())?{??
- ????????????????????????????log.info("HibernateBuffer监控线程被中断……继续监控……");??
- ????????????????????????}??
- ????????????????????????mins++;??
- ????????????????????}??
- ????????????????}??
- ????????????}??
- ????????}.start();??
- ????}??
- ??????
- ????/**?
- ?????*?一个简单的用法示例。?
- ?????*?@param?args?
- ?????*/??
- ????public?static?void?main(String[]?args)?{??
- ????????monitor();??
- ????????HibernateBuffer?hb?=?HibernateBuffer.getInstance();??
- ??????????
- ????????//查询一个Department实例??
- ????????Department?dept?=?(Department)hb.findPersistenceObjByID(Department.class,?1L);??
- ????????System.out.println(dept.getName());??
- ??????????
- ????????//持久化一个Department实例??
- ????????dept?=?new?Department();??
- ????????dept.setName("金融科");??
- ????????dept.setNumber("007");??
- ????????hb.makePersistent(dept);??
- ??????????
- ????????//查询全部Department实例的集合??
- ????????List?deptList?=?hb.findPersistenceObjects(Department.class);??
- ????????System.out.println(deptList.size());??
- ??????????
- ????????//删除金融科??
- ????????hb.makeTransient(Department.class,?dept.getDepartmentID());??
- ??????????
- ????????//再次查询Department实例的集合??
- ????????deptList?=?hb.findPersistenceObjects(Department.class);??
- ????????System.out.println(deptList.size());??
- ????}??
- }??
1 楼 SunMicro 2007-01-20 以目前的水平,看注释较少的代码的确比较吃力,汗!lz通过java容器储存被持久化的实例来实现缓寸,那不是每执行一次makePersistent方法,如果是被注册类的实例就会增大缓存,似乎没有设定缓存的大小,这样的话,若不手工清除,缓存不是会随操作次数的增加而一直增大?
由于看得不是太懂,不知道是不是我有什么地方没有理解到。希望lz能赐教! 2 楼 xifo 2007-01-21 SunMicro 写道以目前的水平,看注释较少的代码的确比较吃力,汗!lz通过java容器储存被持久化的实例来实现缓寸,那不是每执行一次makePersistent方法,如果是被注册类的实例就会增大缓存,似乎没有设定缓存的大小,这样的话,若不手工清除,缓存不是会随操作次数的增加而一直增大?
由于看得不是太懂,不知道是不是我有什么地方没有理解到。希望lz能赐教!使用这个实现的初衷是,对于数据库中常用的表,避免每次从数据库中Select出来,而是在第一次使用时载入内存,本质上与很多人将一些常用表放到application中类似,只是不需要从application中解析,而是和别的没有缓存的表一样,按照统一的方式进行存取。 3 楼 xifo 2007-07-14 看自己一年前的代码,总是有种说不出的别扭。
看现在很多人写的代码,也是说不出的难受。是不是开源的东西看得太多了? 4 楼 Godlikeme 2007-07-14 粗略的看了下,没有看到任何同步的处理,和并发的测试,是这个样子的么?