【问题标题】:Hibernate strange behavior. Many to Many. Cascade ALL on Delete休眠奇怪的行为。多对多。删除时级联所有
【发布时间】:2017-04-09 17:22:25
【问题描述】:

我有以下型号:

图库-照片-关键字
|
关键字

@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 表中有记录并且属于其他画廊中的其他照片。

但如果关键字属于该画廊的其他照片,它不会被删除。

删除代码:

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

从关键字字段注释中的 Photo 类中删除 cascade = ALL 解决了这个问题。但是为什么?

【问题讨论】:

  • 您的多对多映射错误:一侧必须是反面,使用 mappedBy 关键字。并且 cascade=ALL 对多对多没有意义。如果您删除了包含关键字“foo”的照片,您不希望删除 foo,因为其他照片也可能具有相同的关键字 foo(更不用说其他画廊了)。

标签: hibernate many-to-many cascade cascading-deletes


【解决方案1】:

感谢@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

就是这样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-12
    • 2019-07-31
    相关资源
    最近更新 更多