当前位置: 首页 > 知识库问答 >
问题:

如何在Hibernate中覆盖瞬态对象的哈希码和等于?

公孙宇
2023-03-14

我有3个实体,学生,年级和班级。代码如下所示。这只是一个示例。

学生班级

public class Student implements Serializable{
    private static final long serialVersionUID = 1L;
    private String fullName;
    private long studentId;

    //omit getter/setter column mapped to db

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((getFullName() == null) ? 0 : getFullName().hashCode());
        result = prime * result + (int) (getStudentId() ^ (getStudentId() >>> 32));
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (obj instanceof Student)
            return false;
        test other = (test) obj;
        if (getFullName() == null) {
            if (other.getFullName() != null)
                return false;
        } else if (!getFullName().equals(other.getFullName()))
            return false;
        if (getStudentId() != other.getStudentId())
            return false;
        return true;
    }
}

学校班级:

public class SchoolClass implements Serializable{
    private static final long serialVersionUID = 1L;
    private String className;
    private long classId;

    //omit getter/setter column mapped to db

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + (int) (getClassId() ^ (getClassId() >>> 32));
        result = prime * result + ((getClassName() == null) ? 0 : getClassName().hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (obj instanceof SchoolClass)
            return false;
        SchoolClass other = (SchoolClass) obj;
        if (getClassId() != other.getClassId())
            return false;
        if (getClassName() == null) {
            if (other.getClassName() != null)
                return false;
        } else if (!getClassName().equals(other.getClassName()))
            return false;
        return true;
    }

}

等级等级:

public class Grade implements Serializable{
    private static final long serialVersionUID = 1L;
    private SchoolClass  schoolClass;
    private Student student;

    //omit getter/setter column mapped to db

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((getSchoolClass() == null) ? 0 : getSchoolClass().hashCode());
        result = prime * result + ((getStudent() == null) ? 0 : getStudent().hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (obj instanceof Grade)
            return false;
        Grade other = (Grade) obj;
        if (getSchoolClass() == null) {
            if (other.getSchoolClass() != null)
                return false;
        } else if (!getSchoolClass().equals(other.getSchoolClass()))
            return false;
        if (getStudent() == null) {
            if (other.getStudent() != null)
                return false;
        } else if (!getStudent().equals(other.getStudent()))
            return false;
        return true;
    }
}

所以我检查了hibernate文档中的hashcode和equals,它对于DB中存在的实体工作得非常好。我遇到的问题是,在保存到数据库之前,新的瞬态实体对象。我使用HashSet对学生和班级进行了单独的测试,如果它试图添加相同的对象,集合的大小不会增加。

Student s1 = studentRepo.findById(studentId).get();
SchoolClass sc = scRepo.findById(classId).get();
Grade grade = new Grade();
grade.setStudent(s1);
grade.setSchoolClass(sc);
grades.add(grade);
logger.info(grades.size());

这里我有一个新的成绩集,准备这个集并保存到数据库。问题来了,这个集合将包含重复的成绩对象。这意味着将有2个条目具有相同的学生和相同的班级。在年级类中,我覆盖了它的hashcode,等于学生和学校类,它不应该有重复的条目。我想这可能是因为新的年级对象处于瞬态?不确定是什么原因。

当然,我可以用手动方式对成绩进行唯一检查,但哈希码和等于应该是正确的方法,不是吗?

那么这个怎么解决呢?需要一些帮助。

共有1个答案

海翔宇
2023-03-14

感谢@samabcde。他是对的,我错过了!在条件检查中。

 类似资料:
  • 问题内容: 如果未重写hashCode()方法,那么对Java中的任何对象调用hashCode()的结果是什么? 问题答案: 在HotSpot JVM中,默认情况下会在第一次调用时生成未重载或随机数并将其存储在对象标头中。随后的调用或仅从标头中提取此值。默认情况下,它与对象内容或对象位置没有共同点,只有随机数。此行为由HotSpot JVM选项控制,该选项具有以下可能的值: 0:使用全局随机数发生

  • 每当我使用eclipse'source'菜单覆盖hashcode()时,它会在类中生成以下代码 谁能解释一下为什么它要做所有这些计算(乘法和加法),为什么它不简单地返回 ?

  • 问题内容: 我想在哈希中设置所有条目。(SetAllEntriesToHash) 它必须在运行之前清除哈希中的所有项目。 它与GetAllEntriesFromHash相反。 问题答案: 您在这里有几个选择。 1) 您可以通过使用高级Redis API让ServiceStack为您解决此问题。 这种方法将使您不必直接处理散列细节。ServiceStack会为您解决所有问题,并将您发送的对象自动填充

  • 问题内容: 我必须删除列表中的重复对象。这是来自对象Blog的列表,如下所示: 复制的对象是标题,作者,URL和描述与其他对象相同的对象。 而且我无法更改对象。我不能在上面放新方法。 我该怎么做呢? 问题答案: 如果您不能编辑类的源代码(为什么不这样做),则需要遍历列表并根据提到的四个条件(“标题,作者,URL和描述”)比较每个项目。 为了以一种高效的方式做到这一点,我将创建一个新类,类似于包含这

  • 我使用eclipse生成Object的hashCode和equals方法的覆盖,并生成了一些关于hashCode覆盖的问题。下面的hashCode()是否正确? 问题: -为什么eclipse会生成两行代码?我认为将两个结果相加是合适的。知道为什么它们是分开的任务吗? -最终的int素数可以是任何素数吗? -整数结果是否应始终为 1?

  • 问题内容: 我对Java有一个小问题。如果我重写该方法,使得: 这将导致所有键具有相同的索引。是将它们放置在地图的链接列表结构中,还是仅包含替换了所有其他键的最后一个键? 问题答案: 假设您没有覆盖始终返回true 的方法,它们将放置在地图的链接列表结构中。不同的键可能具有相同的hashCode,但是如果所有键都具有相同的hashCode,则您的HashMap将成为链接列表,这首先使使用此结构的目