【问题标题】:JPA - How can I refer a column which is part of compound key in sub tableJPA - 如何在子表中引用作为复合键一部分的列
【发布时间】:2015-12-10 14:03:30
【问题描述】:

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

我有两个表 Questions 和 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" 进行映射)

【问题讨论】:

    标签: spring hibernate jpa jpa-2.0


    【解决方案1】:

    您需要使用派生的身份。

    问题.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 节中讨论。

    【讨论】:

    • 嗨,布赖恩,感谢您的解决方案,但小问题。我改变的和你在这里说的一样。但它变成了两个表之间的关系是双向的。所以我一次又一次地递归地获取相同的数据。
    • 我不明白你现在的问题是什么。或许你可以再给我一些细节?
    【解决方案2】:

    我改变了我的表结构。我删除了复合主键,而不是使用 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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-13
      • 2020-05-15
      • 2012-09-22
      • 2021-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-19
      相关资源
      最近更新 更多