Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JPA/Hibernate:反向OneToOne孤立删除约束冲突 问题:_Hibernate_Jpa_Constraints_One To One_Orphan - Fatal编程技术网

JPA/Hibernate:反向OneToOne孤立删除约束冲突 问题:

JPA/Hibernate:反向OneToOne孤立删除约束冲突 问题:,hibernate,jpa,constraints,one-to-one,orphan,Hibernate,Jpa,Constraints,One To One,Orphan,我在父母和孩子之间有一个@OneToOne关系,该关系由孩子映射,并且孤儿移除设置为true。孩子还与第三个实体有@manytomy关系 当将子项设置为null(希望删除子项)时,我得到一个完整性约束冲突:外键 测试模型: 导师与学生有一对一的关系,后者与课程实体有许多关系: OneTONE关系由Student.tutor映射(学生表中的ID\u tutor外键列) 级联=全部 删除=真 多人关系保存在连接表STUDENT_COURSE中,外键指向STUDENT表和COURSE表 我正在

我在父母和孩子之间有一个@OneToOne关系,该关系由孩子映射,并且孤儿移除设置为true。孩子还与第三个实体有@manytomy关系

当将子项设置为null(希望删除子项)时,我得到一个完整性约束冲突:外键

测试模型: 导师学生有一对一的关系,后者与课程实体有许多关系:

  • OneTONE关系由Student.tutor映射(学生表中的ID\u tutor外键列)
    • 级联=全部
    • 删除=真
  • 多人关系保存在连接表STUDENT_COURSE中,外键指向STUDENT表和COURSE表
我正在使用Hibernate5.0.11(JPA2.1)。在我的测试中,我使用了HSQLDB,但这个问题也发生在Oracle数据库上

脚本: 我有一个导师链接到一个学生,其中包含一个课程列表。将导师的学生设置为null时,Hibernate直接发出SQL“从学生中删除,其中id=?”,这导致“完整性约束冲突:外键无操作;FK1XM2HEI9CHMWOQF2WFM104NMG表:学生课程”

如果OneToMany关系未“反转”(导师表中没有mappedBy和ID_学生外键),则不会出现此问题。在这种情况下,将正确地从数据库中删除学生实体及其在Student_课程表中的相关记录

代码:
@实体
公开课导师{
私人长id;
私有字符串名称;
私立学生;
公共导师(){super();}
公共导师(字符串名称,学生){
超级();
this.name=名称;
设置学生(学生);
}
@身份证
@生成值
public Long getId(){return id;}
public void setId(长id){this.id=id;}
公共字符串getName(){return name;}
public void setName(字符串名){this.name=name;}
@OneTONE(cascade=CascadeType.ALL,orphanRemoving=true,mappedBy=“tutor”)
公共学生getStudent(){return Student;}
公立学校学生(学生){
这个。学生=学生;
如果(学生!=null){
student.setTutor(本);
}
}
}
@实体
公立班学生{
私人长id;
私有字符串名称;
私人地图课程;
私人家教;
公立学生(){super();}
公立学生(字符串名称、地图课程){
超级();
this.name=名称;
本课程=课程;
}
@身份证
@生成值
public Long getId(){return id;}
public void setId(长id){this.id=id;}
公共字符串getName(){return name;}
public void setName(字符串名){this.name=name;}
@许多
公共地图getCourses(){return courses;}
公共课程(地图课程){this.courses=courses;}
@奥内托内
公共导师getutor(){return Tutor;}
public void setTutor(Tutor Tutor){this.Tutor=Tutor;}
}
@实体
公共课{
私人长id;
私有字符串名称;
公共课程(){super();}
公共课程(字符串名称){
超级();
this.name=名称;
}
@身份证
@生成值
public Long getId(){return id;}
public void setId(长id){this.id=id;}
公共字符串getName(){return name;}
public void setName(字符串名){this.name=name;}
}
公共类CheckManyToManyDeletion{
私有静态最终记录器Logger=Logger.getLogger(CheckManyToManyDeletation.class);
私有静态SessionFactory SessionFactory;
公共静态void main(字符串[]args){
configure(“log4j config.xml”);
类[]映射=新类[]{Tutor.Class、Student.Class、Course.Class};
创建表(映射);
sessionFactory=DBUtils.createSessionFactory(映射);
试一试{
long tutoroid=initialImport();
Session Session=sessionFactory.openSession();
事务tx=会话.beginTransaction();
Tutor Tutor=session.get(Tutor.class,tutorId);
logger.info(“删除学生”);
tutor.setStudent(空);
tx.commit();
}最后{
sessionFactory.close();
}
}
私有静态长initialImport(){
Session Session=sessionFactory.openSession();
事务tx=会话.beginTransaction();
学生=新生();
学生名称(“学生”);
Map courses=newhashmap();
学生课程;
对于(int i=0;i<5;i++){
课程=新课程();
课程名称(“课程”+i);
保存(课程);
courses.put(course.getName(),courses);
}
导师=新导师(“导师”,学生);
session.save(导师);
tx.commit();
session.close();
返回tutor.getId();
}
}
笔记: 实际上,我们的应用程序附带了一个巨大的数据模型:

  • 持久化和删除实体是通过级联实现的
  • 我们反转OneToOne关系,为子对象提供与其父对象相同的id(通过@MapsId)

