Pergunta

Eu tenho duas classes de entidade anotadas da seguinte maneira

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

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

Se eu armazenar uma instância da classe 'B', as relações são armazenadas no banco de dados eo getter na classe 'A' irá retornar o subconjunto correta de B de. No entanto, se eu fizer alterações na lista de Bs em 'A', as alterações não são armazenados no banco de dados?

A minha pergunta é, como posso fazê-lo assim que as mudanças em uma ou outra classe são "em cascata" para a outra classe?

EDIT:. Eu tentei variações diferentes de remover o mappedBy parâmetros e definindo um JoinTable (e colunas), mas eu fui incapaz de encontrar a combinação correta

Foi útil?

Solução

A resposta mais curta parece ser que você não pode e não faz sentido. Em um bidirecional um lado associação muitos-para-muitos deve ser mestre e é usado para manter as alterações para o subjacente tabela de junção. Como JPA não vai manter ambos os lados da associação, você pode acabar com uma situação de memória que não pode ser recarregado quando armazenado no banco de dados. Exemplo:

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

Se este estado poderia ser persistentes, você iria acabar com as seguintes entradas na tabela de junção:

a1_id, b_id
a2_id, b_id

Mas após o carregamento, como é que JPA saber que você pretende deixar apenas b saber sobre a2 e não a1? e que sobre a2 que não deve saber sobre b?

É por isso que você tem que manter a associação bidirecional si mesmo (e fazer o exemplo acima impossível chegar, mesmo em memória) e JPA somente serão válidas com base no estado de um dos lados.

Outras dicas

Você especificado o inverso se juntar colunas?

@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; 
   .. 
} 

Isso supondo uma junção tabela chamada A_B com colunas A_ID e B_ID.

Como a relação é bi-direccional de modo que as atualizações de aplicativos um lado da relação, o outro lado também deve ficar atualizado, e estar em sincronia. Em JPA, como em Java, em geral, é a responsabilidade do aplicativo, ou o modelo de objeto para manter relacionamentos. Se a sua aplicação contribui para um lado de uma relacionamento, então ele deve adicionar para o outro lado.

Isso pode ser resolvido através de métodos adicionar ou configurar no modelo de objeto que pega ambos os lados das relações, de modo que o código do aplicativo não precisa se preocupar com isso. Há duas maneiras de fazer isto, você pode adicionar apenas o código de manutenção relacionamento para um lado da relação, e apenas usar o passador de um lado (tal como fazendo do outro lado protegido), ou adicioná-lo para ambos os lados e garantir -lo a evitar um loop infinito.

Fonte: OneToMany # Getters_and_Setters

Você já tentou adicionar o parâmetro de mappedBy para o campo A em classe B como assim

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

Talvez haja um pequeno erro na resposta de a_m. Na minha opinião ele deve ser:

   @Entity
   class B { 
   @ManyToMany 
   @JoinTable (
       name="A_B",
       joinColumns = {@JoinColumn(name="B_ID")},
       inverseJoinColumns = {@JoinColumn(name="A_ID")}
   )
   private List a; 
   .. 
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top