Abrir sesión en el patrón de vista

Estoy haciendo esta pregunta dados mis marcos de desarrollo elegidos de JPA (implementación de Hibernate), Spring, y .

He estado pensando un poco sobre las relaciones en mi capa de entidad, por ejemplo, tengo una entidad de orden que tiene muchas líneas de orden. He configurado mi aplicación para que cargue con entusiasmo las líneas de orden para cada pedido. ¿Crees que esta es una forma perezosa de evitar los problemas de inicialización lenta que encontraría si tuviera que establecer la estrategia de búsqueda en falso?

De la forma en que lo veo, tengo las siguientes alternativas cuando recupero entidades y sus asociaciones:

  1. Utilice el patrón Abrir sesión en vista para crear la sesión en cada solicitud y confirmar la transacción antes de devolver la respuesta.

  2. Implementar una capa DTO (Objeto de transferencia de datos) de modo que cada consulta DAO que ejecute devuelva la DTO correctamente inicializada para mis propósitos. Realmente no me gusta mucho esta opción porque, en mi experiencia, he descubierto que crea una gran cantidad de código de copia repetitivo y se vuelve complicado de mantener.

  3. No asigne ninguna asociación en JPA para que cada consulta que ejecute devuelva solo las entidades que me interesan; esto probablemente me obligue a tener DTO de todos modos y me costará mucho mantenerla y creo que frustra el objective de tener un ORM en primer lugar.

  4. Trae ansiosamente todas (o la mayoría de las asociaciones): en el ejemplo anterior, siempre busca todas las líneas de orden cuando recupero una orden.

Entonces mi pregunta es, ¿cuándo y bajo qué circunstancias usarías cuál de estas opciones? ¿Siempre te apegas a una forma de hacerlo?

Le preguntaría a un colega, pero creo que si mencionara el término “Open Session in View”, sería recibido con miradas en blanco 🙁 Lo que realmente estoy buscando aquí es algún consejo de un desarrollador experimentado o con experiencia.

¡Gracias chicos!

He resuelto con éxito todos mis problemas de inicialización perezosos con Open Session In View -pattern (es decir, la implementación de Spring). Las tecnologías que utilicé fueron exactamente las mismas que tú.

El uso de este patrón me permite mapear completamente las relaciones de la entidad y no preocuparme por buscar entidades secundarias en el dao. Principalmente. En el 90% de los casos, el patrón resuelve las necesidades de inicialización diferida en la vista. En algunos casos, tendrá que inicializar “manualmente” las relaciones. Estos casos fueron raros y siempre involucraron mapeos muy muy complejos en mi caso.

Cuando se utiliza el patrón Open Entity Manager In View, es importante definir las relaciones entre entidades y, especialmente, la propagación y la configuración transaccional. Si no están configurados correctamente, habrá errores relacionados con las sesiones cerradas cuando alguna entidad se inicialice de forma diferida en la vista y falla debido a que la sesión ya se ha cerrado.

Definitivamente iría con la opción 1. La opción 2 podría ser necesaria a veces, pero no veo absolutamente ninguna razón para usar la opción 3. La opción 4 también es un no no. Buscar con entusiasmo todo destruye el rendimiento de cualquier vista que necesite enumerar solo algunas propiedades de algunas entidades padre (pedidos en este caso).

N + 1 selecciona

Durante el desarrollo habrá N + 1 seleccionados como resultado de inicializar algunas relaciones en la vista. Pero esta no es una razón para descartar el patrón. Solo arregle estos problemas a medida que surgen y antes de entregar el código a la producción. Es tan fácil solucionar estos problemas con el patrón OEMIV como con cualquier otro patrón: agregue los métodos apropiados de dao o servicio, arregle el controlador para llamar a un método de búsqueda diferente, tal vez agregue una vista a la base de datos, etc.

Open Session in View tiene algunos problemas .

Por ejemplo, si la transacción falla, es posible que lo sepa demasiado tarde en el momento de la confirmación, una vez que casi haya terminado de renderizar su página (posiblemente la respuesta ya haya sido realizada, ¡así no podrá cambiar la página!) … Si tuviera conocimiento ese error antes, hubieras seguido un flujo diferente y terminaste renderizando una página diferente …

