EntityManager ThreadLocal z JPA w JSE
Opracowuję prosty projekt „Book Store” przy użyciu Struts 1.3 + JPA (z Hibernate jako dostawcą trwałości). Nie mogę przełączyć się na Spring lub inne bardziej zaawansowane środowisko programistyczne (np. Jboss) i nie mogę używać żadnej techniki specyficznej dla Hibernate (np.Session
klasa).
Biorąc pod uwagę fakt, że jestem w środowisku JSE, muszę jawnie zarządzać całym cyklem życia EntityManager.
TheBook
jednostka jest zdefiniowana następująco:
@Entity
public class Book {
@Id private String isbn;
private String title;
private Date publishDate;
// Getters and Setters
}
Zdefiniowałem trzyAction
klasy, które są odpowiedzialne, odpowiednio, za pobieranie wszystkich instancji książki, pobieranie pojedynczej instancji książki przez ISBN i łączenie odłączonej książki z DB.
W celu zwiększenia separacji obaw między kodem logiki biznesowej a kodem dostępu do danych wprowadziłem prostyBookDAO
obiekt, który jest odpowiedzialny za wykonywanie operacji CRUD. W idealnym przypadku wszystkie wywołania związane z dostępem do danych powinny być delegowane do warstwy trwałości. Na przykładListBookAction
jest zdefiniowany następująco:
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");
}
}
Obiekt BookDAO musi uzyskać dostęp doEntityManager
przykład w celu wykonania jakiejkolwiek operacji. Jeśli się uwzględniEntityManger
nie jest bezpieczny dla wątków, wprowadziłem nazwę klasy pomocniczejBookUnitSession
który enkapsuluje EntityManager w ciąguThreadLocal
zmienna:
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;
}
}
Wszystko wydaje się działać, ale nadal mam pewne obawy. Mianowicie:
Czy jest to najlepsze rozwiązanie? jaka jest najlepsza praktyka w tym przypadku?Nadal muszę dokładnie zamknąć zarówno EntityManager, jak i EntityManagerFactory. Jak mogę to zrobić?Dzięki