[读书总结]Hibernate的事件框架

原创 2007年09月28日 17:08:00
   通常,载Hibernate执行持久化的过程中,应用程序无法参与其中。因为所有的数据持久化操作,对用户都是透明的,所以用户无法加入自己的动作。 
   通过事件框架,Hibernate允许应用程序能响应特定的内部事件,从而实现某些通用的功能,或者允许对Hibernate功能进行扩展。
   Hibernate的事件框架由以下两部分组成。
      ●拦截器机制:对于特定动作拦截,回调应用中的特定动作。
   ●事件系统:重写Hibernate的事件监听器。
   1.拦截器:
      通过Inteceptor接口,可以从Session中回调应用程序的特定方法,这种回调机制可让应用程序在持久化对象被保存,更新,删除或加载之前,对其进行检查并修改其属性。
      通过Inteceptor接口,可以在数据进入数据库之前,对数据进行最后的检查,如果数据不符合要求,则可以修改,从而避免非法数据进入数据库。当然,通常无须这样做,只有在某些特殊的场合下,才考虑使用拦截器完成检查功能。
      使用拦截器时按如下步骤进行:
         (1)定义实现Interceptor接口的拦截器类。
         (2)通过Session起用拦截器,或者通过Configuration启用全局拦截器。
      下面是一个拦截器的简单示例的代码:
public class MyInterceptor extends EmptyInterceptor {
    public void onDelete(Object entity,Serializable id,Object[] state,
        String[] propertyNames,Type[] types) {
         System.out.println("该方法在删除数据时调用");
   }
}
   拦截器的使用有两种方法:
      ●通过SessionFactory的openSession(Interceptor in)方法打开一个带局部拦截器的Session。
   ●同过Configuration的setInterceptor(Interceptor in)方法设置全局拦截器。
      下面是使用拦截器的示例的部分代码:
public class HibernateUtil {
   public static final SessionFactory sessionFactory;
   static{
      try{
         Configuration configuration = new Configuration().configure();
         sessionFactory = configuration.buildSessionFactory();
      }catch (Throwable ex) {
         System.err.println("初始化sessionFactory失败。" + ex);
         throw new ExceptionInInitializerError(ex);
      }
   }
   public static final ThreadLocal session = new ThreadLocal();
   public static Session currentSession(Interceptor it) throws HibernateException {
      Session s = (Session) session.get();
      if(s == null) {
         s = sessionFactory.openSession(it);
         session.set(s);
      }
      return s;
   }
   public static void closeSession() throws HibernateException {
       Session s = (Session) session.get();
       if (s != null)
         s.close();
       session.set(null);
   }
}
   2.事件系统:
      Hibernate3事件系统是功能更强大的事件框架,该事件系统可以替代拦截器,也可以作为拦截器的补充来使用。
      基本上,Session接口的每个方法都有对应的事件。比如LoadEvent,FlushEvent等。事实上,当Session调用某方法时,Hibernate Session会生成对应的事件,并激活对应的事件监听器。在系统默认监听器实现的处理过程中,完成了对所有的数据持久化的操作,包括插入和修改等操作。如果用户定义了自己的监听器,则意味着用户必须完成对象的持久化操作。
      例如,可以在系统中实现并注册LoadEventListener,该监听器负责处理所有调用Session的load()的方法的请求。
      由于监听器是单态模式对象,即所有的同类型的事件处理共享同一个监听器实例,因此,此监听器不应该保存任何状态,即不应该使用成员变量。
      使用事件系统时按如下步骤进行:
         (1)实现自己的事件监听器类。
         (2)注册自定义事件监听器,代替系统默认的事件监听器。
      实现用户的自定义监听器有如下三个方法:
      ●实现对应的监听器接口:这是不可思议的,实现接口必须实现接口内的所有方法,关键是必须实现Hibernate对应的持久化操作,即数据库访问,这意味着程序员完全取代了Hibernate的底层操作。
   ●继承事件适配器:可以选择地实现需要关注的方法,但依然需要替代Hibernate完成数据库访问。这也不太现实。
   ●继承系统默认的事件监听器:扩展特定的方法。
      实际上,前两种方法很少使用。因为Hibernate的持久化操作也是通过这些监听器实现的,如果用户取代了这些监听器,则应该自己实现持久化操作,这意味着用户放弃了Hibernate的持久化操作,而改为自己完成Hibernate的核心操作。
      通常我们采用第三种方法实现自己的事件监听器。因为Hibernate默认的事件监听器被声明成non-final,从而方便用户继承。
      下面是用户自定义监听器的示例:
