Sto sviluppando un semplice progetto "Book Store" utilizzando Struts 1.3 + JPA (con Hibernate come provider di persistenza). Non posso passare a Spring o ad altri ambienti di sviluppo più sofisticati (ad es. Jboss) e non posso utilizzare alcuna tecnica specifica di Hibernate (ad esempio, classe Session
).Filetto EntityManager Pattern locale con JPA in JSE
Dato che sono in un ambiente JSE, ho bisogno di gestire esplicitamente l'intero ciclo di vita di EntityManager.
L'entità Book
è definito come segue:
@Entity
public class Book {
@Id private String isbn;
private String title;
private Date publishDate;
// Getters and Setters
}
ho definito tre Action
classi, che sono responsabili, rispettivamente, di recuperare tutte le istanze telefonico, recuperando una singola istanza libro dalla sua ISBN e fondendo un libro indipendente nel DB.
Al fine di aumentare la separazione delle preoccupazioni tra codice di business logic e codice di accesso ai dati, ho introdotto un semplice oggetto BookDAO
, che è responsabile dell'esecuzione delle operazioni CRUD. Idealmente, tutte le chiamate relative all'accesso ai dati dovrebbero essere delegate al livello di persistenza. Ad esempio, il ListBookAction
è definito come segue:
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");
}
}
L'oggetto BookDAO deve accedere un'istanza EntityManager
per fare qualsiasi operazione. Dato che EntityManger
non è thread-safe, ho introdotto una classe di supporto di nome BookUnitSession
che incapsula EntityManager all'interno di una variabile ThreadLocal
:
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;
}
}
Tutto sembra funzionare, ma ho ancora qualche preoccupazione. Vale a dire:
- Questa soluzione è la cosa migliore da fare? qual è la migliore pratica in questo caso?
- Ho ancora bisogno di chiudere esplicitamente sia EntityManager che EntityManagerFactory. Come lo posso fare?
Grazie
Bel lavoro, ma probabilmente si intende JEE invece di JSE. –
Grazie. Attualmente sto utilizzando Tomcat 7 e Struts 1.3 senza alcun server delle applicazioni. Pertanto, direi che non sono completamente conforme a JEE. Dal punto di vista della persistenza, è come essere in un ambiente JSE. Ecco perché ho dichiarato JSE nel titolo. –
Ciao, questa soluzione ha funzionato alla fine? Ho sentito parlare di alcuni problemi con l'utilizzo di ThreadLocal. –