hibernate中拦截器与事件监听器的区别

关于hibrenate中拦截器与事件监听器的介绍和使用的文章能够参看这篇文章:html

 Hibernate拦截器(Interceptor)与事件监听器(Listener)java

关于在hibernate中使用拦截器实现增删改查日志记录的文章可参看这篇文章:数据库

Hibernate4 拦截器(Interceptor) 实现实体类增删改的日志记录
session

拦截器与事件监听器的区别在于hibernate

  1. 监听器比拦截器提供更加细粒度的控制日志

    监听器能够提供如下几种级别的事件的监听:code

而拦截器只提供如下几种事件的监听:htm

2. 监听器比拦截器更加底层,拦截器是在对应的监听器中被启动的,这点能够看hibernate的代码,好比在org.hibernate.event.internal.DefaultFlushEntityEventListener中调用了对应的拦截器,代码以下:对象

protected boolean invokeInterceptor(
			SessionImplementor session,
			Object entity,
			EntityEntry entry,
			final Object[] values,
			EntityPersister persister) {
		return session.getInterceptor().onFlushDirty(
				entity,
				entry.getId(),
				values,
				entry.getLoadedState(),
				persister.getPropertyNames(),
				persister.getPropertyTypes()
		);
	}

3.在监听器中能够取到session,但在拦截器中不行,好比前面那篇用拦截器实现增删改查日志的例子中只能很无奈的调用HibernateUtil.getSessionFactory().openSession()来从新打开一个session了,但在监听器中能够经过AbstractEvent的getSession方法来获取session,以下:blog

protected boolean handleInterception(FlushEntityEvent event) {
		SessionImplementor session = event.getSession();

4.但拦截器使用起来会比监听器直观,好比一样是想监听同步数据库前实体的状态,用拦截器的onFlushDirty方法能够很直接的取到更新前的状态和更新后的值,以下:

public boolean onFlushDirty(
			Object entity, 
			Serializable id, 
			Object[] currentState, 
			Object[] previousState, 
			String[] propertyNames, 
			Type[] types) {

其中,currentState是更新后的值,previousState是更新前的值。

而若是用监听器的话,须要先经过event中获取到对应的持久化实例,再从实例中获取到对应的属性,以下是在DefaultFlushEntityEventListener类中调用拦截器的过程:

EntityEntry entry = event.getEntityEntry();
		EntityPersister persister = entry.getPersister();
		Object entity = event.getEntity();
final Object[] values = event.getPropertyValues();
		final boolean intercepted = invokeInterceptor( session, entity, entry, values, persister );
protected boolean invokeInterceptor(
			SessionImplementor session,
			Object entity,
			EntityEntry entry,
			final Object[] values,
			EntityPersister persister) {
		return session.getInterceptor().onFlushDirty(
				entity,
				entry.getId(),
				values,
				entry.getLoadedState(),
				persister.getPropertyNames(),
				persister.getPropertyTypes()
		);
	}

因此综上几点,若是不须要很是细粒度的监听hibernate中的事件的话优先使用拦截器,但若是想在监听的同时获取到sessionc对象的又不想从新打开一个session的话请务必使用监听器。

相关文章
相关标签/搜索