【问题标题】:hibernate @OneToMany join table not being created未创建休眠@OneToMany 连接表
【发布时间】:2021-01-20 12:49:44
【问题描述】:

我有两个表 Quiz 和 Question,我想将它们与 @OneToMany 关系关联,但连接表未在 mysql 工作台数据库中创建。以下是实体:

测验.java

@Entity
public class Quiz {
    
        // attributes :
    private Integer idQuiz;
    private String quizTopic;

   @OneToMany
   @JoinColumn(name = "quiz_Id")
   private List<Question> questions;

        // constructors 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "quiz_Id")
    public Integer getIdQuiz() {
        return idQuiz;
    }

    @Column(name = "quiz_topic")
    public String getQuizTopic() {
        return quizTopic;
    }
//setters
}

Question.java

@Entity
public class Question {

    // attributes
    private Integer idQuestion;
    private String value;
    private String op1;
    private String op2;
    private String op3;
    private String correctAnswer;

// constructors  

// Getters :
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "question_Id")
public Integer getIdQuestion() {
    return idQuestion;
}

@Column(name = "question_value")
public String getValue() {
    return value;
}

@Column(name = "question_op1")
public String getOp1() {
    return op1;
}

@Column(name = "question_op2")
public String getOp2() {
    return op2;
}

@Column(name = "question_op3")
public String getOp3() {
    return op3;
}

@Column(name = "question_op4")
public String getCorrectAnswer() {
    return correctAnswer;
}
 //setters
}

没有创建外键

这是我跑步后得到的结果

    Hibernate: create table question (question_id integer not null auto_increment, question_op4 varchar(255), question_op1 varchar(255), question_op2 varchar(255), question_op3 varchar(255), question_value varchar(255), primary key (question_id)) engine=InnoDB
Hibernate: create table quiz (quiz_id integer not null auto_increment, quiz_topic varchar(255), primary key (quiz_id)) engine=InnoDB

application.properties:

spring.main.web-application-type=none
spring.application.ui.title=Quiz
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/quiz?createDatabaseIfNotExist=true&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=justpass
spring.jpa.show-sql=true

【问题讨论】:

  • 你确定没有表Quiz_Question?能否请您也显示应用程序属性文件。
  • 没有表Quiz_Question

标签: java mysql spring-boot hibernate jpa


【解决方案1】:

注释

@OneToMany
private ArrayList<Question> questions;

不会创建连接表。它应该在 Quiz 表的 Question 表中创建一个外键。这个外键与

private Integer idQuestion;

列。

【讨论】:

  • 正如documentation 中所述:当使用单向@OneToMany 关联时,Hibernate 会在两个连接实体之间使用链接表。
【解决方案2】:

对于您的解决方案,这取决于您要建立单向还是双向@OneToMany 关系。如果你想要一个单向的一对多关系,你必须定义一个@JoinColumn 来告诉 Hibernate 它应该在相关表中创建一个具有给定名称的外键。大多数情况下,单向的一对多关系是最简单且充分的方法。

单向

@OneToMany
@JoinColumn(name = "quiz_id")
private List<Question> questions;

Hibernate 将在问题表中创建名为“quiz_id”的外键。

在双向情况下,我们可以从问题中访问测验,反之亦然,从测验中访问问题。在这种情况下,您将必须在子类中定义代表父类的变量。例如,如果测验是父类,您将定义注释。 @OneToMany(mappedBy = "quiz")。除此之外,您还必须将问题定义为@ManyToOne 方。总而言之:

双向

测验.java:

@OneToMany(mappedBy = "quiz")
private List<Question> questions;

Question.java

@ManyToOne(fetch = FetchType.LAZY)
private Quiz quiz;

由于性能原因,您可能希望将 fetch 类型定义为惰性(过去我什至遇到了一些溢出错误,没有惰性方法)。

请记住,如果您将双向映射与 jackson 等序列化库一起使用,则在从/到 JSON 进行反序列化/序列化时会遇到JSON infinite recursion problem。在这种情况下,您将希望使用 @JsonIdentityInfo 仅序列化 id 而不是完整实体(这将导致无限递归)或 @JsonIgnore 分别 @JsonManagedReference@JsonBackReference 不序列化实体的子依赖项.

我还建议使用属性cascade 定义级联类型,orphanRemoval 用于在处理关系时删除实体,但我不想用不相关的信息来破坏我的答案。

【讨论】:

  • 我只想建立一个单向关系,我完全按照你告诉我的做了,但是由于某些原因,创建了表但没有外键
  • 所以你使用了@JoinColumn注解?如果是这样,请更新您的问题,因为这不清楚。
【解决方案3】:

您尝试在 Quiz 实体中混合访问策略看起来很可疑。

正如documentation中所述:

作为 JPA 提供者,Hibernate 可以自省实体属性(实例字段)或访问器(实例属性)。 默认情况下,@Id 注释的放置提供了默认访问策略。当放置在一个字段上时,Hibernate 将假定基于字段的访问。当放置在标识符 getter 上时,Hibernate 将使用基于属性的访问。

所以,不要这样:

@OneToMany
@JoinColumn(name = "quiz_Id")
private List<Question> questions;

@OneToMany@JoinColumn(name = "quiz_Id") 注释放在适当的getter 上:

@OneToMany
@JoinColumn(name = "quiz_Id")
public List<Question> getQuestions() {
   return questions;
}

然后尝试通过像这样设置spring.jpa.hibernate.ddl-auto 属性来重新创建您的架构:

spring.jpa.hibernate.ddl-auto=create

【讨论】:

    猜你喜欢
    • 2017-07-30
    • 2010-11-21
    • 1970-01-01
    • 2016-09-07
    • 2013-07-01
    • 1970-01-01
    • 2011-07-30
    • 1970-01-01
    相关资源
    最近更新 更多