Hibernate數據攔截與事件監聽實現審計日志


攔截器(Interceptor)
org.hibernate.Interceptor接口定義了Hibernate中通用攔截機制
創建Session對象的時候,所有的Session對象或者這個Session對象的所有持久化操作的動作都會被指定的攔截器進行攔截.


Interceptor接口的方法

  • afterTransactionBegin()
    當一個事務時候啟動時,會立刻調用這個方法,這個方法可以改變這個事務的狀態,例如:回滾事務
  • instantiate()
    創建對象,如果返回null,則Hibernate將調用實體類的默認構造方法創建持久化對象
  • getEntity()
    當一個持久化對象,通過標示符屬性在Session對象的緩存中進行查找,並且沒有找到時,會調用該方法
  • getEntityName()
    當session對象獲取持久化對象的名字時,會調用這個方法
  • onLoad()
    該方法在持久化對象初始化之前加載,這個的持久化對象處於剛被創建的狀態(對象的屬性值都未賦值)
  • findDirty()
    當調用Session對象的flush()方法時,講調用該方法判斷對象是否為臟數據,這是臟數據檢查的另外攔截的實現方式
  • isTransient()
    當調用Session對象的saveOrUpdate方法時,會調用該方法判斷對象是否尚未保存
  • onSave()
    在對象被保存之前調用,通過這個方法可以對要保持的對象的屬性進行修改
  • onDelete()
    該方法在持久化對象被刪除之前調用
  • preFlush()
    該方法當調用Session對象的flush()方法之前被調用
  • onFlushDirty()
    當調用Session對象flush()方法進行臟數據檢查時,如果發現持久化對象的狀態發生了改變,會調用該方法
  • postFlush()
    該方法調用Session對象的flush()方法之后被調用
  • beforeTransactionCompletion()
    在完成一個事務之前,調用此方法,這個方法可以改變事務的狀態,例如回滾事務
  • afterTransactionCompletion()
    當完成一個事務之后,立刻調用此方法

使用攔截器實現審計日志
審計日志指的是,在應用系統中,對所有的數據庫的操作都做記錄,記錄所操作內容,操作的用戶和操作的時間

demo

log4j.properties

Log4j.properties代碼   收藏代碼
  1. log4j.logger.com.rbh.examples=info,appender1  
  2. log4j.appender.appender1=org.apache.log4j.FileAppender  
  3. log4j.appender.appender1.layout=org.apache.log4j.TTCCLayout  
  4. log4j.appender.appender1.File=ligfile.txt  

LogEntityInterceptor

Java代碼   收藏代碼
  1. package com.rbh.examples;  
  2. import java.io.Serializable;  
  3. import org.apache.log4j.Logger;  
  4. import org.hibernate.EmptyInterceptor;  
  5. import org.hibernate.type.Type;  
  6.   
  7. public class LogEntityInterceptor extends EmptyInterceptor {  
  8.   
  9.     private static final long serialVersionUID = 1L;  
  10.       
  11.     private Logger logger = Logger.getLogger(LogEntityInterceptor.class);  
  12.   
  13.     public void onDelete(Object entity,Serializable id, Object[] state,String[] propertyNames,  
  14.             Type[] types){  
  15.         logger.info("刪除數據");  
  16.     }  
  17.       
  18.     public boolean onFlushDirty(Object entity,Serializable id, Object[] currentState,  
  19.             Object[] preState,String[] propertyNames,  
  20.             Type[] types){  
  21.         logger.info("修改數據");  
  22.         return false;  
  23.     }  
  24.       
  25.     public boolean onSave(Object entity,Serializable id, Object[] State,  
  26.             String[] propertyNames,  
  27.             Type[] types){  
  28.         logger.info("保存數據");  
  29.         return false;  
  30.     }  
  31. }  

 

HibernateTest

Java代碼   收藏代碼
  1. package com.rbh.examples;  
  2.   
  3. import java.util.Date;  
  4. import org.hibernate.Session;  
  5. import org.hibernate.SessionFactory;  
  6. import org.hibernate.cfg.Configuration;  
  7.   
  8. public class HibernateTest {  
  9.     public static void main(String[] args)   
  10.     {  
  11.         HibernateTest test =new HibernateTest();  
  12.         test.testInterceptor();  
  13.     }         
  14.       
  15.     public void testInterceptor()  
  16.     {  
  17.         LogEntityInterceptor interceptor=new LogEntityInterceptor();  
  18.         Configuration config=new Configuration();  
  19.         config.setInterceptor(interceptor);  
  20.         config.configure();  
  21.           
  22.         SessionFactory sf=config.buildSessionFactory();  
  23.         Session session=sf.getCurrentSession();  
  24.           
  25.         Guestbook gb= new Guestbook();  
  26.         gb.setName("Narcissus");  
  27.         gb.setEmail("javac.q@gmail.com");  
  28.         gb.setCreatedTime(new Date());  
  29.         gb.setPhone("11102121");  
  30.         gb.setTitle("test Interceptor");  
  31.         gb.setContent("test Interceptor,test Interceptor");  
  32.   
  33.           
  34.         session.beginTransaction();  
  35.         session.save(gb);  
  36.         session.getTransaction().commit();  
  37.           
  38.         session=sf.getCurrentSession();  
  39.         gb.setName("tom");  
  40.         session.beginTransaction();  
  41.         session.update(gb);  
  42.         session.getTransaction().commit();  
  43.           
  44.         session=sf.getCurrentSession();  
  45.         session.beginTransaction();  
  46.         session.delete(gb);  
  47.         session.getTransaction().commit();  
  48.     }  
  49.       
  50. }  

