java-ee - manager - jpa hibernate
¿Cómo mantengo las entidades(o sus asociaciones) unidas al contexto de persistencia actual a través de múltiples solicitudes(usando Wicket y JPA)? (2)
Estoy trabajando en una aplicación web basada en Wicket en Java EE.
Estoy tratando de encontrar una manera de garantizar que las entidades utilizadas como objetos de modelo siempre se adjunten al EntityManager actual antes de que Wicket intente procesar los componentes. De esta forma, cuando los componentes toman datos de su modelo, la entidad puede cargar los datos de forma perezosa según sea necesario.
Hay muchos tutoriales y algunas publicaciones aquí, que se refieren a los modelos cargables de carga (LDL) como la solución. Esto nos ha funcionado cuando no necesitamos mantener ningún estado entre las solicitudes. En estos casos, siempre que se represente la página, el LDM cargará la versión más reciente de la entidad requerida de la base de datos.
Sin embargo, hay ocasiones en que un usuario necesita editar datos en forma de estado a través de varios pasos antes de guardar los datos, por lo que el modelo necesita retener la entidad en su estado "no guardado". Un LDM eliminaría efectivamente los cambios del usuario en cada paso.
Hasta ahora, hemos estado usando un modelo que combina la entidad con el contexto de persistencia cuando sea necesario. Aquí hay una versión simplificada:
public final class DetachableMergingModel<E extends Identifiable> implements IModel<E> {
private E entity;
private boolean attached = false;
public DetachableMergingModel(E entity) {
this.entity = entity;
}
@Override
public E getObject() {
if (!attached) {
attached = true;
// Non-transactional method merges entity with persistence context
// but does not flush any data to database
entity = getRepository().merge(entity);
}
}
return entity;
}
@Override
public void setObject(E entity) {
this.entity = entity;
}
@Override
public void detach() {
// This ensures that the next call to getObject() will merge the entity with
// the persistence context
attached = false;
}
/* ... */
}
Nuestro EntityManager es inyectado por GlassFish y abarca una solicitud de servlet completa, de modo que cuando una entidad se adjunta al contexto de persistencia, permanecerá adjunta hasta que se haya procesado la página.
Este modelo anterior se ocupa de situaciones en las que la entidad ya se ha conservado y se está editando. Cada vez que un componente en la página llama a getObject () en este modelo, el modelo fusionará la entidad con el contexto de persistencia, y podemos navegar libremente por el gráfico de objeto entero de la entidad sin lanzar ninguna LazyInitializationExceptions.
Sin embargo, en una situación en la que la entidad es nueva y no se ha conservado, no podemos usar este Modelo porque la entidad aún no está lista para fusionarse. Este es a menudo el caso cuando el usuario está creando una nueva entidad, y aún necesita llenarla con valores a través del formulario. En este caso, queremos tener la misma libertad navegando en el gráfico de objeto de la entidad (ya que algunas asociaciones ya se han establecido, como el padre de la entidad), sin temor a una LazyInitializationException.
Aquí se describe una solución similar (opción # 3), pero no cubre el caso de uso de ''nueva entidad'' descrito anteriormente.
¿Alguien ha encontrado este caso de uso? ¿Cómo lo resolvió? ¿Existe una mejor manera de integrar Wicket con JPA que a través de implementaciones de IModel personalizados?
En casos como este, suelo crear un DTO manteniendo todos los datos que necesito para crear una entidad. Si necesita referenciar entidades existentes, páselos a sus formularios / paneles como modelos separados. Cuando se envíe el formulario, puede:
- realizar la validación
- crear una nueva entidad desde DTO que fue editada
- Inyecte referencias a otras entidades que haya almacenado en esos modelos separados de LDM.
- persistir la entidad.
Es un poco complicado pero realmente funciona.
Las conversaciones que abarcan varias solicitudes no están disponibles en wicket puro y probablemente nunca lo estarán: esta no es área de wicket.
Seam admite largas conversaciones y admite wicket (nunca he usado costuras; no puedo aconsejarle sobre esta).
Parece ser amable de una publicación anterior ...
Espero que ayude a otros de todos modos:
Primero: Su LDM es un poco inútil, porque la propiedad de la entidad no es transitoria. Por lo tanto, su entidad se serializa en su tienda de sesiones y ese no es el significado de un LDM. Se supone que minimiza el tamaño de serialización de cualquier modelo de datos.
Segundo: su problema no es un problema real, porque lo que necesita, es lo que ya tiene: desea preparar una entidad en varias páginas para finalmente almacenarla en su base de datos (por ejemplo, un asistente ...). Ahora que su LDM está completamente serializado en su tienda de sesiones entre las solicitudes del cliente, su entidad y sus datos editados sobreviven a múltiples solicitudes, sin necesidad de ninguna fusión. Tan pronto como tu asistente termine, simplemente persistes la entidad del agujero. Antes de que la entidad se encuentre en su estado final, no tiene sentido insistir en nada (aunque sobrevive a las solicitudes en su tienda de sesiones).
Ni siquiera necesitas el LDM para este tipo de funcionalidades.
Simplemente dé la entidad como parámetro a la página siguiente, donde el usuario puede completar sus datos.
Espero que hayas resuelto este problema ya ...