1

I have 2 entity classes: Student is parent and Address is child with one to one mapping:

Student

student_id int (pk), roll_no int (pk), name varchar

Address

student_id (pk, fk), country varchar

student_id in address entity is both the primary key and foreign key

Student Entity class:

@Entity
@Table(name = "student")
public class Student {

    @EmbeddedId
    private StudentPrimaryKey studentPrimaryKey;

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

    @OneToOne(mappedBy = "student", cascade = CascadeType.ALL)
    private Address address;
    ........

StudentPrimaryKey class:

@Embeddable
public class StudentPrimaryKey implements Serializable{

    @Column(name = "student_id")
    private long id;

    @Column(name = "roll_no")
    private long rollNo;
    ....

Address Entity class:

@Entity
@Table(name = "address")
public class Address {

    @Id
    @Column(name  = "student_id")
    private long id;

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

    @OneToOne
    @JoinColumn(name = "student_id")
    @MapsId
    private Student student;
    .......

Exception is - org.hibernate.AnnotationException: Implicit column reference in the @MapsId mapping fails, try to use explicit referenceColumnNames

I understand that there are 2 primary key columns in parent table and @MapsId is unable to figure out which one it should map the foreign key to in parent table, so I tried using referencedColumnName in Address Entity -

@OneToOne
    @JoinColumn(name = "student_id", referencedColumnName = "student_id")
    @MapsId
    private Student student; 

New Exception: Unable to find column reference in the @MapsId mapping: roll_no

From above, it is trying to find the missingcolumn from composite primary key in parent class, but we don't need this column.

[Hibernate - Composite Primary Key contains Foreign Key

This is one of the link that shares the same problem which says JPA/ hibernate doesn't allow partial composite primary keys to be the foreign keys.

Please provide your support to help me handle this.

1 Answer 1

1

If a Student can be uniquely identified only by a combination of both its id and rollNo, then the corresponding Address also requires both fields in its primary key/foreign key and should look like this (note it uses the same @EmbeddedId, StudentPrimaryKey):

@Entity
@Table(name = "address")
public class Address {

    @EmbeddedId
    private StudentPrimaryKey primaryKey;

    @MapsId
    @JoinColumns({
        @JoinColumn(name="student_id", referencedColumnName="student_id"),
        @JoinColumn(name="roll_no", referencedColumnName="roll_no") })
    @OneToOne
    Student student;

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

    ...

You will also need to add the roll_no column to the address table.

If a Student can be uniquely identified by simply its id (as implied by your Address mappings), then you can remove rollNo from the primary key and use a simple @Id mapping on id and @Basic mapping on rollNo.

Sign up to request clarification or add additional context in comments.

4 Comments

This means there is no way in which hibernate can support my use case even if the 'id' column of student class has uniqueness property in database (values won't be repeated for this column) ?
@Kiran If the id column is truly unique, you should be able to use a simple @Id annotation (instead of the current @EmbeddedId). You just need to make sure rollNo is not null before you save to your database (so you do not violate the database's primary key constraint). Have you tried that?
This works, but I don't think it as an ideal way to design entity class. Database Table and Entity classes need to be aligned with each other.
@Kiran Not necessarily. The @Id annotated field need only uniquely identify an entity. There is no requirement that it correspond to the entity's table's primary key as defined by the DDL. You can use any column (or set of columns) in the table that is guaranteed to be non-null and unique.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.