hibernate的拦截器(Interceptor)

本文介绍了Hibernate的拦截器Interceptor和事件监听机制。Interceptor接口用于在特定操作时进行拦截,如对象创建、事务开始等,可用于实现操作日志记录。文章提供了DaoLogInterceptor示例,展示了如何在对象状态改变时记录操作。此外,还讲解了Hibernate的事件监听器,如PostLoadEventListener,可以精确追踪对象变化并执行相应处理。监听器相比拦截器提供更细粒度的控制,并能直接访问Session对象。

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

拦截器(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()
当完成一个事务之后,立刻调用此方法

1、使用拦截器实现操作日志
在应用系统中,对所有的数据库的操作都做记录,记录所操作内容,操作的用户和操作的时间


Java代码 收藏代码

import org.hibernate.CallbackException;
import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;

import java.io.Serializable;
import java.util.Date;


public class DaoLogInterceptor extends EmptyInterceptor {

private static final long serialVersionUID = 1L;

@Override
public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
super.onDelete(entity, id, state, propertyNames, types);
}

@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
return super.onSave(entity, id, state, propertyNames, types);
}

@Override
public void onCollectionUpdate(Object collection, Serializable key) throws CallbackException {
super.onCollectionUpdate(collection, key);
}

@Override
public void onCollectionRemove(Object collection, Serializable key) throws CallbackException {
super.onCollectionRemove(collection, key);
}

@Override
public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
return super.onLoad(entity, id, state, propertyNames, types);
}

@Override
public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) {
System.out.println("operateTm:"+entity.getClass().getName()+"--OperateTm:"+new Date()+"--操作用户:当前登录用户");
getOperateDetails(previousState, currentState, propertyNames);
return super.onFlushDirty(entity, id, currentState, previousState, propertyNames, types);
}


/**
* 操作前后的数据差异
*
* @param oldState
* @param state
* @param operateLog
* @return
*/
private void getOperateDetails(Object[] oldState, Object[] state, String[] propertyNames) {
for (int i = 0; i < propertyNames.length; i++) {
if (!equalsObject(oldState[i], state[i])) {
System.out.println("Field:"+propertyNames[i]+"NewValue:"+state[i] +"OldValue:"+oldState[i]);
}
}
}

private boolean equalsObject(Object o1, Object o2) {
if (o1 == null && o2 != null) {
return false;
}
if (o2 == null && o1 != null) {
return false;
}
if (o1 == null && o2 == null) {
return true;
}
return o1.equals(o2);
}
}






Xml代码 收藏代码

<!--hibernate配置-->

<bean id="myInterceptor" class="com.sf.sfbuy2.context.filter.DaoLogInterceptor"/>
<bean id="postUpdateListener" class="com.sf.sfbuy2.context.filter.PostUpdateListener"></bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="entityInterceptor">
<ref bean="myInterceptor" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="use_sql_comments">true</prop>
<prop key="javax.persistence.validation.mode">none</prop>
<prop key="hibernate.validator.apply_to_ddl">false</prop>
<prop key="hibernate.validator.autoregister_listeners">false</prop>

</props>
</property>
<property name="packagesToScan">
<list>
<value>com.sf.sfbuy2.db.entity</value>
</list>
</property>
</bean>

2、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代码 收藏代码

import org.hibernate.event.PostLoadEvent;
import org.hibernate.event.PostLoadEventListener;
public class LogPostLoadEventListener implements PostLoadEventListener {
private static final long serialVersionUID = 404241098418965422L;
public void onPostLoad(PostLoadEvent event) {
System.out.println("Class:" + event.getEntity().getClass().getName() + ",id:"
+ event.getId());
}
}

修改Hibernate.cfg.xml文件
Xml代码 收藏代码

<mapping resource="com/rbh/examples/Guestbook.hbm.xml" />
<listener type="post-load" class="com.rbh.examples.LogPostLoadEventListener" />
</session-factory>
</hibernate-configuration>

或者通过Configuration 对象注册这个监听器对象
Java代码 收藏代码

Configuration config = new Configuration();
config.setListener("post-load", new LogPostLoadEventListener());
config.configure();
Session session = config.buildSessionFactory().getCurrentSession();



编写、配置好监听器以后,当通过Session对象的load()、get()方法或者Query对象的list方法加载持久化对象之后,LogPostEventListener对象中的onPostLoad()方法就会被执行.



使用监听器实现记录操作日志

利用Hibernate的事件机制,不仅能够精确追踪到持久化对象的字段的修改,持久化对象关联关系的变更,还能记录更新前的数值和更新后的数值



监听器与拦截器的比较

监听器可以实现更细化粒度的拦截
通过监听器获取所拦截的持久化对象的修改后喝修改前的状态值
能直接通过Event对象获取Session对象
### 整合 Hibernate 拦截器到 Spring Boot 的方法 在 Spring Boot 中整合 Hibernate 拦截器可以用于实现自定义逻辑或审计功能。以下是具体的方法: #### 配置 `LocalSessionFactoryBean` 或 `EntityManagerFactory` 由于 Spring Boot 自动配置了 Hibernate,因此可以通过设置 `hibernate.session_factory.interceptor` 属性来指定拦截器类。 ```properties spring.jpa.properties.hibernate.session_factory.interceptor=com.example.CustomInterceptor ``` 此属性会告诉 Hibernate 使用哪个拦截器实例[^1]。 #### 创建自定义拦截器类 创建一个继承自 `org.hibernate.EmptyInterceptor` 的类,并重写所需的方法。例如: ```java import org.hibernate.EmptyInterceptor; import java.io.Serializable; public class CustomInterceptor extends EmptyInterceptor { @Override public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { // 实现保存前的逻辑 System.out.println("Entity is being saved: " + entity); return super.onSave(entity, id, state, propertyNames, types); } @Override public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { // 实现在删除之前的逻辑 System.out.println("Entity is being deleted: " + entity); super.onDelete(entity, id, state, propertyNames, types); } } ``` 上述代码展示了如何通过覆盖 `onSave` 和 `onDelete` 方法,在实体保存和删除之前执行特定操作。 #### 注册拦截器到 Spring 应用上下文中 如果需要动态注册拦截器,则可以在应用启动时将其注入到 Bean 定义中。例如: ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AppConfig { @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, DataSource dataSource) { Map<String, Object> properties = new HashMap<>(); properties.put("hibernate.session_factory.interceptor", customInterceptor()); return builder.dataSource(dataSource).packages("com.example").persistenceUnit("unitName") .properties(properties).build(); } @Bean public CustomInterceptor customInterceptor() { return new CustomInterceptor(); } } ``` 这段代码显示了如何将拦截器作为 Bean 进行管理并传递给 `entityManagerFactory` 的配置过程[^2]。 #### 测试集成效果 完成以上步骤后,运行应用程序并通过调试验证拦截器是否按预期工作。每次触发数据库交互时,相应的拦截器方法会被调用。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值