//自定义LoadListener,继承默认的DefaultLoadEventListener实现类
public class MyLoadListener extends DefaultLoadEventListener {
    //在LoadEventListener接口仅仅定义了这个方法
    public Object onLoad(LoadEvent event,LoadEventListener.LoadType loadType)
        throws HibernateException {
        Object o = super.onLoad(event,loadType);
        System.out.println("自定义的load事件");
        System.out.println(event.getEntityClassName() + "---------"
             + event.getEntityId());
        return o;
    }
}
      注册用户自定义监听器也有以下两种方法。
         ●编程式:通过使用Configuration对象编程注册。
     ●声明式:在Hibernate的XML格式的配置文件中进行声明,使用Properties格式的配置文件将无法配置自定义监听器。
      通过编程式方式使用自定义监听器时,只需将HibernateUtil中的静态块儿用如下的静态块儿替代即可:
      static{
         try{
            Configuration cfg = new Configuration();
            cfg.getSessionEventListenerConfig().setLoadEventListener(
               new MyLoadListener());
            sessionFactory = cfg.configure().buildSessionFactory();
   
         } catch(Throwable ex) {
            System.err.println("初始化sessionFactory失败。" + ex);
            throw new ExceptionInInitializerError(ex);
         } 
      }
      
      使用声明式方式使用自定义监听器时,可在Hibernate配置文件中的<session-factory>元素中增加:
         <listener type="load" class="MyLoadListener">
子元素即可。
      使用配置文件注册事件监听器虽然方便,但也有不利之处:通过配置文件注册的监视器不能共享实例;如果有多个<listener/>元素中使用了相同的类,则每个引用都将产生一个新拦截器实例;如果需要在多个事件之间共享监听器的实例,则必须使用编程式方式来注册事件监听器。
      虽然监听器类实现了特定监听器的接口,但在注册时还要明确指出注册的事件。因为一个类可能实现多个监听器的接口,所以,在注册时明确指定要监听的事件,可以使得启用或者禁用某个事件的监听配置工作更加简单。 

Hibernate框架常用知识点总结

Hibernate配置详解 Hibernate核心详解 Hibernate事务详解 Hibernate多表关系详解
  • shuaicihai
  • shuaicihai
  • 2017年01月16日 09:00
  • 3786

hibernate拦截器与事件

第 13 章 拦截器与事件(Interceptors and events) 应用程序能够响应Hibernate内部产生的特定事件是非常有用的。这样就允许实现某些通用的功能以及允许对Hibernat...
  • jiazimo
  • jiazimo
  • 2014年11月08日 14:55
  • 898

项目总结SpringMVC+hibernate框架 原理(MVC)(1)

本人项目即将结尾,现处于测试阶段,想整理一下备以后使用。其中有部分内容是借助网上的解释。 劲量将所有源码公开,该项目是真正的企业使用项目。  首先看看SpringMVC的框架: 1)Spring...
  • ITpengcheng
  • ITpengcheng
  • 2013年02月28日 17:33
  • 5111

2012年读书年度小结

本文作于寒舍,2013年2月9日       今天是大年三十,待会就是除夕夜了,下午我们在家里打扫了好几遍,把屋子收拾得干干净净,一会儿还会放鞭炮庆祝新年,晚上好吃好喝,然后看看春晚,现...
  • starshus
  • starshus
  • 2013年02月15日 11:18
  • 1317

Hibernate阶段性总结(一)

hibernate它是一个实现对JDBC轻量级封装的ORM(对象关系映射)的框架。处于项目的持久层。主要学习它的hibernate api和hibernate.cfg.xml,对象关系映射文件 ...
  • baidu_21578557
  • baidu_21578557
  • 2016年06月12日 10:40
  • 2675

2016 年度读书总结

2016 年度读书总结《万历十五年》 黄仁宇先生最有名的一部作品,也是研究明史的一部经典之作,时隔多年,重读这部作品,感受已然不同,个人评分四星半。《九州缥缈录》 江南同学创造的九州世界,曾经让...
  • shinian1987
  • shinian1987
  • 2016年12月31日 08:55
  • 1225

Hibernate学习总结(一)

1、什么是Hibernate Hibernate是轻量级JavaEE应用的持久层解决方案,是一个关系数据库ORM框架(ORM,对象关系映射 Object Relationship mapper) ...
  • u012750846
  • u012750846
  • 2015年09月07日 15:36
  • 801

C语言读书心得

[1] Alan R. Feuer, The C Puzzle Book, C语言解惑 2012年5月 整本书主要都是针对C语言程序设计中常容易出现的一些细节上的错误,进行讲述的,内容涉及到了运算符优...
  • yuandong0828
  • yuandong0828
  • 2012年05月22日 21:29
  • 426

基于《如何阅读一本书完整》提炼出分析阅读的核心框架

1.  阅读前通过序、目录、摘要等,对全书有一个大概了解,是否值得阅读 2.  阅读时要解决几个问题 1.  整本书想表达什么 2.  找出作者的想法、声明与论点 3.  对书本有一个大致的判...
  • qq_24890953
  • qq_24890953
  • 2016年02月14日 23:03
  • 305

【SSH进阶之路】Hibernate系列——总结篇(九)

这篇博文是Hibernate系列的最后一篇,既然是最后一篇我们进行一下从头到尾,整体上的总结,将这个系列的内容融会贯通。。。...
  • jiuqiyuliang
  • jiuqiyuliang
  • 2014年11月22日 08:18
  • 17067
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[读书总结]Hibernate的事件框架
举报原因:
原因补充:

(最多只允许输入30个字)