Estoy trabajando en una aplicación web basada en Wicket en Java EE.¿Cómo mantengo las entidades (o sus asociaciones) unidas al contexto de persistencia actual en varias solicitudes (usando Wicket y JPA)?
Estoy tratando de encontrar la forma de garantizar que las entidades utilizadas como objetos de modelo siempre se adjunten al EntityManager actual antes de que Wicket intente representar 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 baja densidad (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 utilizando un modelo que combina la entidad con el contexto de persistencia cuando sea necesario. He aquí 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;
}
/* ... */
}
Nuestra EntityManager es inyectado por GlassFish y se extiende por una petición de servlet conjunto, por lo que cuando una entidad está unida al contexto de persistencia, permanecerá conectado hasta que la página ha sido prestado.
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.
Se describe una solución similar here (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?
Es posible que desee ver el código de Databinder. Es una capa delgada entre Wicket e Hibernate, que utiliza un modelo de carga descargable para acceder a los objetos de hibernación a través de ID o SQL (o Criteria, etc.). Sin embargo, también permite mantener una referencia a objetos no permanentes a través de varias solicitudes. Al persistir el objeto, deja caer la referencia y vuelve a la versión cargable/desmontable, etc. – jbrookover