当前位置: 首页 > 面试题库 >

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

归翔
2023-03-14
问题内容

我一直在搞怪它并使用它搜索了大约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<Phone> studentPhoneNumbers = new HashSet<Phone>(0);

    public Student() {
    }

    public Student(String studentName, Set<Phone> 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<Phone> getStudentPhoneNumbers() {
        return this.studentPhoneNumbers;
    }

    public void setStudentPhoneNumbers(Set<Phone> 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_id | phone_id
------------+---------
          2 |        3
          2 |        4
(2 rows)

电话

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

问题来了。如果我删除了客户端的一个电话号码(移动电话)并将分离的学生实体发送到服务器并执行更新,请hibernate以下内容:

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_id | phone_id
------------+---------
          2 |        3
(1 rows)

电话

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

问题: 这是正常行为吗? 即使级联删除和孤立删除设置为true?我如何实现Hibernate也删除电话表中的电话号码?

更新 我正在使用PostgreSQL


问题答案:

经过与Hibernate的进一步合作,我终于意识到我没有正确实现,equals并且hashCode函数在CRUD操作上的Hibernate
Generated
Sequence造成了一些麻烦。在这篇很棒的文章中描述(并解决了)这个问题(我认为必须阅读)

最好的祝福



 类似资料:
  • 编辑:修改问题以更好地反映问题。此处最初发布的问题 我有一个父实体(< code >上下文)和一个子实体(< code >用户)。父级上的级联“删除”不会删除子级。代码如下:

  • 问题内容: 我的模型与模型有关系。我已指定该关系应级联删除操作。但是,当我查询和删除用户时,出现一个错误,指出仍在引用地址行。如何删除用户和地址? 问题答案: 你有以下… 请注意,在“过滤器”之后,您仍然返回Query对象。因此,当您调用时,您正在调用Query对象(而不是User对象)。这意味着您正在执行批量删除(尽管可能只删除了一行) 您正在使用的方法的文档说… 该方法不提供Python中的级

  • 有什么方法可以捕获“删除级联”事件吗?我在Debezium常见问题解答(在页面底部)中读到: ==为什么在某些情况下我看不到删除事件? 这可能是使用语句造成的。在本例中,数据库https://dev.mysql.com/doc/refman/5.7/en/innodb-and-mysql-replication.html生成的删除事件[不是binlog的一部分],因此Debezium无法捕获。 我

  • 我正在尝试删除hibernate中的子实体,但遇到以下异常: 这些是我的实体: @table(name=“Customer”)公共类Customer{ @OneTomany(Cascade=CascadeType.All,MappedBy=“CustomerID”,OphanRemoval=True)私有集QuoteConfig; 这是我想要移除的部分 我的问题是如何删除子实体QuoteConfi

  • 问题内容: 我有以下两个实体: 1-播放列表: *保存或更新播放列表实体时,需要使用 *CascadeType.ALL 来保存和更新PlaylistadMap集合。 orphanRemoval = true :在删除播放列表实体时需要,PlaylistadMap引用也应删除。 2- PlaylistadMap: 使用我删除播放列表时,出现以下异常: 请告知如何解决此异常。 问题答案: 将 Fetc

  • 问题内容: 我必须缺少SQLAlchemy的层叠选项的琐碎内容,因为我无法获得简单的层叠删除来正确操作-如果删除了父元素,则子对象将使用外键保留。 我在这里放了一个简洁的测试用例: 输出: 父母与子女之间存在简单的一对多关系。该脚本创建一个父级,添加3个子级,然后提交。接下来,它删除父级,但子级仍然存在。为什么?如何使孩子级联删除? 问题答案: 问题是sqlalchemy认为是父级的,因为这是您定