JPA - 如何在子表中引用作为复合键一部分的列

时间:2015-12-10 14:03:31

标签: spring hibernate jpa jpa-2.0

如何从复合字段中映射其中一列?

我有两个表格Question和Question_options。

CREATE TABLE `question` (
  `question_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
  `question` varchar(500) NOT NULL,
  PRIMARY KEY (`question_id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=501 DEFAULT CHARSET=utf8;

CREATE TABLE `question_options` (
  `question_id` smallint(5) unsigned NOT NULL,
  `option_id` varchar(3) NOT NULL,
  `option_description` varchar(500) NOT NULL,
  PRIMARY KEY (`question_id`, `option_id`),
  KEY `idx_fk_op_question_id` (`question_id`),
  KEY `idx_fk_op_option_id` (`option_id`),
  CONSTRAINT `fk_op_question_id` FOREIGN KEY (`question_id`) REFERENCES `question` (`question_id`) ON UPDATE CASCADE
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

在Question.java中:

@JoinColumn(name = "question_id", nullable = false)
private List<QuestionOption> questionOptions;

在QuestionOption.java中

@EmbeddedId
private QuestionOptionPK id;

在QuestionOptionPK.java

@Column(name="question_id", insertable=true, updatable=false, unique=true, nullable=false)
private long questionId;

@Column(name="option_id", insertable=true, updatable=false, unique=true, nullable=false, length=3)
private String optionId;

在Question.java中,我指的是复合键(QuestionOptionPK)的一个字段是questionId。

但我得到的错误是这样的:

  

严重:Web应用程序[/ SpringRestCrud]中的Servlet [mvc-dispatcher]抛出了load()异常   org.hibernate.MappingException:实体映射中的重复列:com.mobily.model.QuestionOption列:question_id(应使用insert =“false”update =“false”映射)

2 个答案:

答案 0 :(得分:0)

您需要使用派生身份。

Question.java:

@Entity
public class Question {
    @Id
    @Column(name="question_id")
    private long id;

    @OneToMany(mappedBy="question")
    private List<QuestionOption> questionOptions;

    ...
}

QuestionOption.java:

@Entity
@Table(name="question_options")
public class Question {
    @EmbeddedId
    private QuestionOptionPK id;

    @ManyToOne
    @JoinColumn(name = "question_id")
    @MapsId("questionId") // maps questionId attribute of the embedded ID
    private Question question;

    ...
}

QuestionOptionPK.java:

@Embeddable
public class QuestionOptionPK {
    private long questionId; // corresponds to the PK type of Question

    @Column(name="option_id")
    private String optionId;
}

JPA 2.1规范第2.4.1节讨论了派生身份。

答案 1 :(得分:0)

我改变了我的表结构。我删除了复合primany键,而不是我使用option_id作为主键,现在option_id是一个数字。我解决了。

CREATE TABLE `question` (
  `question_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
 -- `category` varchar(25) NOT NULL,
  `question` varchar(500) NOT NULL,
--  `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`question_id`)
--  KEY `idx_fk_category` (`category`)
 ) ENGINE=InnoDB AUTO_INCREMENT=501 DEFAULT CHARSET=utf8;

CREATE TABLE `question_options` (
  `option_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
  `question_id` smallint(5) unsigned NOT NULL,
  `option_key` varchar(3) NOT NULL, -- It is like a, b, c... .
  `option_description` varchar(500) NOT NULL,
--  `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`option_id`),
  KEY `idx_fk_op_question_id` (`question_id`),
--  KEY `idx_fk_op_option_id` (`option_id`),
  CONSTRAINT `fk_op_question_id` FOREIGN KEY (`question_id`) REFERENCES `question` (`question_id`) ON UPDATE CASCADE
 ) ENGINE=InnoDB AUTO_INCREMENT=601 DEFAULT CHARSET=utf8;