使用Map使用Hibernate Annotations创建主键

时间:2009-09-01 07:29:51

标签: java hibernate

我不太习惯ORM映射,来自PHP背景。我正在尝试在一系列问题和他们可能的答案之间建立联系,以及该集合中的正确答案。

我正在尝试创建一个可以查询相应Answers的Question对象,但不幸的是,我制作的最好的Java类会导致重复(技术上不必要的)字段。

理想的数据库模式如下所示:

CREATE TABLE `question` (
    `question_id`           BIGINT AUTO_INCREMENT,
    `questionText`          VARCHAR(255),
    `correctAnswerIndex`    INT,
    PRIMARY KEY (`question_id`),
    INDEX correct_answer_idx (`question_id`, `correctAnswerIndex`),
    FOREIGN KEY `correct_answer_idx` (`question_id`, `correctAnswerIndex`) REFERENCES answer(`question_id`, `index`)
);

CREATE TABLE `answer` (
    `question_id`           BIGINT,
    `index`                 INT,
    `answerText`            VARCHAR(32),
    PRIMARY KEY (`question_id`, `index`),
    INDEX question_idx (`question_id`),
    FOREIGN KEY `question_idx` (`question_id`) REFERENCES `question`(`question_id`)
);

不幸的是,我要列出的Java类将为Map创建一组额外的(question_id,index)。如果我可以使用字段作为主键,这是可以接受的。 另外,当使用当前id时,correctAnswer将生成一个不必要的Question参考。

以下是我用来创建结构的类:

@javax.persistence.Entity
@javax.persistence.Table(name = "question")
public class Question implements Serializable {
    @Id
    @TableGenerator(name = "question_seq", table = "hibernate_sequences", allocationSize = 5)
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "question_seq")
    private Long id;

    @ManyToOne(optional = false)
    @JoinColumns({
        @JoinColumn(name = "correct_answer_index", referencedColumnName = "index"),
        @JoinColumn(name = "correct_answer_question", referencedColumnName = "question_id")
    })
    private Answer correctAnswer;

    @CollectionOfElements(fetch = FetchType.LAZY)
    @JoinTable(name = "answer", joinColumns = @JoinColumn(name = "question_id"))
    @MapKey(columns = { @Column(name = "index") })
    private Map<Integer, Answer> answers = new HashMap<Integer, Answer>();

    @Column(length = 255)
    private String questionText;

    //... Accessors, Equals(), Hashcode(), etc...
}

@javax.persistence.Entity
@javax.persistence.Table(name = "answer")
@AssociationOverrides( {
    @AssociationOverride(name = "pk.index", joinColumns = @JoinColumn(name = "index")),
    @AssociationOverride(name = "pk.question", joinColumns = @JoinColumn(name = "question_id")),
})
public class Answer implements Serializable {
    @EmbeddedId
    private AnswerPK pk = new AnswerPK();

    @Column(length = 32)
    private String answerText;

    //... Accessors, Equals(), Hashcode(), etc...
}

@Embeddable
public class AnswerPK implements Serializable {
    @ManyToOne
    @ForeignKey(name = "answer_for_question")
    Question question;

    Integer index;

    //... Accessors, Equals(), Hashcode(), etc...
}

非常感谢任何帮助或建议。

1 个答案:

答案 0 :(得分:0)

请勿使用MapList作为答案,并使用index作为排序顺序。同时为每个答案分配一个唯一的ID(就像问题一样),而不是使用复合键。 Hibernate将在问题对象(而不是索引)中使用此ID。

此设计的唯一缺点是您必须确保正确答案实际上是此问题的答案列表中的项目。从积极的方面来说,这将使您的代码和映射更加简单。