Domanda

Ho un problema con una semplice mappatura @OneToMany tra un genitore e un'entità figlio. Tutto funziona bene, solo che i record figlio non vengono eliminati quando li tolgo dalla collezione.

Il genitore:

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

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

 ...
}

Il bambino:

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

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

  ...
}

Se ora cancello e bambino dal bambino Set, non vengono eliminati dal database. Ho provato annullando il riferimento child.parent, ma che non ha funzionato neanche.

I soggetti sono utilizzati in un'applicazione web, la cancellazione avviene come parte di una richiesta Ajax. Non ho una lista di bambino cancellati quando si preme il pulsante di salvataggio, quindi non posso eliminarli in modo implicito.

È stato utile?

Soluzione

il comportamento di APP è corretta (che significa secondo le specifiche ): gli oggetti non vengono eliminati semplicemente perché li hai rimosso da una collezione OneToMany. Ci sono estensioni specifiche del fornitore che lo fanno, ma nativo APP non è assolutamente adatto per esso.

In parte questo è dovuto al fatto JPA in realtà non sa se deve cancellare qualcosa rimosso dalla raccolta. In termini di modellazione degli oggetti, questa è la differenza tra il composizione e "l'aggregazione *.

composizione , l'entità bambino non ha esistenza senza il genitore. Un esempio classico è tra House e in camera. Elimina la Casa e le Camere vanno troppo.

Aggregazione è una sorta di associazione più flessibile ed è caratterizzata da golf e Student. Eliminare il corso e lo studente esiste ancora (probabilmente in altri corsi).

Quindi è necessario usare sia per le estensioni specifiche del fornitore per forzare questo comportamento (se disponibile) o eliminare in modo esplicito il bambino e rimuoverlo dalla collezione del genitore.

Sono consapevole di:

Altri suggerimenti

In aggiunta alla risposta Cletus', JPA 2.0 , finale dal dicembre 2010 , introduce un attributo orphanRemoval su annotazioni @OneToMany. Per maggiori dettagli si veda questo blog .

Si noti che dal momento che la specifica è relativamente nuovo, non tutti i provider JPA 1 ha un finale di esecuzione JPA 2. Ad esempio, il Hibernate 3.5.0-Beta-2 rilascio non supporta ancora questo attributo.

Si può provare questo:

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

Come ha spiegato, non è possibile fare quello che voglio con APP, quindi ho impiegato l'annotazione hibernate.cascade, con questo, il relativo codice nella classe padre appare come segue:

@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>();

Non ho potuto utilizzo semplice 'ALL' in quanto ciò avrebbe cancellato il genitore pure.

Qui a cascata, nel contesto di rimuovere, vuol dire che i bambini vengono rimossi se si rimuove il genitore. Non l'associazione. Se si utilizza Hibernate come provider JPA, è possibile farlo utilizzando hibernate specifica cascata .

Si può provare questo:

@OneToOne(cascade = CascadeType.REFRESH) 

o

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

qui .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top