论坛首页 Java企业应用论坛

一个Hibernate缓冲代理的简单实现

浏览 4158 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-01-20  

    有的人很奇怪,Hibernate已经为我们提供了良好的缓存机制,还有必要在应用程序的层面上进行缓存吗?这就好比CPU已经有了一级缓存,还要给它来个二级缓存,甚至还需要硬盘的缓存,光驱的缓存,总之,缓存无所不在,它们通常是比父一级的缓存机制更有针对性,更富有效率。

    和大多数人一样,不喜欢写太多的注释。下面的几个类要简单说明一下,其中的Department、Menu、Role等是几个被缓冲的类, CommonDao和PersistenceService是被封装的Hibernate数据操作类。在这里,CommonDao实例主要用来读数据, PersistenceService实例主要用来进行持久化。

    接下来就看看它是怎么实现的吧,有问题请大家多多指点。

java 代码
 
  1. /** 
  2.  *  
  3.  */  
  4. //package com.company.project;  
  5.   
  6. import java.util.ArrayList;  
  7. import java.util.HashMap;  
  8. import java.util.List;  
  9. import java.util.Map;  
  10.   
  11. import org.apache.commons.logging.Log;  
  12. import org.apache.commons.logging.LogFactory;  
  13.   
  14. import com.etong.common.persistence.CommonDao;  
  15. import com.etong.system.domain.Menu;  
  16. import com.etong.system.domain.Role;  
  17. import com.etong.system.service.PersistenceService;  
  18. import com.etong.system.service.ServiceFactory;  
  19.   
  20. /** 
  21.  * Title: Hibernate的一个读写缓冲代理
  22.  * Description: 一个CommonDao和PersistenceService代理,
  23.  * 对于经常从数据库中存取的类,可以在数组中进行注册, 
  24.  * 该缓冲器将用Map,List等形式,缓冲存取的对象和集合。
  25.  * Copyright: Copyright (c) 2006
  26.  * Company: ××信息技术有限公司
  27.  * Created on Jun 16, 2006
  28.  * @author xifo 
  29.  * @version 1.0 
  30.  * 
  31.  */  
  32. public class HibernateBuffer {  
  33.       
  34.     private static final Log log = LogFactory.getLog(HibernateBuffer.class);  
  35.       
  36.     private static long count;  
  37.     private static HibernateBuffer cache = null;  
  38.     private CommonDao cdao = CommonDao.getInstance();  
  39.     private PersistenceService ps = ServiceFactory.createPersistenceService();      
  40.       
  41.     private int objCount;  
  42.     private boolean[] listChanged;  
  43.     private Map cachedIndex;  
  44.     private Map[] objMap;  
  45.     private List[] objList;  
  46.       
  47.     /** 
  48.      * 注册需要缓冲的类和对应的类获取ID的方法名称。 
  49.      */  
  50.     private Class[] objClass = {  
  51.             Menu.class,   
  52.             Role.class,  
  53.             Department.class  

  54.         };  
  55.       
  56.     private String[] getIDMethod = {  
  57.             "getMenuID",  
  58.             "getRoleID",  
  59.             "getDeptId"  
  60.         };  
  61.       
  62.     /** 
  63.      * 通过类反射和方法反射,将数据库中的对象初始化到相应的Map和List中 
  64.      */  
  65.     private HibernateBuffer(){  
  66.         count = 0;//计数器清零  
  67.         objCount = objClass.length;  
  68.         listChanged = new boolean[objCount];  
  69.         cachedIndex = new HashMap();  
  70.         objMap = new HashMap[objCount];  
  71.         objList = new ArrayList[objCount];  
  72.           
  73.         for(int i=0;i
  74.             //将每个类对应的Index映射到Map中  
  75.             cachedIndex.put(objClass[i],i);  
  76.             objList[i] = cdao.findPersistenceObjects(objClass[i]);  
  77.             objMap[i] = new HashMap();  
  78.             int size = objList[i].size();  
  79.             for(int j=0;j
  80.                 Object obj = objList[i].get(j);  
  81.                 try {  
  82.                     Object objID = obj.getClass().getMethod(getIDMethod[i],  
  83.                             new Class[0]).invoke(obj,new Object[] {});  
  84.                     objMap[i].put(objID, obj);  
  85.                 }catch(Exception e) {  
  86.                     String msg = "注册类" + objClass[i].getName() + "的方法" + getIDMethod[i] +  
  87.                             "()调用时产生异常,可能是方法不存在或参数有误。";  
  88.                     log.error(msg, e);  
  89.                     throw new RuntimeException(msg);  
  90.                 }  
  91.             }  
  92.             listChanged[i] = false;  
  93.         }  
  94.         if(log.isInfoEnabled()) {  
  95.             StringBuffer info = new StringBuffer("已缓冲的类有:\n");  
  96.             for(int i=0;i
  97.                 info.append("\t\t");  
  98.                 info.append(objClass[i].getName());  
  99.             }  
  100.             log.info(info);  
  101.         }  
  102.     }  
  103.   
  104.     /** 
  105.      * 获取Hibernate代理的一个共享实例 
  106.      * @return 
  107.      */  
  108.     public static HibernateBuffer getInstance() {  
  109.         if(cache==null) {  
  110.             cache = new HibernateBuffer();  
  111.         }  
  112.         if(log.isDebugEnabled()) {  
  113.             log.debug("HibernateBuffer产生了第" + (++count) + "个共享实例");  
  114.         }  
  115.         return cache;  
  116.     }  
  117.   
  118.     private int getIndexByClass(Class cls) {  
  119.         Object value = cachedIndex.get(cls);  
  120.         if(value==null)return -1;
  121.         return ((Integer)value).intValue();  
  122.     }  
  123.       
  124.     /** 
  125.      * 从数据库中获取指定ID的对象实例。如果该实例不存在将抛出一个异常。 
  126.      * @param cls 
  127.      * @param id 
  128.      * @return 
  129.      */  
  130.     public Object findPersistenceObjByID(Class cls, Long id) {  
  131.         int index = getIndexByClass(cls);  
  132.         if(index<0)return cdao.findPersistenceObjByID(cls,id);  
  133.         return objMap[index].get(id);  
  134.     }  
  135.       
  136.     /** 
  137.      * 从数据库中获取指定ID的对象实例。如果该实例不存在将返回空。 
  138.      * @param cls 
  139.      * @param id 
  140.      * @return 
  141.      */  
  142.     public Object getPersistenceObjByID(Class cls, Long id) {  
  143.         int index = getIndexByClass(cls);  
  144.         if(index<0)return cdao.getPersistenceObjByID(cls, id);  
  145.         try {  
  146.             return objMap[getIndexByClass(cls)].get(id);  
  147.         }catch(Exception e) {  
  148.             return null;  
  149.         }  
  150.     }  
  151.       
  152.     /** 
  153.      * 从数据库中获取指定对象的集合。 
  154.      * @param cls 
  155.      * @return 
  156.      */  
  157.     public List findPersistenceObjects(Class cls) {  
  158.         int index = getIndexByClass(cls);  
  159.         if(index<0)return cdao.findPersistenceObjects(cls);  
  160.         if(listChanged[index]) {  
  161.             objList[index] = cdao.findPersistenceObjects(cls);  
  162.             listChanged[index] = false;  
  163.         }  
  164.         return objList[index];  
  165.     }  
  166.       
  167.     /** 
  168.      * 持久化一个对象实例。 
  169.      * @param obj 
  170.      */  
  171.     public void makePersistent(Object obj) {  
  172.         //持久化后会使该对象自动获得一个ID  
  173.         ps.makePersistent(obj);  
  174.         int index = getIndexByClass(obj.getClass());  
  175.         if(index<0)return;  
  176.         try {  
  177.             //获取持久化对象的ID,以便在objMap中建立缓冲。  
  178.             Long id = (Long)obj.getClass().getMethod(getIDMethod[index], new Class[0]).invoke(obj,new Object[] {});  
  179.             objMap[index].put(id, obj);  
  180.             listChanged[index] = true;  
  181.         }catch(Exception e) {  
  182.             String msg = "注册类" + objClass[index].getName() + "的方法" + getIDMethod[index] +  
  183.                     "()调用时产生异常,可能是方法不存在或参数有误。";  
  184.             log.error(msg, e);  
  185.             throw new RuntimeException(msg);  
  186.         }  
  187.   
  188.     }  
  189.       
  190.     /** 
  191.      * 删除数据库中一个对象的全部实例。 
  192.      * @param cls 
  193.      */  
  194.     public void makeTransient(Class cls) {  
  195.         ps.makeTransient(cls);  
  196.         int index = getIndexByClass(cls);  
  197.         if(index<0)return;  
  198.         objMap[index].clear();  
  199.         objList[index].clear();  
  200.         listChanged[index] = false;  
  201.     }  
  202.       
  203.     /** 
  204.      * 删除一个对象指定ID的实例 
  205.      * @param cls 
  206.      * @param id 
  207.      */  
  208.     public void makeTransient(Class cls, Long id) {  
  209.         ps.makeTransient(cls,id);  
  210.         int index = getIndexByClass(cls);  
  211.         if(index<0)return;  
  212.         objMap[index].remove(id);  
  213.         listChanged[index] = true;  
  214.     }  
  215.       
  216.     /** 
  217.      * 删除一个对象一组指定ID的实例 
  218.      * @param cls 
  219.      * @param ids 
  220.      */  
  221.     public void makeTransient(Class cls, Long[] ids) {  
  222.         ps.makeTransient(cls,ids);  
  223.         int index = getIndexByClass(cls);  
  224.         if(index<0)return;  
  225.         for(Long id:ids) {  
  226.             objMap[index].remove(id);  
  227.         }  
  228.         listChanged[index] = true;  
  229.     }  
  230.       
  231.     /** 
  232.      * 一个简单的监视代理状态的方法。 
  233.      */  
  234.     public static void monitor() {  
  235.         new Thread() {  
  236.             long mins = 0;  
  237.             public void run() {  
  238.                 while(true) {  
  239.                     try{  
  240.                         Thread.sleep(60000);  
  241.                         log.info("HibernateBuffer监控线程已运行"+(++mins)+"分钟,当前已产生"+count+"个共享实例");  
  242.                     }catch(InterruptedException e){  
  243.                         if(log.isInfoEnabled()) {  
  244.                             log.info("HibernateBuffer监控线程被中断……继续监控……");  
  245.                         }  
  246.                         mins++;  
  247.                     }  
  248.                 }  
  249.             }  
  250.         }.start();  
  251.     }  
  252.       
  253.     /** 
  254.      * 一个简单的用法示例。 
  255.      * @param args 
  256.      */  
  257.     public static void main(String[] args) {  
  258.         monitor();  
  259.         HibernateBuffer hb = HibernateBuffer.getInstance();  
  260.           
  261.         //查询一个Department实例  
  262.         Department dept = (Department)hb.findPersistenceObjByID(Department.class, 1L);  
  263.         System.out.println(dept.getName());  
  264.           
  265.         //持久化一个Department实例  
  266.         dept = new Department();  
  267.         dept.setName("金融科");  
  268.         dept.setNumber("007");  
  269.         hb.makePersistent(dept);  
  270.           
  271.         //查询全部Department实例的集合  
  272.         List deptList = hb.findPersistenceObjects(Department.class);  
  273.         System.out.println(deptList.size());  
  274.           
  275.         //删除金融科  
  276.         hb.makeTransient(Department.class, dept.getDepartmentID());  
  277.           
  278.         //再次查询Department实例的集合  
  279.         deptList = hb.findPersistenceObjects(Department.class);  
  280.         System.out.println(deptList.size());  
  281.     }  
  282. }  
   发表时间:2007-01-20  
