Java 是否级联=";“全部删除孤立项”;在Hibernate与联接表的单向多对多关联中有什么意义?

Java 是否级联=";“全部删除孤立项”;在Hibernate与联接表的单向多对多关联中有什么意义?,java,hibernate,many-to-many,cascade,orphan,Java,Hibernate,Many To Many,Cascade,Orphan,我有两个对象,它们形成了父子关系,具有多对多关系。按照《Hibernate参考手册》中的建议,我使用联接表映射了这一点: <class name="Conference" table="conferences"> ... <set name="speakers" table="conference_speakers" cascade="all"> <key column="conference_id"/> <

我有两个对象,它们形成了父子关系,具有多对多关系。按照《Hibernate参考手册》中的建议,我使用联接表映射了这一点:

<class name="Conference" table="conferences">
    ...
    <set name="speakers" table="conference_speakers" cascade="all">
        <key column="conference_id"/>
        <many-to-many class="Speaker" column="speaker_id"/>
    </set>
</class>

<class name="Speaker" table="speakers">
    <id name="id" column="id">
        <generator class="native"/>
    </id>
    <property name="firstName"/>
    <property name="lastName"/>
</class>
s
c1.speakers
中删除时引发错误,因为Hibernate同时删除联接表中的行和
speakers
表行:

DEBUG org.hibernate.SQL-从会议id=?和演讲者id=?
DEBUG org.hibernate.SQL-从id=

如果我将
cascade=“all delete orphan”
更改为just
cascade=“all”
,则此测试会按预期工作,尽管它会导致不希望出现的行为,即我的
扬声器表中会出现孤立行

这让我想知道,Hibernate是否有可能知道何时从关系的子端删除孤立对象,但仅当该子对象未被任何其他父对象引用时(无论这些父对象是否在当前的
会话中
)?也许我误用了
cascade=“all delete orphan”

如果我使用JPA注释而不是XML映射,我会得到同样的行为,例如:

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "conference_speakers",
        joinColumns = @JoinColumn(name = "conference_id"),
        inverseJoinColumns = @JoinColumn(name = "speaker_id"))
@org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
private Set<Speaker> speakers = new HashSet<Speaker>();
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name=“会议演讲者”,
joinColumns=@JoinColumn(name=“conference\u id”),
inverseJoinColumns=@JoinColumn(name=“speaker\u id”))
@org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE\u孤儿)
专用集扬声器=新的HashSet();

顺便说一句,Hibernate 3.6.7.Final就是这样。

DELETE\u孤立级联模式不是为多对多关系定义的-仅为一对多关系定义的(后者在JPA标准
@OneToMany
注释中具有“orphanRemove=true | false”属性,因此您不必求助于专有的Hibernate注释)

原因正如您所描述的——Hibernate无法判断多对多关系的“孤立”端是否真的孤立,而不运行对数据库的查询,这是违反直觉的,并且可能会(潜在地)产生严重的性能影响

因此,您描述的休眠行为是正确的(好吧,“如文档所示”);尽管在一个完美的世界中,它会提醒您注意这样一个事实:在第二次编译映射期间,
DELETE\u ORPHAN
在多对多映射上是非法的

老实说,我想不出一个好办法来实现你想做的事情。最简单(但特定于数据库)的方法可能是定义从
会议演讲者
中删除时的触发器,该触发器将检查该演讲者是否“真正”孤立,并从
演讲者
中删除该演讲者。独立于数据库的选项是在DAO或侦听器中手动执行相同的操作

更新:这里摘录自(第11.11章,就在CascadeType.ALL的灰色注释之后),亮点是我的:

一种特殊的级联样式,删除孤立项,仅适用于一对多 关联,并指示删除()操作应 应用于从关联中移除的任何子对象

再往下看:

启用多对一或多对多的级联通常没有意义 多对多协会。事实上,@manytone和@ManyToMany没有 甚至提供一个删除属性。级联通常用于 一对一和一对多协会


感谢您确认我对Hibernate的看法,我不得不发出另一个查询,以了解它是否真的是孤立的。您是否知道文档中提到了这一点,关于多对多和删除孤儿?我绞尽脑汁想知道是否有人提到将两者结合起来。
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "conference_speakers",
        joinColumns = @JoinColumn(name = "conference_id"),
        inverseJoinColumns = @JoinColumn(name = "speaker_id"))
@org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
private Set<Speaker> speakers = new HashSet<Speaker>();