如何在Hibernate拦截器中获取Hibernate会话?

问题描述:

如何在Hibernate Interceptor中获取Hibernate会话?如何在Hibernate拦截器中获取Hibernate会话?

我试图使用Hibernate透明地强制组织ID访问数据。 我已经设置了一个全局过滤器来按组织ID过滤所有查询。 现在,我需要使用实体拦截器在保存/更新之前在所有实体上设置组织标识。

组织ID来自HttpSession的

我设置机构ID为Hibernate会话的滤镜属性,我想找回我的拦截器内,并用于所有插入和更新以及。 问题是我似乎无法访问拦截器内的会话。任何解决方法?

你可以,但我会用一个简单的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实例挂在它周围不会一直工作,或根本不工作。不用说,所有这些都需要在同一个虚拟机中进行。

我不确定这是否是最简洁的方法来解决这个问题,但它确实让您的组织在您需要它的地方。

如果你需要的只是组织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

当您创建拦截器,如果你能为它提供给SessionFactory的引用,你可以使用SessionFactory#getCurrentSession

拦截器可以制成了BeanFactoryAware和SessionFactory的可以使用bean工厂从当前会话能够获得获得。

因为它似乎是一个不好的设计,因为循环依赖,使拦截器的Spring容器的,我用的ThreadLocal尼古拉斯的建议