Hibernate Envers: инициализация прокси Envers - PullRequest
23 голосов
/ 10 марта 2011

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

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

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

Ответы [ 3 ]

14 голосов
/ 05 апреля 2012

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

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

4 голосов
/ 10 мая 2013

Лучший обходной путь, который я нашел для инициализации прокси-серверов 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 голосов
/ 21 марта 2011

Что-то не так с вашим дизайном.

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

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

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


Редактировать : Похоже, что в спящем режиме есть профили выборки, которые позволяют выбирать план выборки во время выполнения.См. Этот SO вопрос и документы .

...