Интеграция льда / туза: dataTable с JPA и бобами в области запроса - PullRequest
3 голосов
/ 15 февраля 2012

Мне интересно, как правильно обращаться с таблицами данных, которые принимают данные в мире Hibernate / JPA.Насколько я могу судить, один из следующих трех вариантов приводит к распаду целого карточного дома, но я не знаю, какая из них неправильная.

  • Полуавтоматическая транзакция и EntityManagerобработка через пользовательский JSF PhaseListener, который запускает и фиксирует транзакции вокруг каждого запроса
  • Помещение компонентов редактирования в dataTable
  • Использование управляемых bean-объектов в области запроса, которые получают свои данные из EntityManager в области запроса (снекоторая помощь от PrettyFaces для установки идентификаторов для bean-объектов области запроса из их URL-адресов)
  • Резервное копирование dataTable с bean-областью области запроса вместо bean-объекта области просмотра или сеанса.

Я вижу демонстрационную таблицу ICEfaces dataTable с использованием 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 Ответ

4 голосов
/ 19 февраля 2012

Если вы спросите меня, главная ошибка, кажется, заключается в том, чтобы придерживаться почти голого Tomcat, когда ваши требования, кажется, кричат ​​о чем-то более причудливом.Обычно мантра заключается в том, что вы используете Tomcat, когда вам не нужны «все эти другие вещи», поэтому, когда вам это нужно, зачем продолжать использовать голый Tomcat?

Тем не менее, шаблон действительно не 't, что трудно.

  • Иметь базовый компонент области видимости
  • Получить исходные данные в @PostConstruct - (когда нет параметров, таких как идентификаторы) или PreRenderViewEvent в методекомбинация с параметрами представления
  • Использование отдельного класса Service, который использует диспетчер сущностей для получения и сохранения данных
  • Сделать диспетчер сущностей "областью действия"
    • Без EJB / CDI/ Spring:
      • Получать нового менеджера сущностей из фабрики менеджеров сущностей для каждой операции.
      • Запустить (локальная) ресурсная транзакция, выполнить операцию, зафиксировать транзакцию, закрыть диспетчер сущностей.
  • Возврат списка сущностей непосредственно из вашего компонента поддержки, привязка полей ввода режима редактирования таблицы к соответствующим свойствам сущности.
  • При обновлении одной строки передайте соответствующий объект методу обновления вашего сервиса.Помимо накладных расходов на получение менеджера сущностей, запуск транзакции и т. Д., Это в основном вызывает только merge() на менеджере сущностей.

Поймите, что вне службы вы работаете с detached entities allвремя.Таким образом, нет никакого риска для каких-либо исключений LazyInitializationException.Базовые компоненты должны находиться в области видимости, чтобы корректный (отделенный!) Объект обновлялся с помощью JSF, который затем передавал ваш собственный код службе, который сливал ее в контекст постоянства.

Поток для сохранениятаким образом:

<i>View state</i>               <i>View scope </i>        <i>Transaction scoped PC</i>
<b>Facelet/components</b>       <b>Backing Bean</b>       <b>Service</b>
      Strings ------> Detached entities --> Attached entities

(процесс получения данных в точности обратный)

Создание службы таким способом является немного утомительным и своего рода мазохистским упражнением.Для примера приложения и только двух методов (get и update), описанных выше, это не так уж плохо, но для любого значительного приложения это быстро выйдет из-под контроля.

Если вы уже добавляете JSF иJPA для Tomcat, просто сделайте себе одолжение и используйте что-то вроде TomEE .Это чуть больше, чем Tomcat (25 МБ против 7 МБ) и содержит все то, что вы, якобы, пытаетесь избежать, но в действительности вам все равно нужно.

В случае, если вы абсолютно не можете обновить установку Tomcat (например, продуктвладелец или менеджер считает, что ему принадлежит сервер, а не разработчики), возможно, вы захотите инвестировать в изучение CDI.Это может быть легко добавлено к вашей войне (только один дополнительный кувшин) и позволит вам абстрагироваться от утомительного кода.Одна вещь, которую вы также можете использовать, - это JTA-провайдер.Это тоже может быть добавлено отдельно к вашей войне, но чем больше этого материала вы добавите, тем лучше у вас останется, просто используя TomEE (или альтернативы, такие как GlassFish, Resin, JBoss и т. Д.).

Также см.эта статья, которая охватывает различные части ваших требований: Связь в JSF 2.0

...