Hibernate не удалось инициализировать прокси - нет сеанса: LCDS провоцирует ленивую загрузку всех коллекций

В сервлете AMF происходит какое-то грязное дело...

Я вызываю метод DAO, который используется для получения списка DTO без дочерних элементов через удаленный объект из java в flex:

public List<NivelesPlantillasDto> getList()throws HibernateException{
        logger.info("getList()");
        List<NivelesPlantillasDto> list = new ArrayList<NivelesPlantillasDto>();
        Session session = null;
        try{
            session = SessionFactory.getInstance().openSession();
            list=(List<NivelesPlantillasDto>)session.createQuery("from NivelesPlantillasDto").list();
        }catch(HibernateException HE){
            logger.info(HE.getMessage(),HE);
            if (session!=null && session.isConnected())
                session.close();
            throw HE;
        }
        if (session.isConnected())
            session.close();
        return list;
    }

А это hbm.xml

<hibernate-mapping>
    <class name="architecture.dto.NivelesPlantillasDto" table="nivelesplantillas">
        <id name="pkNivelPlantilla" type="int">
            <column name="PKNIVELPLANTILLA" />
            <generator class="identity" />
        </id>
        <property name="plantilla" type="java.lang.String">
            <column name="PLANTILLA" />
        </property>
        <set name="habilidadesList" table="habilidades" inverse="true" lazy="true">
            <key foreign-key="FKNIVELESPLANTILLAS" not-null="true">
                <column name="FKNIVELESPLANTILLAS" sql-type="int"/>
            </key>
            <one-to-many class="architecture.dto.HabilidadesDto"/>
        </set>
        <set name="nivelesList" table="niveles" inverse="true" cascade="merge,delete-orphan" order-by="indice" lazy="true">
            <key foreign-key="FKNIVELESPLANTILLAS" not-null="true">
                <column name="FKNIVELESPLANTILLAS" sql-type="int"/>
            </key>
            <one-to-many class="architecture.dto.NivelesDto"/>
        </set>
        <property name="activo" type="boolean">
            <column name="ACTIVO" />
        </property>
    </class>
</hibernate-mapping>

Эта ошибка возникает после закрытия сеанса, потому что Hibernate пытается загрузить всех дочерних элементов этого класса, когда объект десериализуется в сервлете AMF, я могу видеть запрос каждого дочернего элемента, оставляя сеанс открытым. Таким образом, есть 2 исправления для устранения этой ошибки: одно — установить lazy="false" в обоих отношениях «один ко многим», а второе — оставить сеанс открытым до тех пор, пока AMF не завершит загрузку всех дочерних элементов, но это не то, что я хочу. Почему я вынужден загружать каждого ребенка?

Редактировать: хорошо, я только что исправил это уродливым способом... Я сделал клон полученного списка, поэтому, когда он десериализуется, он не запускает запрос Hibernate. Есть ли способ сообщить LCDS, какие коллекции загружаются лениво?


person Ziul    schedule 17.01.2013    source источник


Ответы (2)


Есть ли способ сообщить LCDS, какие коллекции загружаются лениво?

Не то, что я знаю о. Я думаю, вам следует подумать о реализации шаблона "Открыть сеанс в представлении" — ваш вариант использования подходит. для этого.

Обновить

Основываясь на «ответе», предоставленном ОП, я хотел бы указать, что может быть лучший подход к ленивой загрузке и операции size. Hibernate поддерживает очень ленивые коллекции, которые выдают только оператор select count(... для базы данных, а не загружают всю коллекцию, если все, что вам нужно, это получить ее размер. Просто добавьте эту аннотацию:

@LazyCollection(LazyCollectionOption.EXTRA)

См. http://www.frightanic.com/2010/11/21/extra-lazy-one-to-many-mapping-with-hibernate/ для получения подробной информации.

person Marcel Stör    schedule 17.01.2013
comment
Я исправляю медленное приложение, которое было полностью создано с неленивыми отношениями, есть ли способ превратить эти привязанные объекты в обычные, не требующий клонирования всего? - person Ziul; 18.01.2013
comment
@user1601662 user1601662, превратите эти привязанные объекты в обычные, что не требует клонирования всего - извините, я не понимаю. - person Marcel Stör; 18.01.2013
comment
Я имею в виду, что ленивые коллекции извлекаются с помощью прокси-объектов, есть ли способ вместо этого получить обычные объекты во время выполнения? - person Ziul; 18.01.2013
comment
Я не отказывался от шаблона OP, но у меня есть 2 недели, чтобы закончить это и несколько новых каталогов, я попробую, когда все будет работать гладко, кстати, очень ленивый вариант идеально подходит для быстрого исправления, спасибо! - person Ziul; 19.01.2013
comment
Кроме того, обратите внимание, что это решение работает только в том случае, если сеанс остается открытым для сервлета AMF, потому что он все равно будет запускать счетчик, что является меньшим злом, чем загрузка всего. - person Ziul; 19.01.2013

Хорошо, я думаю, что я получил это сейчас. Таким образом, очевидно, когда вы выполняете list.size() для лениво загруженной коллекции, спящий режим загружает все дочерние элементы, и, поскольку коллекции не равны нулю, я думаю, что сервлет AMF проверяет, является ли коллекция нулевой, а затем, если размер в какой-то момент равно 0, вызывая полную загрузку коллекции. Таким образом, быстрое исправление состояло в том, чтобы перебирать каждую ссылку в поисках ленивых коллекций и устанавливать для них значение null.

person Ziul    schedule 19.01.2013
comment
Я думаю, что для этого есть лучший подход... см. мой обновленный ответ. - person Marcel Stör; 19.01.2013