EntityManager ThreadLocal-pattern mit JPA in JSE
Entwickle ich ein einfaches "Book Store" - Projekt mit Struts 1.3 + JPA (mit Hibernate als Persistenz-provider). Ich kann nicht wechseln, um den Frühling oder andere anspruchsvollere Entwicklungsumgebung (z.B. Jboss) und ich kann keine Hibernate-spezifische Technik (z.B. Session
Klasse).
Angesichts der Tatsache, dass ich in einer JSE Umgebung, muss ich ausdrücklich die Verwaltung des gesamten EntityManager-Lebenszyklus.
Den Book
entity wird wie folgt definiert:
@Entity
public class Book {
@Id private String isbn;
private String title;
private Date publishDate;
//Getters and Setters
}
Definierte ich drei Action
Klassen, die verantwortlich sind, beziehungsweise abrufen alle Buch-Instanzen, abrufen eines Einzel-book-Instanz, indem Sie seine ISBN, und Zusammenführen ein freistehendes Buch in die DB.
Zur Steigerung der Trennung zwischen business-Logik-code und code für den Datenzugriff, ich stellte eine einfache BookDAO
- Objekt, das laden der Ausführung von CRUD-Operationen. Im Idealfall sind alle Daten-access-bezogene Aufrufe delegiert werden sollte, um den persistence layer. Zum Beispiel, die ListBookAction
ist wie folgt definiert:
public class ListBookAction extends Action {
private BookDAO dao = new BookDAO();
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
//Retrieve all the books
List<Book> books = dao.findAll();
//Save the result set
request.setAttribute("books", books);
//Forward to the view
return mapping.findForward("booklist");
}
}
Den BookDAO-Objekt für den Zugriff auf eine EntityManager
Instanz, um eine operation. Da EntityManger
ist nicht thread-safe ist, stellte ich eine helper-Klasse namens BookUnitSession
die kapselt EntityManager innerhalb eines ThreadLocal
variable:
public class BookUnitSession {
private static EntityManagerFactory emf = Persistence.createEntityManagerFactory("BookStoreUnit");
private static final ThreadLocal<EntityManager> tl = new ThreadLocal<EntityManager>();
public static EntityManager getEntityManager() {
EntityManager em = tl.get();
if (em == null) {
em = emf.createEntityManager();
tl.set(em);
}
return em;
}
}
Alles scheint zu funktionieren, ich habe aber noch einige Bedenken. Nämlich:
- Ist diese Lösung das beste, was zu tun ist? was ist die beste Vorgehensweise in diesem Fall?
- Ich muss noch ausdrücklich vorgesehen und schließen Sie den EntityManager und die EntityManagerFactory. Wie kann ich das tun?
Dank
Du musst angemeldet sein, um einen Kommentar abzugeben.
Während der letzten paar Tage habe ich entwickelt, eine mögliche Lösung. Was ich versucht habe, zu konstruieren, mit der
BookUnitSession
Klasse war eigentlich dieEntityManagerHelper
Klasse:Diese Klasse sorgt dafür, dass jeder thread (d.h., jede Anfrage) erhalten Sie einen eigenen
EntityManager
Instanz. Folglich, jedes DAO-Objekt können Sie den korrektenEntityManager
Instanz durch aufrufenEntityManagerHelper.getEntityManager()
Entsprechend der session-per-request-pattern muss jede Anforderung öffnen und schließen Ihre eigenen
EntityManager
Instanz, die verantwortlich für die Kapselung der erforderlichen Einheit in einer Transaktion. Diese kann getan werden, durch ein drittes filter implementiert alsServletFilter
:Erlaubt dieser Ansatz auch die Ansicht (z.B. eine JSP-Seite) an die fetch-Einheit auf den Feldern, auch wenn Sie lazy initialisiert (Open Session in View pattern).
In einer JSE Umfeld der
EntityManagerFactory
muss explizit geschlossen werden, wenn der servlet-container beendet. Dies kann erfolgen, indem einServletContextListener
Objekt:Den
web.xml
deployment-descriptor:EntityManagerInterceptor
Klasse. Zu welchen Themen werden Sie sprechen?ScopedEntityManager Helfer-tool, das ich erstellt habe im Github verwendet eine ähnliche Technik. Anstelle der request-filter habe ich gewählt, ServletRequestListener für das lifecycle-management. Auch ich bin nicht mit einem threadlocal-denn Sie haben die Angewohnheit, von Speicherlecks in J2EE-Containern, wenn nicht sorgfältig programmiert. Tomcat haben einige tricks, um failsafe bestimmte menschliche Fehler.