Интеграция льда / туза:dataTable с JPA и бобами в области запроса
Мне интересно, как правильно обращаться с таблицами данных, которые принимают данные в мире Hibernate/JPA. Насколько я могу судить, один из следующих трех вариантов приводит к тому, что весь карточный домик разваливается, но я не знаю, какой из них неправильный.
- Полуавтоматическая обработка транзакций и EntityManager через пользовательский JSF PhaseListener, который начинает и фиксирует транзакции вокруг каждого запроса
- Помещение компонентов редактирования в таблицу данных
- Использование управляемых bean-компонентов в области запроса, которые извлекают свои данные из EntityManager в области запроса (с некоторой помощью PrettyFaces для установки идентификаторов в bean-объектах beoped по запросу из их URL)
- Резервное копирование dataTable с бином в области запроса вместо бина в области представления или сеанса.
Я вижу демонстрацию dataTable ICEfaces с использованием JPA, но они оба управляют транзакциями вручную и по умолчанию не отображают компоненты редактирования. Вы нажимаете на строку, в результате чего объект назначается для редактирования, а затем, когда вы нажимаете "сохранить", он вручную повторно подключает объект к новому EntityManager, прежде чем вручную инициировать сохранение. Я вижу функцию щелчка для редактирования, которая дает нам способ гарантировать, что нужный объект будет присоединен к текущему сеансу, и я не знаю, как можно жить без чего-то подобного.
У меня сложилось впечатление о новом ICEfaces 3.0 ace:dataTable (ранее PrimeFaces 2.0 dataTable), что он предназначен для использования в bean-объекте с областью видимости или сессией, но я не понимаю, как можно обойти StaleObjectState и / или LazyInitializationExceptions, если у объекта есть объекты модели, выходящие из DAO в запросе A и EntityManager A, а затем изменяемые или перемещаемые по запросу B с EntityManager B.
Я полагаю, что это может работать под Java EE через какое-то глубокое фу, но я не могу позволить себе роскошь модернизировать нас с Tomcat 6 до чего-то более изворотливого (хотя это и является моей целью в долгосрочной перспективе). Мы также не собираемся начинать использовать Spring или Seam или другие интересные вещи. ICEfaces достаточно странные для нас, наверное, слишком странные, если честно.
Итак, подведем итог, что из этого является неправильным выбором? Менеджер сущностей в области запроса, таблица данных в области запроса или использование компонентов редактирования внутри таблицы данных? Или здесь действительно что-то не так?
1 ответ
Если вы спросите меня, главная ошибка, кажется, заключается в том, чтобы придерживаться почти голого Tomcat, когда ваши требования, кажется, кричат о чем-то более причудливом. Обычно мантра заключается в том, что вы используете Tomcat, когда вам не нужны "все эти другие вещи", поэтому, когда вам это нужно, зачем продолжать использовать голый Tomcat?
Тем не менее, шаблон на самом деле не так уж сложно.
- Имейте вид, ограниченный бобом поддержки
- Получить исходные данные в
@PostConstruct
- (когда нет таких параметров, как идентификаторы) илиPreRenderViewEvent
метод в сочетании с параметрами просмотра - Используйте отдельный класс Service, который использует диспетчер сущностей для получения и сохранения данных.
- Сделайте менеджера сущностей "транзакцией в объеме"
- Без EJB/CDI/Spring:
- Получите новый менеджер сущностей из фабрики менеджеров сущностей для каждой операции.
- Запустите (локальную ресурсную) транзакцию, выполните операцию, зафиксируйте транзакцию, закройте диспетчер сущностей.
- Без EJB/CDI/Spring:
- Верните список сущностей прямо из вашего компонента поддержки, свяжите поля ввода режима редактирования таблицы с соответствующими свойствами сущности.
- При обновлении одной строки передайте соответствующий объект методу обновления вашего сервиса. Помимо накладных расходов на получение менеджера сущностей, запуск транзакции и т. Д., Это в основном только вызовы
merge()
на лицо менеджера.
Поймите, что за пределами службы вы работаете detached entities
все время. Таким образом, нет никакого риска для каких-либо исключений LazyInitializationException. Базовые компоненты должны находиться в области видимости, чтобы корректная (отделенная!) Сущность обновлялась с помощью JSF, которую ваш собственный код затем передает службе, которая объединяет ее с контекстом постоянства.
Поток для сохранения таков:
Просмотреть состояние Просмотреть область видимости ПК с транзакциямиFacelet/ компоненты Backing Bean Service Строки ------> Отдельные объекты -> Присоединенные объекты
(поток для получения данных в точности обратный)
Создание Сервиса таким способом является немного утомительным и своего рода мазохистским упражнением. Для примера приложения и только двух методов (get и update), описанных выше, это не так уж плохо, но для любого значительного приложения это быстро выйдет из-под контроля.
Если вы уже добавляете JSF и JPA в Tomcat, просто сделайте себе одолжение и используйте что-то вроде TomEE. Это чуть больше, чем Tomcat (25 МБ против 7 МБ) и содержит все то, что вы, якобы, пытаетесь избежать, но в действительности все равно нужно.
Если вы абсолютно не можете обновить установку Tomcat (например, владелец или менеджер продукта считает, что он владеет сервером вместо разработчиков), вы можете захотеть инвестировать в изучение CDI. Это может быть легко добавлено к вашей войне (всего одна дополнительная банка) и позволит вам абстрагироваться от утомительного кода. Одна вещь, которую вы также могли бы действительно использовать, это провайдер JTA. Это также может быть добавлено отдельно к вашей войне, но чем больше этого материала вы добавите, тем лучше у вас останется, просто используя TomEE (или альтернативы, такие как GlassFish, Resin, JBoss и т. Д.).
Также см. Эту статью, которая охватывает различные части ваших требований: Связь в JSF 2.0