Java 是否级联=";“全部删除孤立项”;在Hibernate与联接表的单向多对多关联中有什么意义?
我有两个对象,它们形成了父子关系,具有多对多关系。按照《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"/> <
<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”
更改为justcascade=“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>();