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的話請務必使用監聽器。

相關文章
相關標籤/搜索