我该如何使用Hibernate注解标记外键约束?

85

我希望使用Hibernate注解来编写数据库表的模型类。

我有两个表,每个表都有一个主键User和Question。

@Entity
@Table(name="USER")
public class User
{
    @Id
    @Column(name="user_id")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    @Column(name="username")
    private String username;

    // Getter and setter
}

问题表格。

@Entity
@Table(name="QUESTION")
public class Questions extends BaseEntity{

    @Id
    @Column(name="question_id")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;

    @Column(name="question_text")
    private String question_text;

    // Getter and setter
}

我还有一个表格叫做UserAnswer,它从上面两个表中引用了userId和questionId作为外键。

但是我不知道如何在UserAnswer表中引用这些约束条件。

@Entity
@Table(name="UserAnswer ")
public class UserAnswer
{
    @Column(name="user_id")
    private User user;

    //@ManyToMany
    @Column(name="question_id")
    private Questions questions ;

    @Column(name="response")
    private String response;

    // Getter and setter
}

我该如何实现这个?

3个回答

82

@Column 并不是合适的注解。你不想在一个列中存储整个用户或问题。你想要创建实体之间的关联。首先将 Questions 重命名为 Question,因为一个实例代表一个单独的问题,而不是多个问题。然后创建关联:

@Entity
@Table(name = "UserAnswer")
public class UserAnswer {

    // this entity needs an ID:
    @Id
    @Column(name="useranswer_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;

    @ManyToOne
    @JoinColumn(name = "question_id")
    private Question question;

    @Column(name = "response")
    private String response;

    //getter and setter 
}

Hibernate文档解释了这一点。阅读它。还要阅读注释的javadoc。


非常感谢您的回复。在表中创建一个名为useranswer_id的新列是必要的吗?如果我可以将另外两个ID作为组合键,那么是否可能呢? - vikiiii
3
可以实现,但这是不良设计,使用起来很痛苦、困难且效率低下。请做正确的事情,为所有实体分配一个自动生成的单列ID。 - JB Nizet
你好,当我按照这个例子操作时,我遇到了以下异常:对象引用未保存的瞬态实例——在刷新之前保存瞬态实例:com.product.domain.Users。 - Senthil Muthiah
如果您在获取未保存的瞬态实例时出现异常,则需要在服务层添加事务注释。在服务层中,我们调用DAO对象执行任务,并将其返回到顶部的服务层,在相应的方法上,我们需要添加@Transaction注释。 - zameer
我是新手,我想知道,在这个答案中,question_id是如何设置并保存到数据库的,因为现在实体期望整个问题对象。不是吗? - Saurabh Tiwari
显示剩余5条评论

16

有许多答案,所有答案都是正确的。但不幸的是,它们都没有清晰的解释。

以下方法同样适用于非主键映射。

假设我们有一个父表A,其中包含列1,还有另一个表B,其中包含列2,该列引用列1:

@ManyToOne
@JoinColumn(name = "TableBColumn", referencedColumnName = "TableAColumn")
private TableA session_UserName;

在这里输入图片描述

@ManyToOne
@JoinColumn(name = "bok_aut_id", referencedColumnName = "aut_id")
private Author bok_aut_id;

谢谢,这真的很有说明性。 - zod101

2

@JoinColumn(name="reference_column_name") 注解可用于被某个实体引用的类的属性或字段上。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接