JSF + Hyperjaxb3 + Hibernate LazyInitializationException по запросам

У меня есть приложение JSF с компонентами тринидада и компонентами сущностей JAXB / JPA, созданными Hyperjaxb3. В пользовательском интерфейсе я использую компонент поля со списком Trinidad, который имеет объект JPA в качестве значений.

Сценарий такой:

  1. Пользователь делает выбор в поле со списком
  2. Пользователь нажимает на элемент управления, который отправляет запрос на сервер и возвращается в той же форме.
  3. Данные из формы были отправлены, и выбор в поле со списком должен быть таким, как сделал пользователь на шаге 1. Метод equals () вызывается для элементов поля со списком (объекты JPA), и возникает это исключение:

org.hibernate.LazyInitializationException: не удалось лениво инициализировать коллекцию ролей: package.AnObject.items, ни один сеанс или сеанс не был закрыт в org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException (AbstractPersistentColiberlection.java:358nate) в orgcollection.java:358nate. .AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected (AbstractPersistentCollection.java:350)

 at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:97)

 at org.hibernate.collection.PersistentBag.size(PersistentBag.java:225)

 at org.jvnet.hyperjaxb3.item.AbstractItemList.size(AbstractItemList.java:51)

 at java.util.AbstractList$Itr.hasNext(Unknown Source)

 at org.jvnet.jaxb2_commons.lang.builder.JAXBEqualsBuilder.append(JAXBEqualsBuilder.java:57)

 at org.jvnet.jaxb2_commons.lang.builder.JAXBEqualsBuilder.append(JAXBEqualsBuilder.java:29)

 at package.AnObject.equals(AnObject.java:177)

 at org.jvnet.jaxb2_commons.lang.builder.JAXBEqualsBuilder.append(JAXBEqualsBuilder.java:34)

 at package.ParentObject.equals(ParentObject.java:532)

 at package.ParentObject.equals(ParentObject.java:551)

 at java.util.ArrayList.indexOf(Unknown Source)

 at org.apache.myfaces.trinidad.component.UIXSelectMany._destructiveCompareOutOfOrderLists(UIXSelectMany.java:179)

 at org.apache.myfaces.trinidad.component.UIXSelectMany.compareValues(UIXSelectMany.java:139)

 at org.apache.myfaces.trinidad.component.UIXEditableValue.validate(UIXEditableValue.java:180)

 at org.apache.myfaces.trinidad.component.UIXEditableValue._executeValidate(UIXEditableValue.java:503)

 at org.apache.myfaces.trinidad.component.UIXEditableValue.processValidators(UIXEditableValue.java:270)

 at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1058)

 at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1058)

Я использую OpenEntityManagerInViewFilter из Spring для получения ленивых загружаемых объектов - это работает в одном запросе.

На уровне сгенерированного HyperJAXB объекта equals() метод вызывает equals(Object object, EqualsBuilder equalsBuilder) метод, где equalsBuilder.append(...) вызывается для каждого атрибута этого объекта. Когда этот атрибут является списком, он проксируется PersistenBag, и именно здесь я получаю исключение LazyInitializationException.

equals() метод - генерируется HyperJaxb:

public boolean equals(Object object) {
    if (!(object instanceof ParentObject)) {
        return false;
    }
    if (this == object) {
        return true;
    }
    final EqualsBuilder equalsBuilder = new JAXBEqualsBuilder();
    equals(object, equalsBuilder);
    return equalsBuilder.isEquals();
}

equals(Object object, EqualsBuilder equalsBuilder) сгенерировано HyperJaxb:

public void equals(Object object, EqualsBuilder equalsBuilder) {
    if (!(object instanceof ParentObject)) {
        equalsBuilder.appendSuper(false);
        return ;
    }
    if (this == object) {
        return ;
    }
    final ParentObjectthat = ((ParentObject) object);
    // PersitentBag, LazyInitializationException is thrown here
    equalsBuilder.append(this.getAnObject(), that.getAnObject());
    equalsBuilder.append(this.get..., that.get...);
    ...
}

У вас есть идеи, как решить эту проблему?

Я пытался использовать конвертер JSF и имел SelectItem со значением String (не объектом), но если я правильно помню, equals () вызывается после преобразования String в мой объект.


person padis    schedule 24.09.2010    source источник


Ответы (1)


Вы получаете это, потому что ваши объекты не отсоединены (1) и вы обращаетесь к данным (2) вне сеанса (3). Чтобы исправить это, вы должны адрес (1-3) в любой комбинации.

  1. Отделите свои объекты. Это, наверное, самый простой способ, но это не ленивая загрузка.
  2. Убедитесь, что сеанс доступен. Вы говорите, что используете шаблон OEMIV - как получается, что сеанса нет при вызове метода equals? Я считаю, что это потому, что equals вызывается не во время рендеринга представления, а на некоторых других этапах JSF. Вы можете попробовать расширить шаблон OEMIV, чтобы он охватил весь жизненный цикл JSF.
  3. Не обращайтесь к данным. Методы equals (...) и hashCode (...) рекомендуются, но не обязательны. Вы можете отключить их генерацию в HJ3, вы можете исключить определенные свойства из построения hashCode () / equals (...), вы можете использовать свои собственные стратегии equals и hashCode - множество способов добиться этого.

Лично я сначала проверю, почему сеанса нет.

person lexicore    schedule 25.09.2010
comment
пс. Не стесняйтесь присылать свои вопросы по адресу [email protected]. - person lexicore; 25.09.2010
comment
Спасибо Лекси за хиты. Наконец, мне удалось найти проблему - OpenEntityManagerInViewFilter должен быть установлен в качестве первого фильтра (не знаю почему), но все, похоже, сейчас находятся в сеансе без исключения Lazy Init - person padis; 06.01.2011