论坛首页 Java企业应用论坛

介绍Hibernate中的Interceptor

浏览 27439 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-10-28  
好像论坛上还没有人介绍过Hibernate的Interceptor的用处吧? 那么今天偶来介绍一下: (以下内容基本上和 http://www.hibernate.org/48.html 类似)

举个实际的例子, 偶们有时候会需要做Audit: 一条记录什么时候被谁创建, 以及最近由谁在何时更新, 以前的做法是在代码里面各处分散地写上:
entity.setCreated(new Date(););; 
entity.setCreatedBy(userId);; 
session.save(entity);;


这样重复的代码就到处都是了, 很不爽呢, OOP号称的once and only once不应该是这样的吧, 让偶们来看看Interceptor它怎么帮忙解决这个问题

先来定义一个mark性质的interface:
public interface Auditable { 
    public AuditInfo getAuditInfo();; 
    public void setAuditInfo(AuditInfo auditInfo);; 
} 


然后是AuditInfo, 用来记录这些信息:
public final class AuditInfo implements Serializable { 
    private Date lastUpdated; 
    private Date created; 
    private String updatedBy; 
    private String createdBy; 
    //getter, setter 
} 


如果偶们的一个业务对象需要有这样能够被Audit的功能, 那么就让它实现Auditable这个接口:
public class FooBean implements Auditable { 
    private Long id;
    private String bar;     
    private AuditInfo auditInfo = new AuditInfo();; 
    //getter, setter 
} 


然后定义mapping文件:
 <class name="FooBean"> 
  <id name="id"> 
   <generator class="native"/> 
  </id> 
  <property name="bar"/> 
  <property name="auditInfo" type="readonly.persistence.hibernate.type.AuditInfoType"> 
    <column name="LAST_UPDATED"/> 
    <column name="CREATED"/> 
    <column name="UPDATED_BY"/> 
    <column name="CREATED_BY"/> 
  </property> 
 </class> 


然后告诉Hibernate, 在打开session的时候用一个自定义的Interceptor :

    public void testCreated(); { 
        Session session = sf.openSession (new MockAuditInterceptor(););;
        FooBean foo = new FooBean();; 
        foo.setBar("abc");; 
        session.save(foo);;
        session.flush();;
        session.close();;
        assertNotNull(foo.getAuditInfo();.getCreated(););; 
        assertEquals("mock", foo.getAuditInfo();.getCreatedBy(););; 
    } 


That's all, 比原来简单多了, 以后如果你有新的Entity需要这个特性的话, implements Auditable一下, 就OK了, 这样就达到了代码重用的目的了.

Interceptor的用处有很多, 就看偶们怎么从一堆代码中, 总结一些可以公用的特性了, 以此类推, 还能做EntityCRUDPermissionInterceptor, HistoryInterceptor, SearchIndexInterceptor等等......

(注, 遗漏的Interceptor和UserType代码请参考最上面的那个link.)
   发表时间:2004-10-28  
实际使用起来还是会带来很多问题。
可以看一下那些回复!
我也是一直不敢采用它。虽然看上去很美!
0 请登录后投票
   发表时间:2004-10-28  
别人怎么说是别人的事情, 自己写个代码试验一下就知道好用不好用了.
0 请登录后投票
   发表时间:2004-10-28  
既然ReadOnly提起Interceptor,我就想起以前在这里提到的一个问题。因为一直没人搭理,后来超过20天就被删除了,贴到Spring论坛上虽然没被删除,但是也没人指点一句。现在弄出来再看看?

因为需要实现isUnsaved的方法,写了一个Interceptor,在Hibernate文档中说明是这么调用的
Session session = sf.openSession( new MyInterceptor(); );;

那么Spring的AOP Interceptor的Spring模式下使用是没问题,但是为了配置简单,而且也不怎么关心Exception,我用的是IOC(Template and Callback)的模式,那么就不能对Session的建立进行干涉?(这一点Spring的文档倒是没有提到) 那就只能在SessionFactory建立的时候配置Hibernate的Entity Interceptor了。
<bean id="caryoHibernateInterceptor" class="com.caryo.core.persistence.interceptor.CaryoHibernateInterceptor" />
<bean id="sessionFactoryWithInterceptor" class="com.caryo.core.persistence.hibernate.CaryoLocalSessionFactoryBean">
	......
	<property name="entityInterceptor"><ref local="caryoHibernateInterceptor"/></property>
	......
</bean>

在需要用到Interceptor的类就配置这个sessionFactory,现在就是不清楚一个数据库多个SessionFactory会不会有什么问题?如果有问题的话只能考虑自己扩展HibernateTemplate,加多一个execute(HibernateCallback action, Interceptor interceptor)的方法......
0 请登录后投票
   发表时间:2004-10-28  
lllyq 写道

一个数据库多个SessionFactory会不会有什么问题

这样用的话, Cache会有问题, 基于HibernateTransactionManager的事务也会有问题.

Interceptor可以基于SessionFactory Level, 也可以基于HibernateTemplate, 需要用到Interceptor的DAO就注入这个有Interceptor的template:

	<bean id="templateWithInterceptor" class="org.springframework.orm.hibernate.HibernateTemplate">
        <property name="sessionFactory">
            <ref local="sessionFactory"/>
        </property>
		<property name="entityInterceptor">
			<ref local="myInterceptor"/>
		</property>
	</bean>
	
	<bean id="barDAO" class="">
		<property name="hibernateTemplate">
			<ref local="templateWithInterceptor"></ref>
		</property>
	</bean>
0 请登录后投票
   发表时间:2004-10-28  
嘿嘿,原来如此,好极了:D  (居然自己没看到
0 请登录后投票
   发表时间:2004-10-29  
写自己的Interceptor目前有一个问题就是它需要实现的方法太多, 有一些还能通过名字直接看出来意义, 比如onSave, onLoad, 有一些就得看javadoc, 甚至查看hibernate的源代码了. 所以Hibernate 3把Interceptor咔嚓掉, 用更丰富的Event/EventListener来达到同样的可扩展性目的.
0 请登录后投票
   发表时间:2004-10-29  
:idea:
0 请登录后投票
   发表时间:2004-11-02  
做ERP之类的系统用来打时间戳很完美,以前一个系统我就这么干的
0 请登录后投票
   发表时间:2004-11-03  
Readonly 写道
写自己的Interceptor目前有一个问题就是它需要实现的方法太多, 有一些还能通过名字直接看出来意义, 比如onSave, onLoad, 有一些就得看javadoc, 甚至查看hibernate的源代码了. 所以Hibernate 3把Interceptor咔嚓掉, 用更丰富的Event/EventListener来达到同样的可扩展性目的.


介绍的很好,但是据我所知,要实现那个接口不仅仅是实现setter和getter方法吧!好像还有 postFlush什麽的
总之自己要实现的方法太多,而且有的方法莫名其妙,根本不知道是做什麽用的, 还是不用了!可以用AOP的拦截机制代替 
0 请登录后投票
论坛首页 Java企业应用版

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