используя карту для создания первичных ключей, используя аннотации Hibernate - PullRequest
0 голосов
/ 01 сентября 2009

Я не слишком привык к ORM-отображению, пришедшему из PHP-фона. Я пытаюсь установить связь между серией вопросов и их возможными ответами, а также правильным ответом из этого набора.

Я пытаюсь создать объект 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, которые я собираюсь перечислить, создадут дополнительный набор (question_id, index) для карты. Это было бы приемлемо, если бы я мог использовать поля в качестве первичного ключа. Кроме того, correctAnswer сгенерирует ненужную ссылку на Вопрос при использовании текущего идентификатора.

Ниже приведены классы, которые я использую для создания структуры:

@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 голосов
/ 01 сентября 2009

Не используйте Map, а List для ответов и используйте index в качестве порядка сортировки. Также присвойте каждому ответу уникальный идентификатор (как и в вопросах) вместо использования составного ключа. Hibernate будет использовать этот идентификатор в объекте вопроса (вместо индекса).

Единственный недостаток этого дизайна заключается в том, что вы должны убедиться, что правильный ответ на самом деле является пунктом в списке ответов на этот вопрос. С положительной стороны, это сделает ваш код и отображение намного проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...