2009-01-08 19 views
6

Wie bekomme ich die Hibernate-Sitzung in einen Hibernate Interceptor?Wie bekomme ich die Hibernate-Sitzung in einen Hibernate Interceptor?

Ich versuche Hibernate zu verwenden, um den Datenzugriff durch die Organisations-ID transparent zu erzwingen. Ich habe einen globalen Filter festgelegt, um alle Abfragen nach Organisations-ID zu filtern. Nun muss ich einen Entity-Interceptor verwenden, um die Organisations-ID auf allen Entitäten vor dem Speichern/Aktualisieren zu setzen.

Die Organisation id kommt von Http

Ich habe in Hibernate Session Organisations-ID als Filter-Eigenschaft, die ich in meinem Interceptor abrufen möchten und verwenden für alle Einsätze und Updates sowie. Das Problem ist, ich habe keinen Zugriff auf die Sitzung im Interceptor. Irgendwelche Problemumgehungen dafür?

Antwort

2

Sie können, aber ich würde ein einfaches POJO verwenden, nur um Dinge sauber getrennt zu halten. Beachten Sie, dass auf den im Singleton gespeicherten Wert nur derselbe Thread zugreifen kann, der die Servlet-Anfrage bearbeitet hat. Wenn Sie also Asynch ausführen, müssen Sie dies berücksichtigen. Hier ist ein super Grund impl:

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

Da die Organisations-ID mit Wohnsitz in der Sitzung ist, können Sie den Wert des Thread in einem frühen Servlet-Filter einstellen könnte wie folgt (nicht viel Fehlerüberprüfung):

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

Dies setzt voraus, dass der OrgID in der Sitzung ist, wenn die Filter genannt wird, aber wenn nicht, bekommen Sie die Idee ....

Dann in Ihrem Interceptor (oder so ziemlich überall) Sie den aktuelle OrgID Thread bekommen mit:

Ein potentielles Problem hier ist, dass alle diese Komponenten (Filter, OrgId und Interceptor) vom selben Klassenlader geladen werden müssen, um sicherzustellen, dass die OrgId Klasse effektiv ein Singleton ist, ansonsten mit mehreren Instanzen des ThreadLocal Um es herumzuhängen wird nicht konsequent oder überhaupt funktionieren. Unnötig zu sagen, dass all dies in derselben VM stattfinden muss.

Ich bin mir nicht sicher, ob dies der sauberste Weg ist, um dieses Problem zu lösen, aber es bringt Sie Ihre OrgId, wo Sie es brauchen.

2

Wenn Sie nur die Organisations-ID benötigen, können Sie sie in ein statisches ThreadLocal einfügen und dann im Interceptor darauf zugreifen.

Auf der anderen Seite, wenn Sie tot auf die Sitzung zu bekommen, und das hängt davon ab, was Ihre Umgebung ist, könnten Sie den Abfangjäger Graben und verwenden Sie eine org.hibernate.event.FlushEntityEventListener, die mehr nach dem zu sein scheint, was Sie sowieso brauchen. Sie können die Sitzung wie folgt aus (grobe Pseudo-Code) erhalten:

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

Vom Hibernate 3 On Line Docs: Das Ereignissystem kann zusätzlich oder als Ersatz für die Abfangjäger eingesetzt werden.

+0

Wollen Sie damit sagen, dass ich eine Thread Variable in meinem Servlet haben kann/Controller und es in den Hibernate Interceptor bekommen? Wie greife ich auf die Variable ThreadLocal zu? Sollte es im Servlet öffentlich sein? – Sathish

+0

Bereitstellung der zweiten Antwort. – Nicholas

+1

Btw EventSource, auf die von FlushEntityEvent zugegriffen werden kann, ist eine Sub-Schnittstelle von Session, so dass Sie nicht durch EntityPersister usw. laufen müssen –

0

kann Interceptor BeanFactoryAware und Session können die BeanFactory erhalten werden hergestellt unter Verwendung von dem aktuellen Sitzung sein erhalten.

Da es wie ein schlechtes Design schien wegen der zirkuläre Abhängigkeit und macht den Interceptor bewusst Federbehälter, verwendet i Thread wie von Nicholas vorgeschlagen

Verwandte Themen