以目前的水平,看注释较少的代码的确比较吃力,汗!lz通过java容器储存被持久化的实例来实现缓寸,那不是每执行一次makePersistent方法,如果是被注册类的实例就会增大缓存,似乎没有设定缓存的大小,这样的话,若不手工清除,缓存不是会随操作次数的增加而一直增大?

   由于看得不是太懂,不知道是不是我有什么地方没有理解到。希望lz能赐教!
0 请登录后投票
   发表时间:2007-01-21  
SunMicro 写道
以目前的水平,看注释较少的代码的确比较吃力,汗!lz通过java容器储存被持久化的实例来实现缓寸,那不是每执行一次makePersistent方法,如果是被注册类的实例就会增大缓存,似乎没有设定缓存的大小,这样的话,若不手工清除,缓存不是会随操作次数的增加而一直增大?

   由于看得不是太懂,不知道是不是我有什么地方没有理解到。希望lz能赐教!
使用这个实现的初衷是,对于数据库中常用的表,避免每次从数据库中Select出来,而是在第一次使用时载入内存,本质上与很多人将一些常用表放到application中类似,只是不需要从application中解析,而是和别的没有缓存的表一样,按照统一的方式进行存取。
0 请登录后投票
   发表时间:2007-07-14  
看自己一年前的代码,总是有种说不出的别扭。

看现在很多人写的代码,也是说不出的难受。是不是开源的东西看得太多了?
0 请登录后投票
   发表时间:2007-07-14  
粗略的看了下,没有看到任何同步的处理,和并发的测试,是这个样子的么?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics