I'm developing a simple "Book Store" project using Struts 1.3 + JPA (with Hibernate as persistence provider). I cannot switch to Spring or any other more sophisticated development environment (e.g., Jboss) and I cannot use any Hibernate-specific technique (e.g., Session
class).
Given the fact that I'm in a JSE Environment, I need to explicitly manage the whole EntityManager's lifecycle.
The Book
entity is defined as follows:
@Entity
public class Book {
@Id private String isbn;
private String title;
private Date publishDate;
// Getters and Setters
}
I defined three Action
classes, which are responsible, respectively, of retrieving all book instances, retrieving a single book instance by its ISBN and merging a detached book into the DB.
In order to increase separation of concerns between business-logic code and data-access code, I introduced a simple BookDAO
object, which is charge of executing CRUD operations. Ideally, all data-access related calls should be delegated to the persistence layer. For example, the ListBookAction
is defined as follows:
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");
}
}
The BookDAO object needs to access an EntityManager
instance in order to do any operation. Given that EntityManger
is not thread-safe, I introduced an helper class named BookUnitSession
which encapsulates EntityManager within a 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;
}
}
Everything seems to work, but I still have some concerns. Namely:
- Is this solution the best thing to do? which is the best practice in this case?
- I still need to explictly close both the EntityManager and the EntityManagerFactory. How can I do that?
Thanks