Otro ejemplo, la lectura de datos a pedido puede dar lugar a muchos problemas de “selección N + 1” , que matan su rendimiento.


Muchos proyectos usan la siguiente ruta:

  1. Mantener transacciones en la capa de negocios ; cargue en ese punto todo lo que se supone que necesita.
  2. La capa de presentación corre el riesgo de LazyExceptions: cada uno se considera un error de progtwigción, se captura durante las pruebas y se corrige al cargar más datos en la capa empresarial (tiene la oportunidad de hacerlo de manera eficiente, evitando problemas de “selección N + 1”).

Para evitar la creación de clases adicionales para DTO, puede cargar los datos dentro de los objetos de la entidad . Este es el punto principal del enfoque POJO (usos por capas modernas de acceso a datos e incluso tecnologías de integración como Spring).

He utilizado con éxito el patrón Open-Session-in-View en un proyecto. Sin embargo, recientemente leí en “Spring In Practice” un interesante problema potencial con lecturas no repetibles si gestiona sus transacciones en una capa inferior mientras mantiene abierta la sesión de Hibernate en la capa de visualización.

Administramos la mayoría de nuestras transacciones en la capa de servicio, pero mantuvimos la sesión de hibernación abierta en la capa de vista. Esto significaba que las lecturas diferidas en la vista daban como resultado transacciones de lectura separadas.

Administramos nuestras transacciones en nuestra capa de servicio para minimizar la duración de la transacción. Por ejemplo, algunas de nuestras llamadas de servicio dieron como resultado una transacción de base de datos y una llamada de servicio web a un servicio externo. No queríamos que nuestra transacción se abriera mientras esperábamos que respondiera una llamada de servicio web.

Como nuestro sistema nunca entró en producción, no estoy seguro de si hubo algún problema real con él, pero sospecho que existe la posibilidad de que la vista intente cargar de forma perezosa un objeto que ha sido eliminado por otra persona.

Sin embargo, hay algunos beneficios del enfoque DTO. Debes pensar de antemano qué información necesitas. En algunos casos, esto evitará generar n + 1 declaraciones de selección. También ayuda a ver dónde usar la búsqueda con ganas y / o las vistas optimizadas.

También apoyaré mi peso detrás del patrón Open-Session-in-View, habiendo estado en el mismo barco antes.

Trabajo con Stripes sin spring y he creado un filtro manual antes de que eso funcione bien. La encoding de la lógica de transacción en el backend se vuelve realmente complicada como lo mencionó. Buscar con entusiasmo todo se vuelve TERRIBLE a medida que mapea más y más objetos entre sí.

Una cosa que quiero agregar es que no te has cruzado de arms, Stripersnate y Stripernate – Stripersist es el sabor más JPA – filtros de autohidratación que te quitan gran parte del trabajo.

Con Stripersist puede decir cosas como /appContextRoot/actions/view/3 y autohidratará la entidad JPA en el ActionBean con id de 3 antes de que se ejecute el evento.

Stripersist está en el paquete stripes-stuff en sourceforge . Ahora uso esto para todos los proyectos nuevos, ya que es limpio y admite fácilmente múltiples fonts de datos si es necesario.

¿Las líneas de orden y orden componen un gran volumen de datos? ¿Participan en procesos en línea donde se requiere una respuesta en tiempo real? Si es así, podría considerar no utilizar la búsqueda ansiosa, pero sí una gran diferencia en el rendimiento. Si la cantidad de datos es pequeña, no hay problema en la búsqueda ansiosa.

Acerca del uso de DTO, podría ser una implementación viable. Si su capa de negocios es utilizada internamente por su propia aplicación (es decir, una pequeña aplicación web y su lógica de negocios), probablemente sea mejor usar sus propias entidades en su vista con la sesión abierta en el patrón de vista, ya que es más simple.

Si sus aplicaciones son utilizadas por muchas aplicaciones (es decir, una aplicación de back-end que proporciona un servicio en su empresa) sería interesante usar DTO ya que no expondría su modelo a sus clientes. Exponerlo podría significar que le resultaría más difícil refacturar su modelo, ya que podría significar la ruptura de contratos con sus clientes. Una DTO lo haría más fácil ya que tienes otra capa de abstracción. Esto puede ser un poco extraño ya que EJB3 eliminaría teóricamente la necesidad de DTOs.