Pergunta

Eu tenho um problema com um mapeamento @OneToMany simples entre um pai e uma entidade filho. Tudo funciona bem, só isso registros filho não são apagados quando eu removê-los da coleção.

O parent:

@Entity
public class Parent {
    @Id
    @Column(name = "ID")
    private Long id;

    @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "parent")
    private Set<Child> childs = new HashSet<Child>();

 ...
}

A criança:

@Entity
public class Child {
    @Id
    @Column(name = "ID")
    private Long id;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="PARENTID", nullable = false)
    private Parent parent;

  ...
}

Se eu agora excluir e criança dos criança definido, ele não ficar excluído do banco de dados. Eu tentei anular a referência child.parent, mas isso não quer trabalhar.

As entidades são usados ??em uma aplicação web, a exclusão acontece como parte de uma solicitação do Ajax. Eu não tenho uma lista de criança apagados quando o botão Salvar é pressionado, então não posso excluí-los implicitamente.

Foi útil?

Solução

comportamento da APP está correta (ou seja, de acordo com a especificação ): objetos não são eliminados simplesmente porque você os removeu de uma coleção OneToMany. Existem extensões específicas do fornecedor que fazem isso, mas JPA nativa não atender a isso.

Em parte, isso é porque JPA na verdade não sei se deve excluir algo removido da coleção. Em termos de modelagem de objetos, esta é a diferença entre composição e "agregação *.

Em composição , a entidade filho não tem existência sem o pai. Um exemplo clássico é entre House e quarto. Excluir a Casa e os quartos ir também.

Agregação é um tipo mais flexível de associação e é caracterizada por curso e Student. Excluir o curso eo estudante ainda existe (provavelmente em outros cursos).

Então, você precisa tanto usar extensões específicas do fornecedor para forçar este comportamento (se disponível) ou explicitamente excluir a criança e removê-lo da coleção do pai.

Eu estou ciente de:

Outras dicas

Além de cletus' resposta, JPA 2.0 , final, desde dezembro de 2010 , introduz um atributo orphanRemoval em anotações @OneToMany. Para mais detalhes veja este blogue entrada .

Note que, desde a especificação é relativamente novo, nem todos provedor de JPA 1 tem uma implementação final JPA 2. Por exemplo, o Hibernate-3.5.0-Beta 2 liberação ainda não suporta este atributo.

Você pode tentar o seguinte:

@OneToOne(orphanRemoval=true) or @OneToMany(orphanRemoval=true).

Como foi explicado, não é possível fazer o que eu quero com JPA, então eu empregada a anotação hibernate.cascade, com isso, o código relevante na classe Parent agora se parece com isso:

@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, mappedBy = "parent")
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE,
            org.hibernate.annotations.CascadeType.DELETE,
            org.hibernate.annotations.CascadeType.MERGE,
            org.hibernate.annotations.CascadeType.PERSIST,
            org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
private Set<Child> childs = new HashSet<Child>();

Eu poderia não uso simples 'ALL', pois isso teria eliminado o pai também.

Aqui Cascade, no contexto de remover, significa que as crianças são removidos se você remover o pai. Não a associação. Se você estiver usando Hibernate como provedor JPA, você pode fazê-lo usando hibernate específica cascata .

Você pode tentar o seguinte:

@OneToOne(cascade = CascadeType.REFRESH) 

ou

@OneToMany(cascade = CascadeType.REFRESH)
@Entity 
class Employee {
     @OneToOne(orphanRemoval=true)
     private Address address;
}

Consulte aqui .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top