EntityManager ThreadLocal шаблон с JPA в JSE
Я разрабатываю простой проект «Книжный магазин», используя Struts 1.3 + JPA (с Hibernate в качестве поставщика сохраняемости). Я не могу переключиться на Spring или любую другую более сложную среду разработки (например, Jboss) и не могу использовать какую-либо специфичную для Hibernate технику (например,Session
класс).
Учитывая тот факт, что я нахожусь в среде JSE, мне нужно явно управлять всем жизненным циклом EntityManager.
Book
Сущность определяется следующим образом:
@Entity
public class Book {
@Id private String isbn;
private String title;
private Date publishDate;
// Getters and Setters
}
Я определил триAction
классы, которые отвечают соответственно за извлечение всех экземпляров книги, извлечение одного экземпляра книги по его ISBN и объединение отдельной книги в БД.
Чтобы увеличить разделение проблем между кодом бизнес-логики и кодом доступа к данным, я ввел простуюBookDAO
объект, который отвечает за выполнение операций CRUD. В идеале все вызовы, связанные с доступом к данным, должны быть делегированы постоянному уровню. Например,ListBookAction
определяется следующим образом:
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");
}
}
Объект BookDAO должен иметь доступ кEntityManager
экземпляр для того, чтобы сделать любую операцию. Учитывая этоEntityManger
не потокобезопасен, я ввел вспомогательный класс с именемBookUnitSession
который инкапсулирует EntityManager в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;
}
}
Кажется, все работает, но у меня все еще есть некоторые проблемы. А именно:
Это решение лучше всего сделать? Какова лучшая практика в этом случае?Мне все еще нужно явно закрыть как EntityManager, так и EntityManagerFactory. Как я могу это сделать?Спасибо