繁体   English   中英

两个类之间具有多个关联的休眠问题

[英]Hibernate problems with multiple associations between two classes

我在Playframework 1.2.4中使用了Hibernate。

我有两节课:考试和问题。 问题始终具有引用考试的属性。 考试总是有一个属性指向一个名为specialQuestion的问题,一个属性指向一个问题集合。

在此处输入图片说明

我的目标是创建一个涉及每个问题的特殊考试。 在创建考试时,我会创建一个特殊问题。 该问题已经很好地创建并保留在数据库中, 检查也保留了,但是在没有引用特殊问题的情况下,匹配列用空值填充。

我不确定注解。 问题是什么 ?

此静态方法返回默认的特殊问题

public static Question specialQuestion(Examination examination) {
        Question question = new Question();
        question.examination = examination;
        /* Other attributes affectations */
        return question;
}

在这里,它创建了考试,影响了specialQuestion属性并持久化了对象:

Examination examination = new Examination();
examination.specialQuestion = Question.specialQuestion(examination);
examination.save();

班级考试包含以下属性:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "examination", fetch = FetchType.LAZY)
    public Set<Question> questions = new HashSet<Question>();

@OneToOne(cascade= CascadeType.ALL, mappedBy = "examination")
    public Question specialQuestion;

课程问题包含:

@ManyToOne
@OneToOne
public Examination examination;

编辑:

如果如果删除mappedBy在specialQuestion @OneToOne注释和@OneToOne在问类考试的注释,我得到的错误:我无法加载实体考试了。

这是DDL的重要部分:

CREATE TABLE `question` (
  `questionId` bigint(20) NOT NULL AUTO_INCREMENT,
  `examination_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`questionId`),
  KEY `FKBE5CA006E00B1456` (`examination_id`)
) ENGINE=MyISAM AUTO_INCREMENT=204 DEFAULT CHARSET=latin1;

CREATE TABLE `examination` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `specialQuestion` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=latin1;

您不能将@ManyToOne@OneToOne添加到同一属性,因为Hibernate需要知道哪一个是正确的。

而且,由于拥有方是“ Question ”,Hibernate应该如何知道哪个问题是特殊问题? 从数据库的角度考虑:将关系存储在问题表中,您最终将获得引用同一考试的多个问题。 如果这些是无序的(一组), 将如何根据可用数据确定特殊问题? 由于您无法做到这一点,Hibernate也不会做到这一点。

为了解决这个问题,您需要使Examination成为specialQuestion一面,并且可能也只有一个单向关系,即,您不将其映射到Question (删除mappedBy并添加一列作为对检查表的引用)。

您可以通过创建一个额外的实体来实现此目的,该实体实际上将充当考试和问题之间的“连接”实体。 这将使您可以灵活地将同一问题分配给多个考试,并为每个考试独立设置特殊问题。

因此,对于包含相同问题但具有不同特殊问题的两次考试,表格如下所示:

╔════════════════════════════════╗
║ exam_id question_id is_special ║
╠════════════════════════════════╣
║ 1        1          0          ║
║ 1        2          0          ║
║ 1        3          1          ║
║ 1        4          0          ║
║ 1        5          0          ║
║ 2        1          1          ║
║ 2        2          0          ║
║ 2        3          0          ║
║ 2        4          0          ║
║ 2        5          0          ║
╚════════════════════════════════╝

这三个实体的基本映射如下:

@Entity
public class Examination{

    @Id
    private int id;

    @OneToMany(mappedBy = "examination")
    private Set<ExaminationQuestion> examQuestions;

    public Set<Question> getNormalQuestions(){
        Set<Question> questions = new HashSet<>();

        for(ExaminationQuestion eq: examQuestions){
            if(! eq.getQuestion.isSpecialQuestion()){
                questions.add(eq.getQuestion());
            }
        }

        return questions;
    }

    public Question getSpecialQuestion(){
        Question specialQuestion = null;

        for(ExaminationQuestion eq: examQuestions){
            if(eq.getQuestion.isSpecialQuestion()){
                specialQuestion = eq.getQuestion();
                break;
            }
        }

        return specialQuestion; 
    }
}

@Entity
public class ExaminationQuestion{

    @Id
    private int id;

    @ManyToOne
    private Examination examination;

    @ManyToOne
    private Questions question;

    private boolean specialQuestion;
}

@Entity
public class Question{

    @Id
    private int id;

    @OneToMany(mappedBy = "question")
    private Set<ExaminationQuestion> examQuestions;
}

我根据托马斯的答案找到了一个解决方案:

在不修改架构的情况下,这些类会变成

课堂问题:

@OneToOne
@JoinColumn(name = "examination_id")
public Examination examination;

班级考试:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "examination", fetch = FetchType.LAZY)
public Set<Question> questions = new HashSet<Question>();

@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "specialQuestion")
public Question specialQuestion;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM