Я разрабатываю простой проект "Книжный магазин", используя Struts 1.3 + JPA (с Hibernate как провайдер непрерывности). Я не могу переключиться на Spring или любую другую более сложную среду разработки (например, Jboss), и я не могу использовать какой-либо метод, зависящий от Hibernate (например, Session
class).
Учитывая тот факт, что я нахожусь в среде 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. Как я могу это сделать?
Спасибо