2009-01-08 111 views
6

如何在Hibernate Interceptor中獲取Hibernate會話?如何在Hibernate攔截器中獲取Hibernate會話?

我試圖使用Hibernate透明地強制組織ID訪問數據。 我已經設置了一個全局過濾器來按組織ID過濾所有查詢。 現在,我需要使用實體攔截器在保存/更新之前在所有實體上設置組織標識。

組織ID來自HttpSession的

我設置機構ID爲Hibernate會話的濾鏡屬性,我想找回我的攔截器內,並用於所有插入和更新以及。 問題是我似乎無法訪問攔截器內的會話。任何解決方法?

回答

2

你可以,但我會用一個簡單的POJO來保持事情乾淨地分開。請記住,存儲在單例中的值只能由處理servlet請求的同一個線程訪問,所以如果您正在做任何異步操作,則需要對此進行說明。這裏有一個超級基本IMPL:

public class OrgId { 
    public static ThreadLocal<Integer> orgId = new ThreadLocal<Integer>(); 
} 

由於機構ID是居住在會話中,你可以設置的ThreadLocal的價值在這樣(沒有太多錯誤檢查)早期的Servlet過濾器:

public class OrgIdFilter implements Filter { 
    public void doFilter(ServletRequest servletrequest, ServletResponse servletresponse, FilterChain filterchain) throws java.io.IOException, javax.servlet.ServletException { 
     int orgId = 0; 
     HttpServletRequest req = (HttpServletRequest) servletRequest; 
     HttpSession session = req.getSession(); 
     orgId = Integer.parseInt(session.getAttribute("OrganizationalIdAttr")); 
     try { 
     OrgId.orgId.set(orgId); 
     filterChain.doFilter(servletRequest, servletresponse); 
     } finally { 
     OrgId.orgId.set(null); // Important to clear after request !! 
     } 
    } 
} 

這假定ORGID是當過濾器被稱爲會話,但如果沒有,你的想法....

然後在您攔截器(或幾乎任何地方),你可以得到線程的當前ORGID與:

OrgId.orgId.get(); // Might be null..... 

這裏的一個潛在問題是,所有這些組件(過濾器,OrgId和攔截器)都需要由相同的類加載器加載,以確保OrgId類實際上是單例,否則,具有多個ThreadLocal實例掛在它周圍不會一直工作,或根本不工作。不用說,所有這些都需要在同一個虛擬機中進行。

我不確定這是否是最簡潔的方法來解決這個問題,但它確實讓您的組織在您需要它的地方。

2

如果你需要的只是組織ID,你可以把它放在一個靜態的ThreadLocal中,然後在攔截器中訪問它。另一方面,如果你對獲得會話感到失望,這取決於你的環境是什麼,那麼你可以將攔截器棄置並使用org.hibernate.event.FlushEntityEventListener,這似乎更符合你所需要的東西。你可以得到這樣的會話(粗糙的僞代碼):

FlushEntityEventListener.onFlushEntity(FlushEntityEvent event) 
EntityEvent entityEvent = event.getEntityEntry(); 
EntityPersister persister = entityEvent.getPersister(); 
SessionFactoryImplementor sessionFactoryImplor = persister.getFactory(); 
Session session = sessionFactoryImplor.getCurrentSession(); 

Hibernate 3 On Line Docs該事件系統可以作爲補充或攔截器的替代品使用。

+0

你的意思是說,我可以在我的Servlet有一個ThreadLocal變量/控制器,並獲得它在Hibernate攔截器? 我如何訪問ThreadLocal變量。它應該在Servlet中是公共靜態的嗎? – Sathish 2009-01-08 20:47:19

0

攔截器可以製成了BeanFactoryAware和SessionFactory的可以使用bean工廠從當前會話能夠獲得獲得。

因爲它似乎是一個不好的設計,因爲循環依賴,使攔截器的Spring容器的,我用的ThreadLocal尼古拉斯的建議