2016-11-25 2 views
0

Ich habe folgendes Modell:Hibernate seltsames Verhalten. Viel zu viel. Cascade ALL auf Löschen

Galerie-Foto-Stichwort
|
Stichwort

@Entity 
@Table(name = "galleries") 
public class Gallery extends BaseModel{  

    @OneToMany(cascade = PERSIST, mappedBy = "mainGallery", orphanRemoval = true) 
    public List<Photo> photos; 

    @ManyToMany(fetch = LAZY, cascade = ALL) 
    @JoinTable(name="gallery_keywords", joinColumns= {@JoinColumn(name="gallery_id")}, inverseJoinColumns={@JoinColumn(name="keyword_id")}) 
    public List<Keyword> keywords = new ArrayList<>(); 


@Entity 
@Table(name = "photos") 
public class Photo extends BaseModel{ 

    @ManyToOne(fetch = LAZY, cascade = PERSIST) public Gallery mainGallery; 

    @ManyToMany(fetch = LAZY, cascade = ALL) 
    @JoinTable(name="photo_keywords", joinColumns= {@JoinColumn(name="photo_id")}, inverseJoinColumns={@JoinColumn(name="keyword_id")}) 
    public List<Keyword> keywords = new ArrayList<>(); 

@Entity 
@Table(name = "keywords") 
public class Keyword extends BaseModel { 

    @ManyToMany(fetch = LAZY) 
    @JoinTable(name="photo_keywords", joinColumns={@JoinColumn(name="keyword_id")}, inverseJoinColumns={@JoinColumn(name="photo_id")}) 
    public List<Photo> photos = new ArrayList<>(); 

    @ManyToMany(fetch = LAZY) 
    @JoinTable(name="gallery_keywords", joinColumns={@JoinColumn(name="keyword_id")}, inverseJoinColumns={@JoinColumn(name="gallery_id")}) 
    public List<Gallery> galleries = new ArrayList<>(); 

PROBLEM: Ich habe ein Problem beim Löschen eines Fotos.
Wenn ein Schlüsselwort, das zu diesem Foto gehört, nicht in anderen Fotos dieser Galerie erscheint, wird es aus der DB gelöscht, obwohl es Datensätze in der Tabelle photo_keywords enthält und zu anderen Fotos in anderen Galerien gehört.

Aber wenn das Stichwort zu anderen Fotos dieser Galerie gehört, wird es nicht gelöscht.

Löschcode:

public void delete(Photo photo) { 
    photo.mainGallery.photos.remove(photo); 
    photo.delete(); 
} 

Entfernen Kaskade = ALL von Fotoklasse von Keywords-Feld Anmerkung löst es. Aber warum noch?

+2

Ihre ManyToMany-Zuordnung ist falsch: Eine der Seiten MUSS die inverse Seite sein, die das mappedBy-Schlüsselwort verwendet. Und cascade = ALL macht keinen Sinn für eine ManyToMany. Wenn Sie ein Foto mit einem Keyword "foo" löschen, möchten Sie nicht, dass foo gelöscht wird, weil andere Fotos möglicherweise dasselbe Keyword foo haben (ganz zu schweigen von anderen Galerien). –

Antwort

0

Thnx zu @JB Nizet.

Problem bestand darin, dass beide Seiten besitzende und umgekehrte Annotationen hatten. Deshalb wurde Kaskade ignoriert. In der Dokumentation wird jedoch gesagt, dass eine bidirektionale Assoziation eine besitzende Seite und eine inverse (mappedBy) Seite hat. Deshalb war das Verhalten unvorhersehbar. Nachdem er von Keywords unnötige Anmerkung zu entfernen:

@JoinTable(name="photo_keywords", joinColumns={@JoinColumn(name="keyword_id")}, inverseJoinColumns={@JoinColumn(name="photo_id")}) 

Und fügte hinzu: mappedBy = "keywords" ich immer vernünftig Ausnahme begonnen: org.hibernate.exception.ConstraintViolationException: could not execute statement So ersetzt i Kaskade = ALL mit Kaskade = {PERSIST, MERGE}

Und es war es.