I have following model:
Gallery-Photo-Keyword
|
Keyword
@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: I have a problem on deletion of a photo.
If any keyword which belongs to this photo does not appear in any other photos of this gallery it gets deleted from DB despite on that it has records in photo_keywords table and belongs to other photos in other galleries.
But if keyword belongs to other photos of this gallery it doesn't get deleted.
Deletion code:
public void delete(Photo photo) {
photo.mainGallery.photos.remove(photo);
photo.delete();
}
Removing cascade = ALL from Photo class from keywords field annotation solves it. But still why?
Thnx to @JB Nizet.
Problem was in that both sides had owning and inverse annotations. That's why cascade was ignored. But in documentation it is said that a bidirectional association has an owning side and an inverse (mappedBy) side. That's why behavior was unpredictable. After removing from Keywords unnecessary annotation:
@JoinTable(name="photo_keywords", joinColumns={@JoinColumn(name="keyword_id")}, inverseJoinColumns={@JoinColumn(name="photo_id")})
And added: mappedBy = "keywords"
I started getting reasonable exception:
org.hibernate.exception.ConstraintViolationException: could not execute statement
So i replaced cascade = ALL with cascade = {PERSIST, MERGE}
And it was it.