Hibernate 3.6.10不会通过OneToMany JoinTable级联删除

我一直在搞乱这个并且谷歌搜索它大约4天而且我对于Hibernate注释如何与JPA注释一起工作变得疯狂。 我有两个非常简单的实体:

学生

package com.vaannila.student; import java.util.HashSet; import java.util.Set; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.OneToMany; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; @Entity public class Student { @Id @GeneratedValue private long studentId; private String studentName; @OneToMany(orphanRemoval = true) @Cascade(CascadeType.ALL) @JoinTable(name = "STUDENT_PHONE", joinColumns = { @JoinColumn(name = "STUDENT_ID") }, inverseJoinColumns = { @JoinColumn(name = "PHONE_ID") }) private Set studentPhoneNumbers = new HashSet(0); public Student() { } public Student(String studentName, Set studentPhoneNumbers) { this.studentName = studentName; this.studentPhoneNumbers = studentPhoneNumbers; } public long getStudentId() { return this.studentId; } public void setStudentId(long studentId) { this.studentId = studentId; } public String getStudentName() { return this.studentName; } public void setStudentName(String studentName) { this.studentName = studentName; } public Set getStudentPhoneNumbers() { return this.studentPhoneNumbers; } public void setStudentPhoneNumbers(Set studentPhoneNumbers) { this.studentPhoneNumbers = studentPhoneNumbers; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (int) (studentId ^ (studentId >>> 32)); result = prime * result + ((studentName == null) ? 0 : studentName.hashCode()); result = prime * result + ((studentPhoneNumbers == null) ? 0 : studentPhoneNumbers.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (studentId != other.studentId) return false; if (studentName == null) { if (other.studentName != null) return false; } else if (!studentName.equals(other.studentName)) return false; if (studentPhoneNumbers == null) { if (other.studentPhoneNumbers != null) return false; } else if (!studentPhoneNumbers.equals(other.studentPhoneNumbers)) return false; return true; } } 

电话

 package com.vaannila.student; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Phone { @Id @GeneratedValue private long phoneId; private String phoneType; private String phoneNumber; public Phone() { } public Phone(String phoneType, String phoneNumber) { this.phoneType = phoneType; this.phoneNumber = phoneNumber; } public long getPhoneId() { return this.phoneId; } public void setPhoneId(long phoneId) { this.phoneId = phoneId; } public String getPhoneType() { return this.phoneType; } public void setPhoneType(String phoneType) { this.phoneType = phoneType; } public String getPhoneNumber() { return this.phoneNumber; } public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (int) (phoneId ^ (phoneId >>> 32)); result = prime * result + ((phoneNumber == null) ? 0 : phoneNumber.hashCode()); result = prime * result + ((phoneType == null) ? 0 : phoneType.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Phone other = (Phone) obj; if (phoneId != other.phoneId) return false; if (phoneNumber == null) { if (other.phoneNumber != null) return false; } else if (!phoneNumber.equals(other.phoneNumber)) return false; if (phoneType == null) { if (other.phoneType != null) return false; } else if (!phoneType.equals(other.phoneType)) return false; return true; } } 

我在这里粘贴了整个代码,以便您可以看到导入的来源。 我认为问题在那里。 重要提示 :我正在使用JoinTable因为Hibernate Docs建议使用

好! 现在我创建一个有两个电话号码的Student ,并将其正确保存在数据库中。 这会创建以下内容:

学生

  studentid | studentname -----------+------------- 2 | foo (1 rows) 

student_phone

  student_id | phone_id ------------+--------- 2 | 3 2 | 4 (2 rows) 

电话

  phoneid | phonenumber | phonetyp ---------+-------------+--------- 4 | 9889343423 | mobile 3 | 32354353 | house (2 rows) 

这就是问题所在。 如果我删除客户端中的一个电话号码(移动)并将分离的学生实体发送到服务器并执行更新,请执行以下操作:

 Hibernate: update Student set studentName=? where studentId=? Hibernate: update Phone set phoneNumber=?, phoneType=? where phoneId=? Hibernate: delete from STUDENT_PHONE where STUDENT_ID=? Hibernate: insert into STUDENT_PHONE (STUDENT_ID, PHONE_ID) values (?, ?) 

如您所见,它只删除连接表中的条目,但不删除电话表中的电话条目本身。 所以现在这些表看起来像这样:

学生

  studentid | studentname -----------+------------- 2 | foo (1 rows) 

student_phone

  student_id | phone_id ------------+--------- 2 | 3 (1 rows) 

电话

  phoneid | phonenumber | phonetyp ---------+-------------+--------- 4 | 9889343423 | mobile 3 | 32354353 | house (2 rows) 

问题: 这是正常行为吗? 即使级联删除和孤立删除设置为true? 我怎样才能实现Hibernate删除手机表中的电话号码呢?

更新我正在使用PostgreSQL

在进一步使用Hibernate之后,我意识到我没有正确实现equalshashCode函数,导致在CRUD操作上使用Hibernate生成序列的一些麻烦。 在这篇伟大的文章中描述(并解决了)这个问题(在我看来必须阅读)

最好的祝福

这看起来非常相似

http://www.mkyong.com/hibernate/cascade-jpa-hibernate-annotation-common-mistake/

您正在混合JPA和hibernate注释。 我会坚持使用一个(最好是JPA,但博客文章坚持使用hibernate)并且这样关系:

 @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)