2011-03-10 7 views
23

В Hibernate Envers все связанные коллекции объектов загружаются лениво, независимо от того, какой тип выборки задан. Поэтому при проведении аудита для объекта, имеющего коллекцию других объектов (как проверенных, конечно), коллекция сначала является SetProxy (ее можно увидеть при отладке).Hibernate Envers: Инициализация Envers Proxies

Итак, как мне инициализировать этот прокси? Использование Hibernate.initialize() не имеет эффекта (я подозреваю, что Hibernate и Envers используют разные прокси-объекты). Я знаю, что могу инициализировать набор, повторяя его элементы, но это не вариант для меня, потому что у меня есть несколько коллекций в сущности и не говоря уже о проблемах обслуживания.

Мне нужно инициализировать их с нетерпением, потому что я получаю доступ к коллекции в более поздний момент времени, когда сеанс Hibernate уже закрыт (преобразование объектов домена в dtos).

Я использую Hibernate 3.5.6.

+0

Я не могу заставить это работать! Кажется, что Envers игнорирует план извлечения! У меня есть несколько объектов, настроенных на оживленную выборку с режимом выборки SELECT (потому что я знаю, что они всегда находятся в кеше второго уровня - только для чтения и вечны).Я получаю ленивые ошибки инициализации при рендеринге JSP. БОЛЬ В ВАС-ЗНАТЬ-ЧТО. :(Grrr! – les2

ответ

13

По-видимому, это открытая проблема с Hibernate Envers. В их JIRA уже существует проблема: https://hibernate.atlassian.net/browse/HHH-3552. Не стесняйтесь проголосовать за это, возможно, это ускорит процесс, когда увидят, что есть некоторые люди, которые хотят, чтобы это было исправлено;)

Пока команда Envers не исправляет эту проблему, есть работа, которая работает для меня : Вызов size() в коллекциях инициализирует прокси-объекты.

+1

Hibernate.initialize() тоже не сработал для нас. Только #size() –

-2

С вашим дизайном что-то не так.

Если вам нужно инициализировать их внутри перехватчика (я подозреваю, что Envers работает, перехватывая вызовы спящего режима), это означает, что вам нужно знать о вашей модели домена заранее. Аудит должен быть полностью независимым от моделирования доменов.

После этого сказал, вы можете свернуть свой собственный инициализатор используя некоторый общий метод отражения для перебора коллекции, или вы можете использовать Open-Session-In-View шаблон и адаптировать его к работе с Envers (т.е. внутри ваш перехватчик).

Имейте в виду, что доступ к этим элементам, вероятно, вызовет другие запросы, что может сбить с толку, если вы проанализируете журналы.


Edit: кажется, что спящий режим имеет выборки профилей, которые могут препятствовать вам выбрать выборки план во время выполнения. См. Это SO question и docs.

+0

Я не уверен, что вы подразумеваете под «инициализацией их внутри перехватчика». В конце концов, я получаю объекты домена, как это предполагается, с помощью API Envers (выполняющего AutitQuery через AuditReader). Однако, моя проблема действительно является открытой проблемой (http://opensource.atlassian.com/projects/hibernate/browse/HHH-3552), как я узнал позже. –

+0

Получил ту же проблему. Как вы обошли ее в конце? – ndtreviv

+0

Существует некоторая работа. Вы должны называть 'size()' в коллекциях. Затем будут инициализированы объекты прокси-сервера Envers. –

4

Лучшим обходным решением, которое я нашел до сих пор для инициализации прокси-серверов Envers, является использование Dozer. Отображение проверяемой сущности, возвращаемой Envers для себя, принудительно инициализирует.

Например:

// Assuming you have an initialized EntityManager in entityManager & 
    // id contains your entity id.. 

    List<Object[]> auditList = (List<Object[]>)AuditReaderFactory. 
            get(entityManager). 
            createQuery(). 
            forRevisionsOfEntity(Foo.class, false, true). 
            add(AuditEntity.id().eq(id)). 
            getResultList(); 

    // Use a singleton in production apps instead... 
    DozerBeanMapper mapper = new DozerBeanMapper(); 

    for(Object[] audit : auditList) { 
     audit[0] = mapper.map(audit[0], Foo.class); 
    } 

    // The proxies in the Foo instances in auditList are now initialized 

Я не очень доволен этим решением, но я предпочитаю его по инициализации прокси вручную прикасаясь к коллекции. Надеюсь, что кто-то придумает лучшую альтернативу или HHH-3552 исправится!

+0

Хорошее решение, но следите за ошибками, вызванными несоблюдением правильного использования геттера и сеттера для всех свойств во всех классах всего графа объектов. Пример ошибки может быть для логических свойств, например http://stackoverflow.com/вопросы/532264 8/в-а-логическое поле-что-это-на-именования-конвенции-в-своей-геттерного-инкубаторе – user598656

Смежные вопросы