Исключение при ленивой загрузке коллекции из сущности - PullRequest
1 голос
/ 26 июля 2011

Я боюсь, что упускаю очень простой момент, но я застрял на данный момент, надеюсь, кто-то может направить мои глаза в упор на правильное ... Я пытаюсь пройти процедуру настройки приложения,шаг для прояснения (надеюсь, что людям не надоест, пока они не достигнут конца публикации):

У меня есть компонент CDI с областью действия, служащий обработчиком для представления JSF 2.0.Он содержит менеджер сущностей, список объектов и специальный отдельный объект:

@Named
@SessionScoped
public class EventHandler implements Serializable {

  @PersistenceContext
  private EntityManager em;

  private List<MyEvent> events;

  private MyEvent currentEvent;
  ...

Когда представление запрашивает список для отображения таблицы, оно заполняет список путем запроса базы данных:

Query query = em.createQuery("select e from MyEvent e");
events = (ArrayList<MyEvent>) query.getResultList();

Представление показывает это в таблице данных и предоставляет ссылку на метод действия в обработчике:

<h:dataTable value="#{eventHandler.events}" var="_var">
  ...
    <h:commandLink action="#{eventHandler.linkAction(_var)}"> ... </h:commandLink>

Метод действия сохраняет ссылку:

public void setCurrentEvent(MyEvent currentEvent) {
  this.currentEvent = currentEvent;
  ...

Ву сущности, использованной в коллекции и ссылках выше, есть отношение, которое по умолчанию загружается лениво:

@ManyToMany(mappedBy="supportedServices")
public Set<MyEntity> getSupportingEntities() {
  ...

Теперь, когда вы находитесь в подробном представлении и пытаетесь получить доступ к этому отношению, выполнив:

#{eventHandler.currentEvent.supportingEntities...}

Я получаю исключение org.hibernate.LazyInitializationException, сообщающее, что сеанс закрыт.

Не должен ли обработчик загружать запрошенные отношения на более позднем этапе во втором представлении, когдаобработчик имеет сессионную область и загружает ссылки с помощью запроса?

1 Ответ

1 голос
/ 26 июля 2011

Хм, я думаю, это потому, что persistenceContext, событие, если оно является членом бина области сеанса, не является областью сеанса.
Когда представление вызывается в первый раз, создается контекст постоянства, объекты (события) загружаются, и таблица данных заполняется. Затем контекст постоянства сбрасывается, закрывается и ответ отправляется клиенту. Все это происходит в одном запросе http.

Но когда вы затем вызываете подробное представление, выдается другой http-запрос, и создается другой контекст постоянства, и ваша ссылка на "currentEvent" больше не привязывается к последнему контексту постоянства. Следовательно, LazyInitializationError (сущность должна управляться для отложенной загрузки).

Решения могут быть:

  • Использовать расширенный контекст постоянства ( объяснено здесь ).
  • Стремитесь получить отношение:

    @ManyToMany(mappedBy="supportedServices", fetch=FetchType.EAGER)

  • Объединить отдельный экземпляр currentEvent перед использованием его в подробном представлении:

    entityManager.merge(currentEvent);

...