Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Hibernate session inside a Hibernate Interceptor?

How to get Hibernate session inside a Hibernate Interceptor?

I'm trying to use Hibernate to enforce data access by organization id transparently. I have set a global Filter to filter all queries by organization id. Now, I need to use an Entity interceptor to set Organizational Id on all Entities before Save/Update.

The organization id comes from HttpSession

I've set Organizational Id as a Filter property in Hibernate session which i want to retrieve inside my interceptor and use for all Inserts and Updates as well. The problem is i dont seem to have access to Session inside the Interceptor. Any workarounds for this?

like image 470
Sathish Avatar asked Jan 08 '09 11:01

Sathish


People also ask

How can we get a Session object in hibernate?

Hibernate SessionFactory provides three methods through which we can get Session object - getCurrentSession() , openSession() and openStatelessSession() .

What is Hibernate Session and how do you get it?

The Session interface is the main tool used to communicate with Hibernate. It provides an API enabling us to create, read, update, and delete persistent objects. The session has a simple lifecycle.

Can Hibernate Session be shared between threads?

Hibernate sessions are not thread-safe. Session Factory interface: This is a factory that delivers the session objects to hibernate applications. Generally, there will be a single SessionFactory for the whole application and it will be shared among the application threads.

What is $$ hibernate interceptor?

The Hibernate Interceptor is an interface that allows us to react to certain events within Hibernate. These interceptors are registered as callbacks and provide communication links between Hibernate's session and application.


1 Answers

You can, but I would use a simple POJO just to keep things cleanly separated. Keep in mind that the value stored in the singleton will only be accessible by the same thread that handled the servlet request, so if you're doing any asynch, you will need to account for that. Here's a super basic impl:

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

Since the Organizational Id is resident in the session, you could set the value of the ThreadLocal in an early servlet filter like this (not much error checking):

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 !!
      }
   }
}

This assumes that the orgId is in the session when the filter is called, but if not, you get the idea....

Then in your interceptor (or pretty much anywhere) you can get the thread's current orgId with:

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

A potential snafu here is that all these components (filter, OrgId and interceptor) need to be loaded by the same class loader to ensure that the OrgId class is effectively a singleton, otherwise, with multiple instances of the ThreadLocal hanging around it won't work consistently, or at all. Needless to say, all this needs to be happening in the same VM.

I am not sure if this is the cleanest way to solve this problem, but it does get you your orgId where you need it.

like image 82
Nicholas Avatar answered Oct 06 '22 01:10

Nicholas