recursive practices manytoone lazyinitializationexception lazy initialize fetchtype example best java hibernate proxy lazy-loading hibernate-envers

java - practices - Hibernate Envers: Inicializando Envers Proxies



lazy hibernate xml (3)

Al parecer, este es un problema abierto con Hibernate Envers. Ya existe un problema existente en su JIRA: https://hibernate.atlassian.net/browse/HHH-3552 . Siéntase libre de votar, tal vez acelerará las cosas, cuando vean que hay personas que desean que esto se solucione;)

Hasta que el equipo de Envers resuelva este problema, hay un trabajo que me funciona: Llamar a size() en las colecciones inicializa los objetos proxy.

En Hibernate Envers, todas las colecciones relacionadas de una entidad se cargan perezosamente, independientemente de qué tipo de búsqueda se establezca. Por lo tanto, cuando se realizan consultas para una entidad que tiene una colección de otras entidades (ambas auditadas, por supuesto), la colección es un SetProxy al principio (se puede ver cuando se realiza la depuración).

Entonces, ¿cómo puedo inicializar ese proxy? El uso de Hibernate.initialize() no tiene ningún efecto (sospecho que porque Hibernate y Envers utilizan diferentes objetos proxy). Sé que puedo inicializar el conjunto iterando sobre sus elementos, pero esa no es una opción para mí porque tengo varias colecciones en una entidad y por no mencionar los problemas de mantenimiento.

Necesito inicializarlos con entusiasmo porque estoy accediendo a la colección en un momento posterior cuando la sesión de Hibernate ya está cerrada (convirtiendo los objetos del dominio en dtos).

Estoy usando Hibernate 3.5.6.


Hay algo mal con tu diseño

Si necesita inicializarlos dentro de un interceptor (sospecho que Envers funciona interceptando llamadas de hibernación), significa que debe conocer su modelo de dominio de antemano. La auditoría debe ser una preocupación completamente independiente del modelado de dominios.

Dicho esto, puede rodar su propio inicializador utilizando algún método de reflexión genérico para iterar la colección, o puede usar el patrón Open-Session-In-View y adaptarlo para que funcione con Envers (es decir, dentro de su interceptor).

Tenga en cuenta que el acceso a estos elementos probablemente desencadenará otras consultas, lo que puede resultar confuso si analiza los registros.

Edición : parece que hibernar tiene perfiles de recuperación, lo que le permite elegir un plan de recuperación en tiempo de ejecución. Ver esta pregunta y los docs .


La mejor solución que he encontrado hasta ahora para inicializar los proxies de Envers es usar Dozer . La asignación de la entidad auditada devuelta por Envers a sí misma fuerza la inicialización.

Por ejemplo:

// 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

No estoy muy contento con esta solución, pero la prefiero a la inicialización de los proxies al tocar manualmente las colecciones. ¡Espero que a alguien se le ocurra una alternativa mejor o se arregla el HHH-3552!