2011-04-26 21 views
5

Dado el escenario siguiente:relación JPA no conseguir actualizado cuando se eliminan los niños

@Entity 
public class A { 
    @OneToMany(mappedBy = "a", cascade = CascadeType.ALL) 
    private List<B> bList; 
} 

@Entity 
public class B { 
    @ManyToOne() 
    @JoinColumn(name = "a_id", referencedColumnName = "id") 
    private A a; 

    @ManyToOne() 
    @JoinColumn(name = "c_id", referencedColumnName = "id") 
    private C c; 
} 

@Entity 
public class C { 
    @OneToMany(mappedBy="c", cascade=CascadeType.ALL, orphanRemoval=true) 
    @CascadeOnDelete // eclipselink specific optimization annotation 
    private List<B> bList; 
} 

En otras palabras: tanto el objeto A y el objeto C contiene un número de objetos B.

Cuando elimino un objeto C (técnicamente, estoy actualizando un objeto que contiene varios objetos C y utilizando orphanremoval), deseo eliminar todos los objetos B a los que se hace referencia, que funcionan como se esperaba con las anotaciones actuales. Sin embargo, el administrador de la entidad no parece entender que el objeto A que yace en su caché ahora ha perdido algunos hijos. Si tuviera una instancia de A, tendría que actualizar su bList manualmente, o hacer una nueva consulta para actualizarla, pero incluso los objetos A recién recuperados todavía están desactualizados. Para reiterar:

  • C se eliminan los objetos.
  • La eliminación se realiza en cascada en objetos B con orphanRemoval.
  • ListaB en una caché de objetos del gestor de entidades es no actualizan.
  • Purga manual La memoria caché de Entity Managers hace que recupere objetos actualizados correctamente.

¿Cómo se puede solucionar? Esperaría que los administradores de entidades actualicen automáticamente su contexto de persistencia o que hagan una anotación en cascada disponible en @JoinColumn, pero ninguno parece ser el caso aquí.

EDITAR: Parece que el problema radica en que la lista b del objeto C no se actualiza cuando se actualiza la lista b del objeto A (y por lo tanto no puede realizar cambios en cascada). No tengo ni idea de por qué, sin embargo ... Todavía tengo en cuenta que estoy hablando del contexto de persistencia y de los objetos no instanciados.

Respuesta

6

APP no hace relación maintenence para usted, la aplicación debe mantenerlas. Eso significa que cuando eliminas una entidad, la aplicación es responsable de limpiar cualquier referencia a esa entidad. Es obvio cuando se trata de una relación de clave externa, ya que las restricciones de la base de datos generalmente causarán una excepción si no se hace. Sin embargo, en el caso de referencias pasadas donde la relación no tiene una restricción de base de datos estricta, los usuarios generalmente creen erróneamente que JPA lo manejará, dejando el caché dañado.

La manera de manejarlo es eliminar cualquier referencia a las entidades C y B. En su modelo de objeto, eso significa fijar la lista A de B para eliminar Bs. He visto esto manejado a través de entidades eliminar eventos o en el código de la aplicación. Como en este caso, A no tiene una clave externa, también puede actualizar las entidades A afectadas de la base de datos después de que se haya producido la eliminación (es decir, después de una descarga o confirmación).

+0

Hmm, siempre asumí que JPA manejó detrás de escena porque la situación en la base de datos es idéntica independientemente de si elimino/agrego referencias o no en el lado no propietario de la relación. Gracias. –

Cuestiones relacionadas