tutorial - En Spring con jpa/hibernate, ¿cómo mantengo una sesión abierta para evitar excepciones de inicialización perezosa?
spring hibernate jpa repository example (6)
¿Está utilizando Spring''s HibernateTemplate? Se gestionará la sesión para usted, creo. Alternativamente, si está en Hibernate 3.0.1 o superior, Spring debería poder administrar la sesión por usted.
Hay una entrada de blog de SpringSource que describe cómo configurar esto. He incluido un extracto a continuación:
Desde Hibernate 3.0.1 (y en la API de persistencia de Java desde el momento en que se lanzó por primera vez), Spring pudo gestionar el recurso subyacente sin tener que pasar por ninguna de las plantillas disponibles para esas tecnologías. Esto significa que incluso si está utilizando la API de Hibernate directamente (por ejemplo, a través de SessionFactory.getCurrentSession ()), seguirá usando una sesión de Hibernate administrada por Spring. Lo mismo se aplica a un EntityManager obtenido a través de un JPA EntityManagerFactory. Esta es otra razón por la que ya no tiene que usar la Plantilla HibernateTemplate de Spring para obtener una experiencia integrada. [...]
El siguiente es el XML que usaremos para ensamblar la aplicación. Como puede ver, por supuesto, todavía estamos usando la forma Spring de configurar Hibernate (usando LocalSessionFactoryBean).
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<!– the works –>
</bean>
<bean id="accountRepo" class="com.mycompany.HibernateAccountRepository">
<constructor-arg ref="sessionFactory"/>
</bean>
Ahora, como dije antes, debido a un pequeño cambio en Hibernate 3.0.1, Spring puede administrar la sesión de Hibernate por usted, sin que tenga que pasar por la sesión de Hibernate. Lo único que faltaba era la traducción de la excepción. Para lograrlo, solo necesita anotar el repositorio con la anotación @Repository (proporcionada por Spring) y activar la traducción de excepciones mediante un postprocesador.
@Repository // from org.springframework.stereotype
public class HibernateAccountRepository implements AccountRepository {
// see above for full impl…
}
Actualmente, marco las colecciones en beans de entidad como deseosas de evitar una excepción de inicialización lenta cuando intento acceder a las propiedades de la colección después de cargar el bean con el EntityManager.
Si, en cambio, dejo la colección como carga diferida, ¿cómo mantengo una sesión abierta? Pensé en probar @Transactional, pero incluso si eso funcionara, no querría hacerlo porque no parece correcto dejar una transacción abierta en un método largo.
Ahora, no he usado Spring, pero he usado Hibernate en varios proyectos diferentes. El enfoque que adopté para el proyecto más reciente surgió del patrón de Manejo de sesión defensiva (junto con un filtro de servlet), y estamos contentos con él. Puedes encontrar más patrones de diseño here .
Como han dicho otros, debe leer sobre el patrón de "sesión abierta en vista", cuya idea básica es tener una sesión de hibernación abierta durante la duración completa del procesamiento de la solicitud http. Hay soluciones https://www.hibernate.org/43.html tanto para https://www.hibernate.org/43.html como para spring : usé resortes antes y funcionan bien.
En la pregunta mencionas que no quieres tener una transacción abierta por mucho tiempo. Para la mayoría de las personas esto no es un problema porque cada solicitud se procesa de manera relativamente rápida. Sin embargo, si en tu caso es imposible, este patrón no funcionará para ti. ¿Puede explicar por qué no desea que las transacciones se mantengan abiertas?
Cuando deja una sesión abierta que ha leído algunos datos, dejará esa transacción abierta. Las transacciones de larga duración no son un problema tan grande (aunque eso podría depender de su base de datos) lo que realmente causa problemas son los bloqueos que se mantienen durante mucho tiempo, pero estos solo pueden crearse una vez que realmente cambia los datos en la base de datos. De nuevo esto depende de tu base de datos.
Una última opción que parece haberse perdido es que puede crear su gráfico de objetos en función de su caso de uso mediante el uso de UNIR.
Esto resultará en la inicialización del objeto, es decir, no será un proxy.
Utilice este enfoque si tiene el control del cliente (es decir, no está creando un servicio abierto que publica una api) porque necesita saber qué estado se está tocando cuando se cierra la sesión porque la transacción se ha cerrado.
https://www.hibernate.org/43.html
Básicamente, tienes algunas opciones.
-Puede utilizar el patrón de "abrir sesión en vista" en el que utiliza una lógica de filtro / interceptor / AOP para abrir una sesión cuando comienza la lógica del lado del servidor y cerrarla cuando finalice.
-Podría implementar conversaciones que abarquen varios ciclos de solicitud-respuesta.
Un simple filtro de Servlet es lo más fácil.