代码之家  ›  专栏  ›  技术社区  ›  Shpytyack Artem

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

  •  1
  • Shpytyack Artem  · 技术社区  · 8 年前

    我们有这样的 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中运行良好。 org.hibernate.exception.ConstraintViolationException: could not execute statement 错误

    启用“Show 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".
    

    1 回复  |  直到 8 年前
        1
  •  2
  •   Shpytyack Artem    6 年前

    问题的原因是hibernate内核中的一个bug。班级组织。冬眠发动机spi。操作队列。 以下是修复后的代码:

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

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