Por que a fusão não está em cascata em um para muitos relacionamento

Minha pergunta aqui é quase semelhante à minha outra pergunta, a exclusão explícita nos relacionamentos do JPA, mas eu pensei em simplificá-la ainda mais para garantir respostas mais detalhadas.

Imagine que eu tenha um relacionamento OneToMany entre pai e filho.

@Entity public class Parent { private String name; @OneToMany(mappedBy="owner",cascade=CascadeType.ALL, fetch=FetchType.EAGER) private List children; } @Entity public class Child { private String name; @ManyToOne private Parent owner; } 

Na minha interface do usuário, estou mostrando uma lista de pai. O usuário pode escolher um pai e ele / ela pode editar a lista de seus filhos. Para mostrar isso, usei uma variável currentParent para representar o pai atual editado. O usuário pode optar por adicionar / editar o nome das crianças.

Ao clicar em um botão, eu salvaria a nova lista de crianças usando uma chamada EJB.

 @ViewScoped public class MyBean(){ private Parent currentParent; @EJB private MyEJB myEJB; public void saveChanges(){ myEJB.save(currentParent); } } 

Minha chamada EJB é assim.

 @Stateless public class MyEJB{ @PersistenceContext(unitName = "MyPU") private EntityManager em; public void save(Parent parentNew){ Parent pOld = em.find(entityClass, p.getId()); if(pOld !=null){ pOld.setName(parentNew.getName()); pOld.setChildren(parentNew.getChildren()); em.merge(pOld); } } } 

Meu problema é que, eu sou capaz de mudar o nome do pai, mas as alterações na lista das crianças não são refletidas no database. Ele não altera nem executa qualquer SQL para excluir / atualizar / adicionar childs.

O que poderia ser a causa?

ATUALIZAR

Bem, depois de algumas tentativas e erros e de ler vários links, parece que configurar a opção orphanRemoval no meu @onetomany resolveria meu problema. O Eclipseelink exclui automaticamente as linhas órfãs durante a mesclagem.

Tanto para complexidade JPA ..

 @Entity public class Parent { private String name; @OneToMany(mappedBy="owner",cascade=CascadeType.ALL, fetch=FetchType.EAGER,orphanRemoval = true) private List children; } 

Este é um problema padrão com mesclagem. As alterações nos objects-filhos da coleção serão apanhadas.

A chamada de mesclagem pode apenas efetuar cascata sobre os objects que estão na lista, portanto, as alterações nos objects que não estão na lista são perdidas. Infelizmente, o oneToMany não possui o relacionamento: o filho de ManyToOne faz. Portanto, as entidades filho precisam ser mescladas para que as alterações sejam vistas e enviadas ao database. Entidades filhas são objects independentes e precisam ser mesclados individualmente quando são alterados. Isso, ou adicionado a um pai / tree diferente para ser mesclado.

Sua pergunta What could be the cause? . A causa é o conteúdo de valor de parentNew . Se o parentNew for uma das seguintes causas, ele não afetará / atualizará para o filho.

  1. Nenhum visto de instância de referência e visto de criança. —> Ele irá lançar exceção.
  2. Parent valor do parâmetro Parent tem uma lista nula ou vazia de Clild -> Esta será sua causa.
  3. Child não recebe o nome atualizado da interface do usuário .–> Esta será a sua causa.

Exemplo. Eu rapidamente escrevo. Está tudo bem.

Já existem dados no DB

 Parent Child ================== ======================================= 'P001', 'Parent 1' 'C002', 'Child 2', 'P001' 'C003', 'Child 3', 'P001' 'C001', 'Child 1', 'P001' 

Depois de atualizado:

 Parent Child ================== ======================================= 'P001', 'Update Parent 1' 'C002', 'Update Child 2', 'P001' 'C003', 'Update Child 3', 'P001' 'C001', 'Update Child 1', 'P001' List clidList = new ArrayList(); Parent parent = new Parent("P001", "Update Parent 1", clidList); Child c1 = new Child("C001", "Update Child 1", parent); Child c2 = new Child("C002", "Update Child 2", parent); Child c3 = new Child("C003", "Update Child 3", parent); clidList.add(c1); clidList.add(c2); clidList.add(c3); Parent existingParent = em.find(Parent.class, parent.getId()); existingParent.setName(parent.getName()); existingParent.setChildren(parent.getChildren()); em.merge(existingParent);