How can I mark a foreign key constraint using Hibernate annotations?
Asked Answered
V

3

86

I am trying to use Hibernate annotation for writing a model class for my database tables.

I have two tables, each having a primary key User and 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
}

Question Table.

@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
}

And I have one more table, UserAnswer, which has userId and questionId as foreign keys from the above two tables.

But I am unable to find how I can reference these constraints in the UserAnswer table.

@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
}

How can I achieve this?

Verlie answered 15/3, 2013 at 7:14 Comment(0)
P
83

@Column is not the appropriate annotation. You don't want to store a whole User or Question in a column. You want to create an association between the entities. Start by renaming Questions to Question, since an instance represents a single question, and not several ones. Then create the association:

@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 
}

The Hibernate documentation explains that. Read it. And also read the javadoc of the annotations.

Photocathode answered 15/3, 2013 at 7:31 Comment(10)
Thank you so much for replying. Is it necessary to create a new column in the table as useranswer_id ? Is it possible if i can make the other two ids as composite keys?Verlie
It is possible, but it's bad design, painful, hard to use, and inefficient. Do the right thing, and assign an autogenerated, single-column ID to all your entities.Photocathode
@JB_Nizet I dont mind adding a id column to an entity . But do i need to add a column in table also? I mean oracle database.Verlie
Yes, of course. Where would Hibernate store the ID of the entity if the ccorresponding column doesn't exist?Photocathode
I asked my team lead. I can't add the column . I have to make them composite keys. I tried using @ EmbeddedId and @ Embeddable . But i get a hibernate exceptionVerlie
org.hibernate.AnnotationException: No identifier specified for entity . It can't find user_idVerlie
You must use the MapsId annotation. See docs.oracle.com/javaee/6/api/javax/persistence/MapsId.html, it has an example.Photocathode
Hi When i follow this example, i got the following exception bject references an unsaved transient instance - save the transient instance before flushing: com.product.domain.UsersRecorder
if you are getting unsaved transient instance as exception then you need to add transaction annotation at service level.in service layer where we call the DAO objects to perform the task and it will return to the service layer on the top of the respected method,we need to mention @Transaction.Pietje
I am new to this thing and I am wondering, In this answer, how is the question_id set and saved to DB, because now the entity expects the whole question object. Isn't it?Abeokuta
P
17

There are many answers and all are correct as well. But unfortunately none of them have a clear explanation.

The following works for a non-primary key mapping as well.

Let's say we have parent table A with column 1 and another table, B, with column 2 which references column 1:

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

Enter image description here

@ManyToOne
@JoinColumn(name = "bok_aut_id", referencedColumnName = "aut_id")
private Author bok_aut_id;
Preposterous answered 16/9, 2018 at 17:16 Comment(1)
Thank you this was really illustrative.Apulia
I
2

@JoinColumn(name="reference_column_name") annotation can be used above that property or field of class that is being referenced from some other entity.

Intuitional answered 5/2, 2016 at 12:6 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.