可以通過session方式加載攔截器對象,也可以通過Configuration對象加載攔截器

Configuration:對所有的session都會被攔截
session:只對當前的session進行攔截

 

Hibernate的事件監聽機制

Hibernate中的事件監聽機制可以對Session對象的動作進行監聽,一旦發生了特殊的事件,Hibernate就會執行監聽器中的事件處理方法

在某些功能的設計中,我們即可以使用Hibernate的攔截器實現,也可以使用Hibernate的事件監聽來實現

 

Hibernate中事件與對應的監聽器接口

        事件類型                        監聽器接口

                     auto-flush                                                    AutoFlushEventListener
                        merge                                                       MergeEventListener
                        delete                                                       DeleteEventListener
                        persist                                                      PersistEventListener
                    dirty-check                                                    DirtyCheckEventListener
                         evice                                                        EvictEventListener
                          flush                                                        FlushEventListener
                    flush-entity                                                    FlushEntityEventListener
                          load                                                         LoadEventListener
                 load-collection                                                  InitializeCollectEventListener
                          lock                                                          LockEventListener
                      refresh                                                         RefreshEventListener
                      replicate                                                      ReplicateEventListener
                     save-update                                                 SaveOrUpdateEventListener
                     pre-load                                                        PreLoadEventListener
                     pre-update                                                    PreUpdateEventListener
                     pre-delete                                                     PreDeleteEventListener
                     pre-insert                                                      PreInsertEventListener
                     post-load                                                       PostLoadEventListener
                     post-update                                                   PostUpdateEventListener
                     post-delete                                                    PostDeleteEventListener
                     post-insert                                                     PostInsertEventListener

 


應用Hibernate事件監聽器

用戶制定的事件監聽器首先需要實現與所需要處理的事件對應的接口,或者繼承實現這個接口的類

通過使用Hibernate的配置文件(hibernate.cfg.xml)配置事件監聽對象,或者使用Configuration對象注冊這個定制的事件監聽器對象

LogPostLoadEventListener

Java代碼   收藏代碼
  1. import org.hibernate.event.PostLoadEvent;  
  2. import org.hibernate.event.PostLoadEventListener;  
  3. public class LogPostLoadEventListener implements PostLoadEventListener {  
  4.     private static final long serialVersionUID = 404241098418965422L;  
  5.     public void onPostLoad(PostLoadEvent event) {  
  6.         System.out.println("Class:" + event.getEntity().getClass().getName() + ",id:"  
  7.                 + event.getId());  
  8.     }  
  9. }  

 

修改Hibernate.cfg.xml文件

Xml代碼   收藏代碼
  1. <mapping resource="com/rbh/examples/Guestbook.hbm.xml" />  
  2.         <listener type="post-load" class="com.rbh.examples.LogPostLoadEventListener" />  
  3.     </session-factory>  
  4. </hibernate-configuration>  

 

或者通過Configuration 對象注冊這個監聽器對象

Java代碼   收藏代碼
  1. Configuration config = new Configuration();  
  2. config.setListener("post-load"new LogPostLoadEventListener());  
  3. config.configure();  
  4. Session session = config.buildSessionFactory().getCurrentSession();  

 編寫、配置好監聽器以后,當通過Session對象的load()、get()方法或者Query對象的list方法加載持久化對象之后,LogPostEventListener對象中的onPostLoad()方法就會被執行.

 

使用監聽器實現審計日志

利用Hibernate的事件機制,不僅能夠精確追蹤到持久化對象的字段的修改,持久化對象關聯關系的變更,還能記錄更新前的數值和更新后的數值

 

監聽器與攔截器的比較

監聽器可以實現更細化粒度的攔截
通過監聽器獲取所攔截的持久化對象的修改后喝修改前的狀態值
能直接通過Event對象獲取Session對象

 

 使用監聽器實現審計日志的一個demo 見附件

簡要說明:AuditLog表式記錄 日志的表

AuditLog.java 和AuditLog.hbm.xml表的持久化映射

AuditLogEventListener 具體的實現類

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM