java - 如何在 hibernate 中覆盖 transient 对象的哈希码和等于?

标签 java hibernate spring-data-jpa

我有 3 个实体:学生、年级和类(class)。代码如下所示。这只是一个样本。

学生类

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;
    }
}

学校类(class):

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,它对于数据库中存在的实体来说工作得非常好。我遇到的问题是在保存到数据库之前新的 transient 实体对象。我使用 HashSet 对 Student 和 SchoolClass 进行了单独的测试,如果尝试添加相同的对象,集合的大小不会增加。

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());

这里我有一组新的成绩并准备好该组并保存到数据库。问题来了,这个集合将包含重复的等级对象。这意味着同一学生和同一类(class)将有 2 个条目。在年级类(class)中,我覆盖其哈希码并等于 Student 和 SchoolClass,它不应该有重复的条目。我想这可能是因为新的 Grade 对象处于 transient ?不太确定是什么原因。

当然,我可以手动方式对成绩进行唯一检查,但 hashcode 和 equals 应该是正确的方法,不是吗?

那么如何解决这个问题呢?需要一些帮助。

最佳答案

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

关于java - 如何在 hibernate 中覆盖 transient 对象的哈希码和等于?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57246696/

相关文章:

java - 白标错误页面 - 应用程序没有明确的映射/错误

postgresql - 无法使用Kotlin和Spring数据保留数据

java - jOOQ 中带有条件的 MySQL sum()

java - Cascade.DELETE_ORPHAN 和父/子关系的 Hibernate "deleted entity passed to persist"问题

spring - 我无法获取 JDBC 连接异常

java - JPA 如果失败则尝试删除设置为非 Activity 状态

java - 从 JPA native 查询中获取列名

java - 按下后退按钮时 Activity 不会关闭

Java:从集合中删除元素

java - java中的正则表达式仅允许字母数字输入数据