您不介意将cascade添加到课程中吗?也许我会稍后再看,但对于初学者来说,您不应该通过将things设置为null来删除数据库条目。您需要查看正在创建的数据库模式并考虑这一点。一个学生可以有多个导师,而一个导师可以有多个学生,因此这是一个多个关系,应该由联接表来处理。正确的删除方法是将学生从导师的学生名单中删除,反之亦然。我们的商业模式相当复杂。这就是为什么我创建了一个测试模型b
@Entity
public class Tutor {
    private Long id;
    private String name;
    private Student student;
    public Tutor() { super(); }
    public Tutor(String name, Student student) {
        super();
        this.name = name;
        setStudent(student);
    }
    @Id
    @GeneratedValue
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    @OneToOne(cascade=CascadeType.ALL, orphanRemoval=true, mappedBy="tutor")
    public Student getStudent() { return student; }
    public void setStudent(Student student) {
        this.student = student;
        if(student != null) {
            student.setTutor(this);
        }
    }
}

@Entity
public class Student {
    private Long id;
    private String name;
    private Map<String, Course> courses;
    private Tutor tutor;
    public Student() { super(); }
    public Student(String name, Map<String, Course> courses) {
        super();
        this.name = name;
        this.courses = courses;
    }
    @Id
    @GeneratedValue
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    @ManyToMany
    public Map<String, Course> getCourses() { return courses; }
    public void setCourses(Map<String, Course> courses) { this.courses = courses; }
    @OneToOne
    public Tutor getTutor() { return tutor; }
    public void setTutor(Tutor tutor) { this.tutor = tutor; }   
}

@Entity
public class Course {
    private Long id;
    private String name;
    public Course() { super(); }
    public Course(String name) {
        super();
        this.name = name;
    }
    @Id
    @GeneratedValue
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

public class CheckManyToManyDeletation {
    private static final Logger logger = Logger.getLogger(CheckManyToManyDeletation.class);
    private static SessionFactory sessionFactory;
    public static void main(String[] args) {
        DOMConfigurator.configure("log4j-config.xml");
        Class[] mappings =  new Class[] {Tutor.class, Student.class, Course.class};
        DBUtils.createTables(mappings);
        sessionFactory = DBUtils.createSessionFactory(mappings);
        try {
            long tutorId = initialImport();

            Session session = sessionFactory.openSession();
            Transaction tx = session.beginTransaction();

            Tutor tutor = session.get(Tutor.class, tutorId);
            logger.info("DeletingStudent");
            tutor.setStudent(null);

            tx.commit();
        } finally {
            sessionFactory.close();
        }

    }

    private static long initialImport() {
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();
        Student student = new Student();
        student.setName("student");

        Map<String, Course> courses = new HashMap<>();
        student.setCourses(courses);
        for (int i = 0; i < 5; i++) {
            Course course = new Course();
            course.setName("course" + i);
            session.save(course);
            courses.put(course.getName(), course);
        }

        Tutor tutor = new Tutor("tutor", student);
        session.save(tutor);
        tx.commit();
        session.close();
        return tutor.getId();
    }
}