2012-02-24 11 views
15

Nella mia applicazione, un'operazione di ibernazione va in questo modo. L'applicazione aggiorna un'entità padre con nuovi valori dalla richiesta ed elimina tutte le entità figlio esistenti (precedentemente inserite) e inserisce nuovi record figli.Una raccolta con cascade = "all-delete-orphan" non è più referenziata dall'istanza dell'entità proprietaria

Sto utilizzando lo stato di sospensione DELETE_ORPHAN per questo, come puoi vedere di seguito.

quando faccio questo, sto diventando l'eccezione di seguito:

org.hibernate.HibernateException: Una collezione con cascade = "all-delete-orphan" non era più a cui fa riferimento il possesso entità istanza: com.childs

Ho visto thread simili con il problema, e ho cercato di appy soluzioni in quei thread. Ma che non ha funzionato

mio soggetto controllante

public class Parent implements Serializable { 

      @Column(name = "PARENT_ID") 
      @Basic(fetch = FetchType.EAGER) 
      @Id 
      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq") 
      @SequenceGenerator(name = "seq", sequenceName = "seq") 
      private Integer parentId; //primary key of parent 

      ....... 
      ........ 

      //mapping to child entity 
      @OneToMany(mappedBy = "parent", cascade = { CascadeType.ALL }, fetch = FetchType.LAZY) 
      @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) 
      private Set<Child> childs; 

      ................ 
      ............... 

} 

entità Bambino ha una chiave combinata e ha un'entità PK ha mostrato di seguito Codice

public class ChildPK implements Serializable { 

    /** The Constant serialVersionUID. */ 
    private static final long serialVersionUID = -447592368963477750L; 

    /** . */ 
    @ManyToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY) 
    @JoinColumns({ @JoinColumn(name = "PARENT_ID", referencedColumnName = "PARENT_ID") }) 
    @Id 
    private Parent parent; 

    /**. */ 

    @Column(name = "CHILD_ID") 
    @Basic(fetch = FetchType.EAGER) 
    @Id 
    @GenericGenerator(name="child_seq", strategy="com.DB2Dialect") 
    @GeneratedValue(generator="child_seq") 
    private Integer childId; 

} 

child entity goes like this: 


public class Child implements Serializable { 

    /** The Constant serialVersionUID. */ 
    private static final long serialVersionUID = 185670997643552301L; 

    /** The pol cntct id. */ 
    @Column(name = "CHILD_ID") 
    @Basic(fetch = FetchType.EAGER) 
    @Id 
    private Integer childId; 

    @ManyToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY) 
    @JoinColumns({ @JoinColumn(name = "PARENT_ID", referencedColumnName = "PARENT_ID") }) 
    @Id 
    private Parent parent; 

} 

Java

................... 
    .............. 
    parent.getChild().clear(); 
    Child child = new Child(); 
    parent.setChild(child); 

Cosa potrebbe essere sbagliato qui.
Grazie in anticipo ...

risposta

49

Il tuo ultimo frammento di codice Java non viene compilato. Immagino che sembri

parent.getChilds().clear(); // note: you should name it children rather than childs 
parent.setChilds(someNewSetOfChildren): 

Non fare l'ultima istruzione. Invece di sostituire il set con un altro, deselezionare il set e aggiungere i nuovi bambini al set eliminato:

parent.clearChildren(); 
parent.addChildren(someNewSetOfChildren); 

in cui sono definiti i metodi come:

public void clearChildren() { 
    this.children.clear(); 
} 

public void addChildren(Collection<Child> children) { 
    this.children.addAll(children); 
} 

Il metodo setChildren deve essere rimosso completamente , o dovrebbe essere sostituito con la seguente implementazione:

public void setChildren(Collection<Child> children) { 
    this.children.clear(); 
    this.children.addAll(children); 
} 
+0

Per @JBNizet ho un problema simile e ho applicato la soluzione. In realtà, dalle 2 soluzioni che hai indicato ho usato la versione successiva (nel metodo setter ho eliminato la collezione bambini - this.children.clear() - e ho aggiunto i nuovi bambini - this.children.addAll (bambini)). Questo cambiamento non ha risolto il mio problema. Ricevo ancora il messaggio "Una raccolta con cascade =" all-delete-orphan "non è più referenziata dall'eccezione" istanza dell'entità proprietaria ". Hai un'idea del perché? Grazie mille! – ovdsrn

+0

No, non ne ho idea. Puoi fare una domanda, mostrando il tuo codice, la traccia completa dello stack, ecc. –

+1

Forse in 'setChildren' deve essere aggiunto il controllo nullo' if (children! = Null) {this.children.addAll (bambini);} – lolotron

9

Ha funzionato per me.

  1. Cancellato tutte le entità figlio.
  2. Invece di impostare le nuove entità figlio sull'oggetto padre, ho utilizzato il metodo addAll per aggiungere le nuove entità figlio.

    parent.getChildren().clear(); 
    parent.getChildren().addAll(newChildrenList); 
    
    @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, 
          cascade = CascadeType.ALL, orphanRemoval = true) 
    
    public Set<Children> getChildren() { 
        return this.children; 
    } 
    
4

invece di setChilds uso addAll,

da questo,

parent.getChilds().clear(); 
    parent.setChilds(newChilds); 

a

parent.getChilds().clear(); 
    parent.getChilds().addAll(newChilds); 
+0

dove devono essere aggiunti? nell'entità padre o nell'entità figlio? –

+0

nell'entità padre aggiungere tutte le entità figlio – mathi

5

Ho affrontato lo stesso problema e farlo risolto nel seguente modo:

1- aggiungere {} CascadeType.ALL, orphanRemoval = true in tutte @OneToMany annotazioni in tutte entità Childs di tale elemento.

2- Controllare i hashCode() e equalls() di queste entità, a volte hanno erros

3- Non utilizzare parent.setChilds(newChilds); come il motore chiederà manca il riferimento al bambino, ma utilizza invece utilizzare

parent.getChilds().clear(); 
parent.getChilds().add(Child); 

o

parent.getChilds().addAll(Childs); 

Questi passaggi hanno risolto il problema dopo 4 ore di ricerca

Problemi correlati