<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 431,  comments - 344,  trackbacks - 0
     

    在某些情況下,我們需要對實體的CURD操作進行捕獲并執行一些操作,這可以通過數據庫觸發器來實現,但是正如我們上一節中所分析的,由于觸發器的執行對Hibernate Session是透明的,因此會帶來很多問題(參見上一節)。為此Hibernate提供了一些專門用于捕獲監聽實體CURD操作的接口,通過這些接口可以實現類似觸發器的功能,能夠在實體發生CURD操作時捕獲事件,并且執行相應的動作邏輯。在Hibernate中這些接口是:Lifecycle,Validatable,Interceptor,下面我們就分別講解怎樣通過這些接口,實現回調攔截的技術細節。

    A、LifecycleValidatable

     HibernateLifecycle接口定義如下:

    public interface Lifecycle{

     /**

       在實體對象執行save/insert操作之前觸發

     **/

     public boolean onSave(Session session) throws CallbackException;

     /**

       session.update()執行之前觸發

     **/

     public boolean onUpdate(Session session) throws CallbackException;

     /**

     在實體對象執行delete操作之前觸發

    **/

    public boolean onDelete(Session session) throws CallbackException;

    /**

     在實體對象加載之后觸發

    **/

    public void onLoad(Session session) throws CallbackException;

    }

    實體對象可以實現Lifecycle接口,來獲得在持久化階段捕獲CURD事件,并執行相應動作的能如下所示:

    public class User implements Serializable,Lifecycle{

     public boolean onSave(Session s) throws CallbackException{

    ……

    return false;

    ……

     }

     public boolean onUpdate(Session s) throws CallbackException{

    ……

    return true;

    ……

     }

     public boolean onDelete(Session s) throws CallbackException{

    ……

    return false;

    ……

     }

     public boolean onLoad(Session s) throws CallbackException{

    ……

     }

    }

    對于onSave,onUpdate,onDelete方法,如果返回true則意味著需要終止執行對應的操作過程。如果在運行時拋出CallbackException,對應的操作也會被終止。

    注意在接口中對應的方法中,不要去通過方法的Session參數執行持久化操作,在這些方法中Session無法正常使用,如果必須要執行一些持久化操作,那么需要進行特殊的處理,我們將在Interceptor部分詳細講解。

    Hibernate中還定義了Validatable接口,該接口定義如下:

    public interface Validatable{

     public void validate() throws ValidationFailure;

    }

    Validatable接口是用來實現數據驗證的,實體類實現Validatable接口,并在接口的validate方法中實現數據驗證邏輯,以保證數據輸入的合法性。validate方法將會在實體對象持久化前得到調用進行數據驗證,與Lifecycle接口中的方法不同,Validatable.validate()方法在實體生命周期中可能被多次調用,因此此方法應該僅限于數據合法性的驗證,而不應該實現業務邏輯的驗證。

    BInterceptor:

    以上是Hibernate提供的Lifecycle接口和Validatable接口,以及使用方法,這兩個方法定義了一種自然的回調機制,但是如我們所見,如果想實現對實體的回調攔截,那么相應的實體對象必須實現這兩個Hibernate原生接口,這就使代碼的可移植性大大下降,因為此時實體類已經不再是一個POJO了,Hibernate的那些天才的設計者們也已經意識到了這個問題,所以又提供了Interceptor接口,為持久化事件的捕獲和處理提供了一個非入侵性的解決方案,Interceptor接口通過設置注入來實現持久化事件的捕獲和處理,這是典型的IOC(控制反轉)設計思想。下面我們就講解Interceptor接口的技術細節和使用方法。

    Hibernate中的Interceptor接口定義如下:

    public interface Interceptor{

     //對象初始化之前調用,這時實體對象剛剛被創建,各個屬性還都為null,如果在這個方法中修改了實體對象的數據,那么返回true,否則返回null.

     public boolean onLoad(Object entity,Serializable id,Object[] state,

    String[] propertyNames,Type[] types) throws CallbackException;

          //Session.flush()在進行臟數據檢查時,如果發現實體對象數據已臟,就調用此方法

     public boolean onFlushDirty(Object entity,Serializable id,Object[] state,

    String[] propertyNames,Type[] types) throws CallbackException;

     //實體對象被保存前調用,如果在這個方法中修改了實體對象的數據,那么返回true,否則返回null.

     public boolean onSave(Object entity,Serializable id,Object[] state,

    String[] propertyNames,Type[] types) throws CallbackException;

         //通過Session刪除一個實體對象前調用

     public boolean onDelete(Object entity,Serializable id,Object[] state,

    String[] propertyNames,Type[] types) throws CallbackException;

         //Session執行flush()之前調用

    public boolean preFlush(Iterator entities) throws CallbackException;

         //Session執行flush()之后,所有的SQL語句都執行完畢后調用

    public boolean postFlush(Iterator entities) throws CallbackException;

         //當執行saveOrUpdate方法時調用,判斷實體對象是否已經保存

         public Boolean isUnsaved(Object entity);

         //執行Session.flush()方法時,調用此方法判斷該對象是否為臟對象,這提供了臟數據檢查的另一個回調攔截機制

    public int[] findDirty(Object entity,Serializable id,Object[] state,

    String[] propertyNames,Type[] types) throws CallbackException;

         //Session構造實體類實例前調用,如果返回null,Hibernate會按照默認方式構造實體類對象實例

    public Object findDirty(Class clazz,Serializable id) throws CallbackException;

    }

    Intercepter不需要實體對象來實現,而是通過開發人員定義一個實現Interceptor接口的類,然后在創建Hibernate Session時,通過將Interceptor對象設置進所創建的Session,這樣通過這個Session來操作的實體對象,就都會具有對持久化動作的回調攔截能力。在HibernateInterceptor對象共有兩種用法,如下所述:

    1                SessionFactory.openSession(Interceptor):為每個Session實例分配一個攔截Interceptor,這個攔截接口對象,存放在Session范圍內,為每個Session實例所專用。

    2、                Configuration.setInterceptor(Interceptor):SessionFactory實例分配一個Interceptor實例,這個Interceptor實例存放在SessionFactory范圍內,被每個Session實例所共享。

    A、Interceptor的典型應用:

    下面我實現一個利用Interceptor接口實現日志數據稽核的功能,所謂日志數據稽核就是針對一些關鍵操作進行記錄,以便作為業務跟蹤的基礎依據。

    首先定義用于記錄操作的實體:

    public class AudiLog implements Serializable{

     private String id;

     private String user;

     private String action;

     private String entityName;

     private String comment;

     private Long logtime;

     …getter/setter…

    }

    接下來定義Interceptor接口的實現類和用于持久化操作的AuditDAO類:

    package com.lbs.apps.unemployment.subsidy.beforeinfoimport.util;

    import net.sf.hibernate.Session;

    import net.sf.hibernate.Interceptor;

    import Java.io.Serializable;

    import net.sf.hibernate.type.Type;

    import net.sf.hibernate.HibernateException;

    import Java.util.Iterator;

    import Java.util.Set;

    import Java.util.HashSet;

    import com.neusoft.entity.User;

    public class MyInterceptor implements Interceptor{

     private Set insertset=new HashSet();

     private Set updateset=new HashSet();

     private Session session;

     private String userID;

     public void setSession(Session session){

        this.session=session

    ?。?/span>

     public void setUserID(String id){

       this.userID=id;

     }

     public boolean onLoad(Object object, Serializable serializable,

                            Object[] objectArray, String[] stringArray,

                            Type[] typeArray) {

        return false;

     }

     public boolean onFlushDirty(Object object, Serializable serializable,

                                  Object[] objectArray, Object[] objectArray3,

                                  String[] stringArray, Type[] typeArray) {

        if(object instanceof User){

          insertset.add(object);

        }

        return false;

     }

     public boolean onSave(Object object, Serializable serializable,

                            Object[] objectArray, String[] stringArray,

                            Type[] typeArray) {

        if(object instanceof User){

          updateset.add(object);

        }

        return false;

     }

     public void onDelete(Object object, Serializable serializable,

                           Object[] objectArray, String[] stringArray,

                           Type[] typeArray) {

     }

     public void preFlush(Iterator iterator) {

     }

     public void postFlush(Iterator iterator) {

    try{

     if(insertset.size()>0){

       AuditDAO.dolog(“insert”,userID,inserset,session.connection);

     }

     if(updateset.size()>0){

       AuditDAO.dolog(“update”,userID,updateset,session.connection);

     }

    }catch(HibernateException he){

     he.printStackTrace();

    }

     }

     public Boolean isUnsaved(Object object) {

        return null;

     }

     public int[] findDirty(Object object, Serializable serializable,

                             Object[] objectArray, Object[] objectArray3,

                             String[] stringArray, Type[] typeArray) {

        return null;

     }

     public Object instantiate(Class class0, Serializable serializable) {

        return "";

     }

    }

    public class AuditDAO{

     public static void doLog(String action,String userID,Set modifySet,Connection connection){

         Session tempsession=HibernateUtil.getSessionFactory().openSession(connection);

         try{

           Iterator it=modifyset.iterator();

           while(it.hasNext()){

             User user=(User)it.next();

             AudiLog log=new AudiLog();

             log.setUserID(userID);

             log.setAction(action);

             log.setComment(user.toString());

             log.setLogTime(new Long(Calendar.getInstance().getTime().getTime()));

             tempsession.save(log);

           }

         }catch(Exception e){

           throw new CallbackException(e);

         }finally{

           try{

             tempsesson.close();

           }catch(HibernateException he){

             throw new CallbackException(he);

           }

         }

     }

    }

    最后看一下業務邏輯主程序:

    SessionFactory sessionfactory=config.buildSessionFactory();

    MyInterceptor it=new MyInterceptor();

    session=sessionfactory().openSession(it);

    it.setUserID(“currentUser”);

    it.setSession(session);

    User user=new User();

    user.setName(“zx”);

    Transaction tx=session.beginTransaction();

    session.save(user);

    tx.commit();

    session.close();

    以上示例代碼中,在創建Session時,設置Interceptor實例對象,當執行到session.save(user)前,會觸發onSave()方法,當執行tx.commit()時,會執行flush(),在執行該方法后會觸發postFlush()方法,這個方法通過AuditDAO進行持久化保存業務日志,在這個類中的紅色部分時有關持久化操作部分,我們并沒有使用原有的Session實例,這是因為要避免Session內部狀態混亂,因此我們依托當前SessionJDBC Connection創建了一個臨時Session用于保存操作記錄,在這個持久化操作中沒有啟動事務,這是因為臨時Session中的JDBC Connection是與外圍調用InterceptorSession共享,而事務已經在外圍SessionJDBC Connection上啟動。這是在攔截方法中進行持久化操作的標準方法??傊?/span>Interceptor提供了非入侵性的回調攔截機制,使我們可以方便而且優雅的實現一些持久化操作的特殊需求。
    posted on 2009-06-11 16:49 周銳 閱讀(524) 評論(0)  編輯  收藏 所屬分類: Hibernate
    主站蜘蛛池模板: 四虎影视永久免费视频观看| 亚洲熟妇无码av另类vr影视| 日本无吗免费一二区| 95老司机免费福利| 青青操免费在线观看| 特级毛片在线大全免费播放| 亚洲中文字幕无码久久2020 | 亚洲人成网站在线在线观看| 亚洲色图在线观看| 亚洲av午夜成人片精品网站| 亚洲人成色7777在线观看不卡| 成人免费a级毛片无码网站入口 | 久久亚洲国产欧洲精品一| 99re热免费精品视频观看| 久9久9精品免费观看| 97性无码区免费| 亚洲视频免费在线观看| A国产一区二区免费入口| 免费国产高清毛不卡片基地| 国产亚洲午夜精品| 美女被吸屁股免费网站| 亚洲欧美国产欧美色欲| 亚洲精品无码mⅴ在线观看| 在线综合亚洲欧洲综合网站| 亚洲伦理中文字幕| 亚洲日日做天天做日日谢| 亚洲av永久无码精品天堂久久| 亚洲精品人成电影网| 91嫩草私人成人亚洲影院| 亚洲天天做日日做天天看| 久久亚洲中文字幕精品有坂深雪| 亚洲AV永久无码区成人网站 | 99re6在线精品免费观看| 中文字幕免费观看视频| a国产成人免费视频| 免费一区二区三区| 日韩人妻一区二区三区免费 | 亚洲午夜久久久久久尤物| 亚洲欧洲日韩极速播放 | 国产jizzjizz免费看jizz| 免费在线观看毛片|