Java

本类阅读TOP10

·使用MyEclipse开发Struts框架的Hello World!(录像1)
·hibernate配置笔记
·AOP编程入门--Java篇
·linux下Tomcat 5.0.20 与 Apache 2 安装/集成/配置
·在win2003下整合了整合Tomcat5.5+ apache_2.0.53+ mod_jk_2.0.47.dll
·构建Linux下IDE环境--Eclipse篇
·Jsp 连接 mySQL、Oracle 数据库备忘(Windows平台)
·ASP、JSP、PHP 三种技术比较
·Tomcat5.5.9的安装配置
·AWT GUI 设计笔记(二)

分类导航
VC语言Delphi
VB语言ASP
PerlJava
Script数据库
其他语言游戏开发
文件格式网站制作
软件工程.NET开发
**ibernate Interceptor很AOP的搞定对象修改纪录的保存

作者:未知 来源:月光软件站 加入时间:2005-2-28 月光软件站

 在项目收尾阶段,客户突然提出一个很麻烦但也很正常的需求,系统内的一切改动都要进行记录。格式如:
    2004.1.1 12:30  郁也风 销售订单 订货日期 2004.1.2->2004.1.3
   
    第一时间我就想到了也很AOP的Trigger,但Trigger毕竟和Java代码是两个世界,怎么把操作员名字传进去就有点麻烦(要所有表再加一个last modifier的列,然后修改程序),同时Trigger一个很不够AOP的地方就是有多少个表就要写多少个Trigger,有多少个列就要写多少列。
    Hibernate的Community Area 刚好有一篇History Interceptor的文章,很AOP的解决了这个问题。虽然用Velocity生成Trigger可能更加集中快捷,但技术的狂热驱使我去尝试了方法2。
 
1.Hibernate Inteceptor 概念
  Inteceptor--拦截器的概念源自AOP,在2.1.6中文版的参考手册里面这样写
  Interceptor接口提供从session到你的应用程序的回调方法,让你的程序可以在持久化对象保存/更改/删除或者装载的时候操作它的属性。典型代码:
public class AuditInterceptor implements Interceptor, Serializable 
{
   public boolean onFlushDirty(Object entity,
                                Serializable id,
                                Object[] currentState,
                                Object[] previousState,
                                String[] propertyNames,
                                Type[] types) 
   {
        if ( entity instanceof Auditable )
       {
            for ( int i=0; i < propertyNames.length; i++ )
            {
                if ( "lastUpdateTimestamp".equals( propertyNames[i] ) )
               {
                    currentState[i] = new Date();
                    return true;
                }
            }
        }
        return false;
    }
}
当session被创建的时候,指定拦截器。
Session session = sf.openSession( new AuditInterceptor() );
 
可见,Interceptor的基本模式是
1.提供onLoad(),onSave(),onDelete,onFlushDirty()几个回调函数。
   在创建session时向session指定Interceptor.

2.每个回调函数的参数如下,已经足够作任何事情
   1.Object entity   对象
   2.Serializable id   对象的id
   3.String[] propertyNames  属性的名称数组
   4.Type[] types   属性的类型数组
   5.Object[] previousState  更新前的属性值
   6.Object[] currentState    更新后的属性值
 
3.在函数内,通过if ( entity instanceof Auditable )判断是否目标对象类型.
 
2.History Interceptor模式
1.所有需要记录更改历史的VO implement Historizable接口。
   History Interceptor根据 if ( entity instanceof Historizable)l来判断是否需要干活。

2.所有VO含有setLastModifyer()函数。在程序中把操作员名字传入。

3.创建HistoryEntry的POJO和hbm
   包含如下的列 id,who,what,property,oldValue,newValue
 
4.创建一个History表,靠history_type列用继承映射为不同的子类,如GoodsHistory,CustomerHistory。
 
5.为所有需要纪录更改历史的对象在POJO和hbm中加入historyEntry Set。
6.留意属性除String,BigDecimal等基本类型外,其他内嵌对象要保证有Equals函数和toString()函数.
用hbm2java生成的java code,  toString()函数输出的是ID,需要改为有意义的ID+name,
可以在hbm里把name属性的<meta>设为<meta-attribute name="is-tostring-value" value="true">
 
3.剩下的问题
  1.单层的对象已经获得完美的解决,但对于订单的子对象又如何解决呢?

  2.如何高效利用i18把被更改的表名和列名翻译成中文。
  3.Spring虽可在<Session Factory>或者<trancetion manager>节点定义<Entity Interceptor>,但在onflushDirty()函数中老是拿不到previousState,虽然同事找到方法暂时解决了,但总是不正规.
 
    其中问题1是Trigger更加无法完成的。



相关文章

相关软件