2014-04-10 103 views
1

我想用spring處理數據庫事件。 spring有事件處理機制,並在春季定義了一些自定義事件處理程序。例如,如果員工在系統中失去活性,那麼需要某些活動集才能執行,因此有什麼方法可以激發彈簧自定義事件列表器。我在冬眠時使用spring。 我懷疑是否可能有一種方法在hibernate中實現這一點,但我想處理它的春天。在此先感謝彈簧處理數據庫事件

回答

1

如果我正確理解您的問題,您需要知道攔截hibernate實體更改事件並觸發可由Spring處理的事件的方法。你總是可以在hibernate中攔截事件,即使用Interceptor檢查和/或改變hibernate實體元素的屬性值。例如,員工實體具有狀態(比如字符串)字段,您可以檢測更改(例如,從活動更改爲不活動)並將其更改爲此字段,然後執行一些操作,然後才能將更改持久保存到數據庫。此實體中存在的任何集合的更改也可以被攔截。爲簡潔起見,我只接受現場更換。

定義監聽器接口FieldChangeListener現場變化跟蹤:

public interface FieldChangeListener<T>{ 
     /** 
     * Defining generically so that it can be implemented by any entity on which field change needs to be observed.  
     * @param propertyName - the property name on the entity  
     * @param entity - the entity object  
     * @param previousState - the old value  
     * @param currentState - the new value  
     * */ 
      void onChange(Object[] previousState, Object[] currentState, String[] propertyName, Type[] types, Object entity);  
    } 

爲了使用所述攔截器,我們需要創建一個擴展EmptyInterceptor類:

public class FieldChangeInterceptor extends EmptyInterceptor { 
     private Map<Class, FieldChangeListener<?>> listeners;  

     public void setListeners(Map<Class, FieldChangeListener<?>> listeners) { 
      this.listeners = listeners; 
     } 

     @Override 
     public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) {  
      FieldChangeListener<?> listener = listeners.get(entity.getClass()); 
      boolean report = false; 
      // Only check for changes if an entity-specific listener was registered. 
      if (listener != null) { 
       listener.onChange(previousState, currentState, propertyNames, types, entity); 
       report = true; 
      } 
      return report; 
     } 
    } 

定義攔截器和您在上下文xml中的聽衆:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
     ... 
    </bean> 
    <bean id="fieldInterceptor" class="package.FieldChangeInterceptor"> 
     <property name="listeners"> 
      <util:map id="listeners" map-class="java.util.HashMap"> 
       <entry> 
        <key><value>package.Employee</value></key><ref bean="employeeListener"/> 
       </entry>     
      </util:map> 
     </property> 
    </bean> 
    <bean id="employeeListener" class="package.listener.EmployeeListener"/> 

EmployeeListener類是:

public class EmployeeListener implements FieldChangeListener<Employee>, ApplicationEventPublisherAware{   

     private ApplicationEventPublisher publisher; 
     public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { 
      this.publisher = publisher; 
     } 

     @Override 
     public void onChange(Object[] previousState, Object[] currentState, String[] propertyName, Type[] types, Object obj) { 
      log.info("Enter onChange()..."); 
      Employee employee = (Employee)obj; 
      boolean isChange = false; 
      for (int i = 0; i < currentState.length; i++) { 
       if (currentState[i] == null) { 
        if (previousState[i] != null){ 
         isChange = true; 
        }else{ 
         isChange = false; 
        } 
       } else if (!currentState[i].equals(previousState[i])) { 
        isChange = true; 
       } 
       if (isChange) { 
         //check for status property of Employee 
         if(propertyName[i].equals("status")){ 
         //Do your activity here - maybe you want to publish application event using eventService.  
         //Define event. 
          publisher.publishEvent(event); 
         } 
         report = false; 
        }   
      }  
      log.info("Exit onChange()..."); 
    } 

要發佈定製了ApplicationEvent,呼籲一個ApplicationEventPublisher的publishEvent()方法。有關活動發佈的更多詳情,請查看 第5.14.2節標準和自定義事件here