JPA: get-use-close von EntityManager und lazy loading

9

IBM empfiehlt, dass die beste Methode für die Verwendung von EntityManagers get / use / close ist. Wenn EntityManager nicht geschlossen ist, besteht die Möglichkeit, dass derselbe EntityManager von mehreren Threads verwendet wird, was zu folgendem Fehler führt:

%Vor%

Wenn Sie ein Objekt laden, dessen OneToMany-Sammlung wie folgt auf fetch = LAZY abgebildet ist:

%Vor%

Die Sammlung ist immer null, da zu dem Zeitpunkt, zu dem jemand den Getter aufruft, der EntityManager geschlossen ist. Die Sammlung wird nur geladen, wenn Fetch EAGER ist, was jedoch jedes Mal zu einem SQL-Join führt, der langsam ist.

Also ist es entweder "Mehrere Threads" Fehler, oder openjpa.Multithreaded = true was eine schlechte Praxis ist oder es ist langsam wegen der SQL-Join jedes Mal, auch wenn die Sammlung nicht benötigt wird. Gibt es eine Möglichkeit, es richtig zu machen, so ist es sowohl schnell mit Lazy Fetch und nur mit Best Practices gemacht?

    
Maxim Suponya 19.10.2012, 06:15
quelle

4 Antworten

3

Ok, hier ist meine Schlussfolgerung nach zwei Tagen Forschung zu diesem Thema. Für Anwendungen, die sich nicht auf die Bereitstellung auf einem Java-EE-Server stützen können und nicht den Zugriff auf einzelne Threads garantieren können (z. B. Web-Apps auf Tomcat), ist es die beste Vorgehensweise, Entitätsmanager im Rahmen der Methode zu öffnen, zu verwenden und zu schließen des DAO-Objekts.

Dies bedeutet, dass Lazy Loading außerhalb von DAO nicht funktioniert. Um es zu umgehen, müssen in Methoden, die eine Entität nach ID suchen, alle Sammlungen abgerufen werden, indem size () für die Sammlung aufgerufen wird, um das Abrufen auszulösen, bevor der Entitätsmanager geschlossen wird. Dies führt dazu, dass die Methode find ein vollständig geladenes Objekt zurückgibt, obwohl Fetch faul ist.

Bei Methoden, die Auflistungen von Objekten zurückgeben, wie z. B. die Suche, ist es zu langsam, um alle Entitäten im Suchergebnis vollständig zu laden, sodass die Ergebnisse so zurückgegeben werden, wie sie ohne untergeordnete Elemente vorhanden sind. Immer wenn eine der Entitäten im Suchergebnis angezeigt werden muss, muss sie einzeln über diese Methode geladen werden, die vollständig geladene Objekte erhält.

    
Maxim Suponya 23.10.2012, 10:01
quelle
2

OK, ohne Java EE zu verwenden, können Sie einen einfachen Pool von EntityManagers erstellen. Ich benutze einen StackKeyedObjectPool (von Apache Commons Pool) und erstelle neue EntityManager, wenn ich sie brauche. Ich habe eine Ausleihe / Rückgabe-Schnittstelle, und der Pool erstellt bei Bedarf automatisch ein neues Objekt. Siehe Ссылка

    
Zagrev 22.10.2012 16:43
quelle
0

Eigentlich sollten Sie in der Lage sein, Websphere den Entity Manager für Sie injizieren zu lassen.

%Vor%

wo Sie auf die Daten zugreifen müssen. Der Anwendungsserver verarbeitet die Threading-Probleme für Sie, da jede Bean nur eine einzige Anfrage verarbeitet und diese Anfrage in einem einzigen Thread abläuft.

    
Zagrev 19.10.2012 15:11
quelle
0

Ich habe ein GitHub-Projekt erstellt, das eine automanaged EntityManager-Lebensdauer in einem Servlet (Tomcat) -Container bietet. Single-Threaded-HTTP-Anforderungskontext ruft dieselbe Instanz ab, und EM wird am Ende der HTTP-Anforderung automatisch geschlossen. Dies ergibt eine einfache Abstraktion für Servlet- und Jsp-Skripte ohne ausdrückliches try-catch-finally-Muster.
Ссылка

    
Whome 22.07.2014 19:58
quelle

Tags und Links