休眠奇怪的行为。多对多。在删除时级联 ALL
Hibernate strange behavior. Many to Many. Cascade ALL on Delete
我有以下型号:
图库-照片-关键字
|
关键词
@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<>();
问题:我在删除照片时遇到问题。
如果属于这张照片的任何关键词没有出现在该图库的任何其他照片中,尽管它在 photo_keywords table 中有记录并且属于其他图库中的其他照片,但它会从数据库中删除。
但如果关键字属于该图库的其他照片,则不会被删除。
删除代码:
public void delete(Photo photo) {
photo.mainGallery.photos.remove(photo);
photo.delete();
}
从关键字字段注释中删除 cascade = ALL from Photo class 即可解决。但还是为什么?
感谢@JB Nizet。
问题在于双方都有拥有和反向注释。这就是级联被忽略的原因。
但是在文档中据说双向关联具有拥有方和反向(mappedBy)方。
这就是为什么行为是不可预测的。
从关键字中删除不必要的注释后:
@JoinTable(name="photo_keywords", joinColumns={@JoinColumn(name="keyword_id")}, inverseJoinColumns={@JoinColumn(name="photo_id")})
并添加:mappedBy = "keywords"
我开始得到合理的例外:
org.hibernate.exception.ConstraintViolationException: could not execute statement
所以我用 cascade = {PERSIST, MERGE}
替换了 cascade = ALL
就是这样。
我有以下型号:
图库-照片-关键字
|
关键词
@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<>();
问题:我在删除照片时遇到问题。
如果属于这张照片的任何关键词没有出现在该图库的任何其他照片中,尽管它在 photo_keywords table 中有记录并且属于其他图库中的其他照片,但它会从数据库中删除。
但如果关键字属于该图库的其他照片,则不会被删除。
删除代码:
public void delete(Photo photo) {
photo.mainGallery.photos.remove(photo);
photo.delete();
}
从关键字字段注释中删除 cascade = ALL from Photo class 即可解决。但还是为什么?
感谢@JB Nizet。
问题在于双方都有拥有和反向注释。这就是级联被忽略的原因。 但是在文档中据说双向关联具有拥有方和反向(mappedBy)方。 这就是为什么行为是不可预测的。 从关键字中删除不必要的注释后:
@JoinTable(name="photo_keywords", joinColumns={@JoinColumn(name="keyword_id")}, inverseJoinColumns={@JoinColumn(name="photo_id")})
并添加:mappedBy = "keywords"
我开始得到合理的例外:
org.hibernate.exception.ConstraintViolationException: could not execute statement
所以我用 cascade = {PERSIST, MERGE}
就是这样。