hibernate 拦截hibernate事件

本文详细介绍了如何使用 Hibernate 实现审计日志功能,包括创建标记接口、映射日志记录类、编写拦截器以及启用拦截器等步骤。重点展示了如何在保存实体时自动记录创建和更新事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

拦截hibernate事件: 
例子实现审计日志: 
1、创建标记接口 
用这个接口给所有应该子被自动审计的持久化类做上标记: 
  1. /** 
  2. * 例子实现审计日志: 
  3. * 1、创建标记接口 
  4. * 用这个接口给所有应该子被自动审计的持久化类做上标记 
  5. * @author partner4java 
  6. * 
  7. */  
  8. public interface Auditable {  
  9.     public Long getId();  
  10. }  

2、创建和映射日志记录 
创建新的持久化类AuditLogRecord。这个类标识你想要的审计数据库表中记入日志信息: 
  1. /** 
  2. * 2、创建和映射日志记录 
  3. * 创建新的持久化类AuditLogRecord。这个类标识你想要的审计数据库表中记入日志信息 
  4. * @author partner4java 
  5. * 
  6. */  
  7. public class AuditLogRecord implements Serializable {  
  8.     private Long auditLogId;  
  9.     private String message;  
  10.     private Long entityId;  
  11.     private Class entityClass;  
  12.     private Long userId;  
  13.     private Date created;  
  14.       
  1.   <class name="AuditLogRecord" table="Audit_Log_Record" mutable="false">  
  2.       <id name="auditLogId" column="audit_Log_Id" type="long">  
  3.           <generator class="native"/>  
  4.       </id>  
  5.   
  6. <property name="message" length="200"></property>  
  7. <property name="entityId" column="entity_Id" type="long" not-null="true"></property>          
  8.       <property name="entityClass" column="entity_Class" type="class" not-null="true"></property>  
  9.       <property name="userId" column="user_Id" type="long"></property>  
  10.       <property name="created" type="java.util.Date" not-null="true" update="false"></property>    
  11.   </class>  


3、编写拦截器 
当调用save时(),应该自动调用logEvent()方法。利用hibernate完成实现Interceptor接口。 
  1. /** 
  2. * 3、编写拦截器 
  3. * 当调用save时(),应该自动调用logEvent()方法。利用hibernate完成实现Interceptor接口。 
  4. * @author partner4java 
  5. * 
  6. */  
  7. public class AuditLogInterceptor extends EmptyInterceptor {  
  8.     private Session session;  
  9.     private Long userId;  
  10.       
  11.     private Set inserts = new HashSet();  
  12.     private Set updates = new HashSet();  
  13.       
  14.   
  15.     public void setSession(Session session) {  
  16.         this.session = session;  
  17.     }  
  18.   
  19.     public void setUserId(Long userId) {  
  20.         this.userId = userId;  
  21.     }  
  22.   
  23.     /** 
  24.      * 每当hibernate侦测到脏对象时,就调用 
  25.      * Called when an object is detected to be dirty, during a flush. The interceptor may modify the detected currentState, which will be propagated to both the database and the persistent object. Note that not all flushes end in actual synchronization with the database, in which case the new currentState will be propagated to the object, but not necessarily (immediately) to the database. It is strongly recommended that the interceptor not modify the previousState. 
  26.      */  
  27.     public boolean onFlushDirty(Object entity, Serializable id,  
  28.             Object[] currentState, Object[] previousState,  
  29.             String[] propertyNames, Type[] types) {  
  30.         if(entity instanceof Auditable){  
  31.             inserts.add(entity);  
  32.         }  
  33.           
  34.         return false;  
  35.     }  
  36.   
  37.     /** 
  38.      * 保存实体时 
  39.      * Called before an object is saved. The interceptor may modify the state, which will be used for the SQL INSERT and propagated to the persistent object. 
  40.      */  
  41.     public boolean onSave(Object entity, Serializable id, Object[] state,  
  42.             String[] propertyNames, Type[] types) {  
  43.         if(entity instanceof Auditable){  
  44.             updates.add(entity);  
  45.         }  
  46.           
  47.         return false;  
  48.     }  
  49.   
  50.     /** 
  51.      * hibernate在执行了把持久化上下文实现为与数据库同步的SQL之后调用他 
  52.      * Called after a flush that actually ends in execution of the SQL statements required to synchronize in-memory state with the database 
  53.      */  
  54.     public void postFlush(Iterator entities) throws CallbackException{  
  55.         try {  
  56.             for(Iterator it = inserts.iterator();it.hasNext();){  
  57.                 Auditable auditable = (Auditable) it.next();  
  58.                 AuditLog.logEvent("create",auditable,userId,session.connection());  
  59.             }  
  60.               
  61.             for(Iterator it = updates.iterator();it.hasNext();){  
  62.                 Auditable auditable = (Auditable) it.next();  
  63.                 AuditLog.logEvent("update",auditable,userId,session.connection());  
  64.             }  
  65.         }finally {  
  66.             inserts.clear();  
  67.             updates.clear();  
  68.         }  
  69.           
  70.     }  
  71.       
  72. }  


4、启用拦截器 
第一次打开会话时,你需要把Interceptor分配到Hibernate Session:
  1. public class ItemDao {  
  2.       
  3.     public void saveDao(Item item){  
  4.         AuditLogInterceptor interceptor = new AuditLogInterceptor();  
  5.         Session session = getSessionFactory().openSession(interceptor);  
  6.         Transaction tx = session.beginTransaction();  
  7.           
  8.         interceptor.setSession(session);  
  9.         interceptor.setUserId(1L);  
  10.           
  11.         session.save(item);  
  12.           
  13.         tx.commit();  
  14.         session.close();  
  15.     }  
  16. }  

AuditLog:
  1. public class AuditLog {  
  2.   
  3.     public static void logEvent(String message, Auditable auditable,  
  4.             Long userId, Connection connection) {  
  5.         Session session = getSessionFactory().openSession(connection);  
  6.           
  7.         try {  
  8.             AuditLogRecord auditLogRecord = new AuditLogRecord(message, auditable.getId(),   
  9.                     auditable.getClass(), userId, new Date());  
  10.             session.save(auditLogRecord);  
  11.             session.flush();  
  12.         } finally{  
  13.             session.close();  
  14.         }  
  15.           
  16.     }  
  17.   
  18. }  


调用:
  1.         ItemDao itemDao = new ItemDao();  
  2.         itemDao.saveDao(new Item("hello2"));  
  3.           
  4. //      hibernate打印:  
  5. //      Hibernate: insert into ITEM (ITEM_NAME) values (?)  
  6. //      Hibernate: insert into Audit_Log_Record (message, entity_Id, entity_Class, user_Id, created) values (?, ?, ?, ?, ?)  







内核事件系统: 
Hibernate3.x与Hibernate2.x相比,是内核持久化引擎实现的一项重要的重新设计。新内核引擎基于一个事件/监听器的模型。 
(默认方法通过DefaultLoadEventListener处理) 
监听器实际上应该被认为是单例,意味着他们在请求之间被共享,因而不应该把任何事务相关的状态保存为实例变量。 


cfg.getEventListeners().setLoadEventListeners(listenerStack); 

hibernate: 

...
<event type="load"> 
<listener class="mylis.."/> 
</event> 
</session-factory> 

JPA: 
... 
<property name="hiernate.ejb.event.load" value="mylis...,..."/> 
</properties> 
</persistence-unit> 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值