最近項目須要,用到了Hibernate的攔截器和監聽器,有些小當心得,和你們分享下。
首先說說這兩個東西。
攔截器(Intercept):顧名思義,攔截操做,也就是在Hibernate作出動做以前會調用的方法。若是你有須要在Hibernate操做數據庫以前想要作的操做,就須要用到這個東西了。
監聽器(Listener):監聽,就是監視Hibernate的一舉一動,若是咱們要獲取Hibernate各類操做PO的前先後後的信息,那就要用到他了。
這裏有的朋友可能就有疑問了,從上面的描述來看,這個監聽器彷佛可以實現攔截器的功能,由於他也能獲取Hibernate操做數據庫前的情況。
其實否則,在此我只舉出兩個很典型的例子,你們就會明白他們倆是不能被互相取代的。
一、監聽器只會默默的獲取信息,不會阻斷Hibernate的工做,而用攔截器時,咱們能夠根據咱們的需求,去終止某個Hibernate的持久化動做。
二、若是我有這樣一個需求,在PO保存時,我想按個人需求改變某個屬性的值後,再保存入庫。分析下知道,這個操做要在Hibernate執行 Save以前來作,那麼看似攔截器和監聽器都能實現,但實踐一下就會知道,若是咱們用監聽器來作(好比此時用 PreInsertEventListener),當咱們在此改變某屬性值後,會發現,保存入庫的仍然是原來的值,監聽器的Pre******是不容許我 們這樣作的。此時就須要用到攔截器,實現其OnSave方法,在此進行處理。
說完了這些,就簡單說下他們的用法及配置方法。
1、
首先說監聽器,咱們以PostUpdateEventListener講解
新建一個咱們本身的監聽器類,實現PostUpdateEventListener接口便可
spring
public class MyListener extends DefaultLoadEventListener session
implements PostUpdateEventListener { app
public void onPostUpdate(PostUpdateEvent event) { ide
System.out.println(event.getEntity().getClass().getName()+":更新完畢"); post
for (int i = 0; i < event.getState().length; i++) { spa
// 更新前的值 hibernate
Object oldValue = event.getOldState()[i]; orm
// 更新後的新值 對象
Object newValue = event.getState()[i];
//更新的屬性名
String propertyName = event.getPersister().getPropertyNames()[i];
}
}
}
若是要實現其餘監聽器,只需實現其餘的監聽器接口便可,具體有哪些監聽器,你們能夠查看Hibernate包下的org.hibernate.event,裏面能看到全部的監聽器。
以後要加載監聽器,我這裏只講解用過spring注入sessionFactory,用property配置的方法,由於另外的兩種配置方法在網上很容易搜索到,這裏就不重複。
先將咱們的監聽器定義到spring中
<bean id="myListener" class="com.app.common.util.hibernateSupport.MyListener">
在sessionFactory的bean標籤中加入以下內容:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
...
<property name="eventListeners">
<map>
<entry key="post-update">
<ref bean="myListener" />
</entry>
</map>
</property>
...
</bean>
這樣咱們的監聽器就能夠工做了,當Hibernate執行update操做時,就會輸出咱們的信息了。
2、
再來講說攔截器
攔截器的實現要比監聽器簡單得多。
咱們只要新建一個本身的攔截器類,繼承自org.hibernate.EmptyInterceptor類,重寫原來的方法,以後在spring中配置便可。
簡單例子:
public class MyIntercept extends EmptyInterceptor {
@Override
public boolean onSave(Object entity, Serializable id, Object[] state,
String[] propertyNames, Type[] types) {
//entity就是當前的實體對象
//若是當前操做的TbUser,則作處理
if(entity instanceof TbUser){
TbUser user=(TbUser)entity;
user.setUserPassword("123");
if(user.getUserId()==null){
//返回true則攔截本次操做
return true;
}
}
return super.onSave(entity, id, state, propertyNames, types);
}
}
配置文件:
<bean id="myIntercept"
class="com.app.common.util.hibernateSupport.MyIntercept">
.......
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
...
<property name="entityInterceptor">
<ref bean="myIntercept"/>
</property>
...
</bean>
以上內容基於Hibernate3,2.xx相似附件附上org.hibernate.event.EventListeners的源碼文件,裏面有配置配置文件時不一樣攔截器對應的key值,在文件的最下方。