Hibernate从4迁移到5之后,OneToOne关系会导致ConstraintViolationException

时间:2017-10-02 17:44:55

标签: java postgresql hibernate migration

我们有OneToOne双向关系:

class Student:

    @PrimaryKeyJoinColumn
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @Fetch(FetchMode.JOIN)
    private StudentState state;

    public Student() {
        super();
        state = new StudentState(this);
    }

    public StudentState getState() {
        return state;
    }

class StudentState:

    @MapsId
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "student")
    private Student student;

    @Column(name = "inactive")
    private Boolean isInactive = false;

    public StudentState() {
    }

    public StudentState(Student student) {
        this.student = student;
    }

    public boolean isInactive() {
        if (isInactive == null) {
            return false;
        }
        return isInactive;
    }

    public void setIsInactive(boolean isInactive) {
        this.isInactive = isInactive;
    }

以下代码用于创建学生:

Transaction t = session.beginTransaction();

Student student = new Student();
session.save(student);
student.getState().setIsInactive(true);

t.commit();

代码在Hibernate 4中运行良好。 在Hibernate 5中,它与org.hibernate.exception.ConstraintViolationException: could not execute statement崩溃 错误。

启用“显示sql”表明在事务提交时,hibernate尝试在insert StudentState查询之前执行insert Student查询。它导致:

Caused by: org.postgresql.util.PSQLException: 
ERROR: insert or update on table "studentstate" violates foreign key constraint "fk77j3mjaigcfotxlor35mdsl56"'
Detail: Key (student)=(12) is not present in table "students".

任何想法为什么会发生,为什么它以前工作以及如何解决它? TIA

1 个答案:

答案 0 :(得分:1)

问题的原因是hibernate核心中的一个错误。类org.hibernate.engine.spi.ActionQueue。 这是修复后的代码:

            boolean hasAnyParentEntityNames(BatchIdentifier batchIdentifier) {
                return parentEntityNames.contains(batchIdentifier.getEntityName())
                        || parentEntityNames.contains(batchIdentifier.getRootEntityName());
            }

            boolean hasAnyChildEntityNames(BatchIdentifier batchIdentifier) {
                return childEntityNames.contains(batchIdentifier.getEntityName())
                        || childEntityNames.contains(batchIdentifier.getRootEntityName());
            }

以下是以前的代码:

        boolean hasAnyParentEntityNames(BatchIdentifier batchIdentifier) {
            return parentEntityNames.contains(batchIdentifier.getEntityName())
                    || parentEntityNames.contains(batchIdentifier.getRootEntityName());
        }

        boolean hasAnyChildEntityNames(BatchIdentifier batchIdentifier) {
            return childEntityNames.contains(batchIdentifier.getEntityName())
                    || parentEntityNames.contains(batchIdentifier.getRootEntityName());
        }

使用错误列表查找子项的人,在某些情况下,该方法返回相反的值。