`
xifo
  • 浏览: 3012 次
  • 性别: Icon_minigender_1
  • 来自: 安徽
文章分类
社区版块
存档分类
最新评论

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

阅读更多

    有的人很奇怪,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. }  
分享到:
评论
4 楼 Godlikeme 2007-07-14  
粗略的看了下,没有看到任何同步的处理,和并发的测试,是这个样子的么?
3 楼 xifo 2007-07-14  
看自己一年前的代码,总是有种说不出的别扭。

看现在很多人写的代码,也是说不出的难受。是不是开源的东西看得太多了?
2 楼 xifo 2007-01-21  
SunMicro 写道
以目前的水平,看注释较少的代码的确比较吃力,汗!lz通过java容器储存被持久化的实例来实现缓寸,那不是每执行一次makePersistent方法,如果是被注册类的实例就会增大缓存,似乎没有设定缓存的大小,这样的话,若不手工清除,缓存不是会随操作次数的增加而一直增大?

   由于看得不是太懂,不知道是不是我有什么地方没有理解到。希望lz能赐教!
使用这个实现的初衷是,对于数据库中常用的表,避免每次从数据库中Select出来,而是在第一次使用时载入内存,本质上与很多人将一些常用表放到application中类似,只是不需要从application中解析,而是和别的没有缓存的表一样,按照统一的方式进行存取。
1 楼 SunMicro 2007-01-20  
以目前的水平,看注释较少的代码的确比较吃力,汗!lz通过java容器储存被持久化的实例来实现缓寸,那不是每执行一次makePersistent方法,如果是被注册类的实例就会增大缓存,似乎没有设定缓存的大小,这样的话,若不手工清除,缓存不是会随操作次数的增加而一直增大?

   由于看得不是太懂,不知道是不是我有什么地方没有理解到。希望lz能赐教!

相关推荐

    hibernate 教程

    实现一个默认的构造方法(constructor) 4.1.3. 提供一个标识属性(identifier property)(可选) 4.1.4. 建议使用不是final的类 (可选) 4.2. 实现继承(Inheritance) 4.3. 实现equals()和hashCode...

    hibernate

    实现一个默认的构造方法(constructor) 4.1.3. 提供一个标识属性(identifier property)(可选) 4.1.4. 建议使用不是final的类 (可选) 4.2. 实现继承(Inheritance) 4.3. 实现equals()和hashCode...

    Hibernate学习

    在入门阶段,通常会涉及到一个简单的示例来展示Hibernate的基本用法。例如创建一个表示用户信息的`User`类,并配置其与数据库表之间的映射关系,通过简单的操作实现用户的增删改查等功能。这样的示例有助于初学者...

    JAVA上百实例源码以及开源项目源代码

    简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 凯撒加密解密程序 1个目标文件 1、程序结构化,用函数分别实现 2、对文件的加密,解密输出到文件 利用随机函数抽取幸运数字 ...

    Java面试试题(二).docx

    - **定义**:动态代理允许在运行时创建实现一个或多个接口的类,通常用于实现AOP(面向切面编程)。 - **应用场景**: - **AOP实现**:例如Spring AOP利用动态代理实现切面编程,增强目标类的功能。 - **性能...

    java架构图示

    Hibernate是一个全功能的ORM解决方案,它提供了一种机制,可以将Java对象映射到数据库表,并且可以将数据库查询语言转换为SQL。Hibernate架构图通常展示以下关键组件: - **Configuration**: 配置文件,定义了...

    2018年Java面试集锦

    8. **Spring框架**:Spring的核心组件如IoC、AOP,以及Spring Boot、Spring Cloud等相关知识,面试中可能会让你解释依赖注入的原理或者实现一个简单的AOP切面。 9. **数据库**:SQL基础,如查询优化、索引、事务...

    百度2019年最新面试题库

    用于提供一个部分实现的基础,子类可以继承并覆盖方法。 #### IOC的优点是什么 - **Inversion of Control (IoC)**: 是一种设计模式,用于降低组件之间的耦合度。通过将对象的创建和管理权交给第三方容器(如Spring...

    Java 最常见的 200+ 面试题:面试必备(附详解答案).zip

    以上只是部分Java面试中可能会遇到的知识点,具体到这份PDF文件中,每个问题都会配有详细的解答,帮助面试者更好地理解和掌握Java技术。对于正在寻找Java工作或者希望提升自己技能的开发者来说,这份资源无疑是非常...

    1剑盛二面准备试题.txt1剑盛二面准备试题.txt

    一个类可以实现多个接口,但只能继承一个抽象类。接口是一种更松耦合的结构。 15. **Java中IO流的分类**:Java中的IO流分为输入流和输出流,再细分可以分为字节流(InputStream、OutputStream)和字符流(Reader、...

    Java开发技术大全 清晰版

    13. 反射:动态获取类信息,创建并调用对象,修改私有成员,实现动态代理。 14. 注解:自定义注解,了解编译时注解和运行时注解,以及元注解的使用。 七、JVM 15. 类加载机制:类加载过程(加载、验证、准备、解析...

    java面试技巧及笔试汇集

    1. 常见设计模式:熟悉单例、工厂、抽象工厂、建造者、适配器、装饰器、代理、观察者等设计模式的实现。 八、框架知识 SSH(Spring、Struts、Hibernate)是经典的Java企业级开发框架,面试中可能会涉及Spring的依赖...

    java-test.zip_java面试题

    - 动态代理:Java动态代理的实现,InvocationHandler接口。 6. **设计模式**: - 常见的23种设计模式:单例、工厂、建造者、观察者、装饰者、适配器、策略等模式的应用场景与实现。 7. **JVM优化**: - 内存...

    Spring 2.0 开发参考手册

    9.9.1. 对一个特定的 DataSource 使用错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1. 简介 11.1.1. Spring ...

    Java岗面试题库.7z

    Java岗面试题库通常会涵盖Java编程语言的基础、进阶概念、框架应用、并发处理、设计模式、数据库操作以及常见的面试技巧等多个方面。以下是一些可能出现在Java面试中的关键知识点: 1. **Java基础** - 数据类型:...

    java面试题 汇总

    Java面试题汇总是一个珍贵的学习资源,专为Java开发者和毕业生准备,旨在帮助他们更好地理解和掌握Java编程语言的核心概念,以及在实际面试中可能遇到的问题。这份资料包含了广泛的Java面试问题,覆盖了从基础到高级...

    2023年6月14日java面试笔试题.zip

    在Java面试和笔试中,考察的知识点非常广泛,涵盖了基础语法、面向对象、集合框架、多线程、异常处理、IO流、网络编程、数据库操作、设计模式、JVM优化等多个方面。以下是一些可能被问到的重要知识点的详细解释: 1...

    Java八股文+Java面试题,面试找工作,基础薄弱,初中高级开发都适用+面试题,基础学习

    - NIO(New Input/Output):通道(Channel)、缓冲区(Buffer)和选择器(Selector)的概念。 - 文件操作:File类的常用方法及文件复制。 5. **反射与注解**: - 反射:Class类的使用,动态创建对象,调用方法...

    spring chm文档

    9.9.1. 对一个特定的 DataSource 使用错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1. 简介 11.1.1. Spring ...

    Java工程师面试宝典

    - **装饰器模式**:动态地给一个对象添加新的职责,无需通过子类实现。 - **观察者模式**:定义对象间的一对多依赖,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 - **策略模式**:定义...

Global site tag (gtag.js) - Google Analytics