Pregunta

Tengo dos clases de entidades anotadas de la siguiente manera

@Entity
class A {
   @ManyToMany(mappedBy="A", cascade=CascadeType.ALL)
   private List<B> b;
 ..
}

@Entity
class B {
   @ManyToMany(cascade=CascadeType.ALL)
   private List<A> a;
 ..
}

Si almaceno una instancia de la clase 'B', las relaciones se almacenan en la base de datos y el captador en la clase 'A' devolverá el subconjunto correcto de B's. Sin embargo, si hago cambios en la lista de Bs en 'A', ¿los cambios no se almacenan en la base de datos?

Mi pregunta es, ¿cómo puedo hacerlo para que los cambios en cualquiera de las clases estén en cascada? a la otra clase?

EDITAR: he intentado diferentes variaciones para eliminar el parámetro mappedBy y definir una tabla de combinación (y columnas), pero no he podido encontrar la combinación correcta.

¿Fue útil?

Solución

La respuesta más corta parece ser que no puedes y tiene sentido. En una asociación bidireccional de muchos a muchos, un lado debe ser maestro y se utiliza para persistir los cambios en la tabla de unión subyacente. Como JPA no mantendrá ambos lados de la asociación, podría terminar con una situación de memoria que no podría recargarse una vez almacenada en la base de datos. Ejemplo:

A a1 = new A();
A a2 = new A();
B b = new B();
a1.getB().add(b);
b.getA().add(a2);

Si este estado pudiera persistir, terminaría con las siguientes entradas en la tabla de unión:

a1_id, b_id
a2_id, b_id

Pero al cargar, ¿cómo sabría JPA que solo pretendía informar a b sobre a2 y no sobre a1? ¿Y qué hay de a2 que no debería saber sobre b?

Esta es la razón por la que debe mantener la asociación bidireccional (y hacer que el ejemplo anterior sea imposible de obtener, incluso en la memoria) y JPA solo persistirá en función del estado de un lado.

Otros consejos

¿Ha especificado las columnas de unión inversa?

@Entity
class A {
   @ManyToMany(mappedBy="A", cascade=CascadeType.ALL)
   private List <B> b;
   ..
}

@Entity 
class B { 
   @ManyToMany 
   @JoinTable (
       name="A_B",
       joinColumns = {@JoinColumn(name="A_ID")},
       inverseJoinColumns = {@JoinColumn(name="B_ID")}
   )
   private List<A> a; 
   .. 
} 

Eso supone una tabla de unión llamada A_B con las columnas A_ID y B_ID.

  

Como la relación es bidireccional, así como la aplicación se actualiza   un lado de la relación, el otro lado también debe actualizarse,   y estar en sincronía. En JPA, como en Java en general es el   responsabilidad de la aplicación o del modelo de objeto para mantener   relaciones. si su aplicación se agrega a un lado de un   relación, entonces debe agregarse al otro lado.

     

Esto se puede resolver a través de agregar o establecer métodos en el modelo de objetos   que manejan ambos lados de las relaciones, por lo que el código de la aplicación   No tiene que preocuparse por eso. Hay dos maneras de hacer esto,   solo puede agregar el código de mantenimiento de relación a un lado   de la relación, y solo use el setter de un lado (tal como   haciendo que el otro lado esté protegido), o agréguelo a ambos lados y asegúrese de   evita un bucle infinito.

Fuente: OneToMany # Getters_and_Setters

¿Ha intentado agregar el parámetro mappedBy en el campo A de la clase B?

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

Tal vez hay un pequeño error en la respuesta de AM. En mi opinión, debería ser:

   @Entity
   class B { 
   @ManyToMany 
   @JoinTable (
       name="A_B",
       joinColumns = {@JoinColumn(name="B_ID")},
       inverseJoinColumns = {@JoinColumn(name="A_ID")}
   )
   private List a; 
   .. 
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top