Inicialización de colecciones y proxies

Hibernate lanzará una LazyInitializationException si se accede a una colección o proxy sin alcanzar afuera del ámbito de la Session por ejemplo cuando la entidad que posee la colección o que tiene la referencia al proxy esté en el estado separado.

A veces es indispensable inicializar un proxy o una colección antes de cerrar la Session. Puede forzar la inicialización llamando a cat.getSex() o cat.getKittens().size() por ejemplo. Sin embargo esto puede ser confuso para los lectores del código y no es conveniente para el código genérico.

Los métodos estáticos Hibernate.initialize() y Hibernate.isInitialized() ofrecen a la aplicación una manera conveniente de laborar con colecciones o proxies inicializados perezosamente. Hibernate.initialize(cat) forzará la inicialización de un proxy cat en tanto su Session esté todavía libre. Hibernate.initialize( cat.getKittens() ) tiene un resultado parecida para la colección de gatitos.

Otra opción es mantener la Session libre hasta que todas las colecciones y proxies necesarios hayan sido cargados. En determinadas arquitecturas de aplicación particularmente en aquellas donde el código que accede a los datos usando Hibernate y el código que los emplea están en capas de aplicación distintos o procesos físicos distintos puede ser un asunto asegurar que la Session esté libre cuando se inicializa una colección. Tienen lugar dos maneras básicas para abordar este asunto

En una aplicación basada en la web se puede utilizar un filtro de servlets para cerrar la Session sólamente al final de una petición del usuario una vez que la entrega de la vista esté completa (el patrón sesión libre en vista (open session in view)). Por supuesto estos sitios necesitan una fuerte demanda de corrección del empleo de excepciones de la infraestructura de su aplicación. Es de una vital relevancia que la Session esté cerrada y la transacción terminada antes de regresar al usuario inclusive cuando ocurra una excepción mientras le entrega de la vista. Refiérase a la Wiki de Hibernate para ver ejemplos de este patrón Open Session in View (sesión libre en vista).
En una aplicación con una capa de negocios separada la lógica empresarial tiene que preparar todas las colecciones que la capa web va a necesitar antes de retornar. Esto implica que la capa empresarial debe cargar todos los datos y devolver a la capa web/presentación todos los datos ya inicializados que se requieran para un caso de uso en propia. Normalmente la aplicación llama a Hibernate.initialize() para cada colección que se necesitará en la capa web (esta llamada debe tener espacio antes de que se cierre la sesión) o recupera la colección tempranamente utilizando una consulta de Hibernate con una cláusula FETCH o una FetchMode.JOIN en Criteria. Normalmente esto es más fácil si adopta el patrón Comando en vez de una Fachada de Sesión.
También puede adjuntar un objeto cargado preliminarmente a una nueva Session con merge() o lock() antes de alcanzar a colecciones no inicializadas u otros proxies. Hibernate no y verdaderamente no debe realizar esto automáticamente ya que introduciría semánticas de transacción improvisadas.
A veces no desea inicializar una colección grande pero todavía requiere cierta información sobre ella como por ejemplo su dimensión o un subconjunto de los datos.

Puede utilizar un filtro de colecciones para conseguir el dimensión de una colección sin inicializarla

( (Integer) s.createFilter( collection select count(*) ).list().get(0) ).intValue()
El método createFilter() también se emplea para recuperar eficientemente subconjuntos de una colección sin necesidad de inicializar toda la colección

s.createFilter( lazyCollection ).setFirstResult(0).setMaxResults(10).list()