2

I am new to Hibernate. I am working on two entities as follows:

Entity 1 is as follows:

@Entity
@Table(name = "vm_user")
public class VmUser implements Serializable {

    private static final long serialVersionUID = 1L;

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

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

    @Column(name = "created_date")
    private Instant createdDate;

    @Column(name = "last_modified_date")
    private Instant lastModifiedDate;

    @OneToOne
    @JoinColumn(unique = true)
    private User user;             <--- HOW WILL I DENOTE THIS PRIMARY KEY OF VMUSER ENTITY ?

In the associated table in mysql i.e. vm_user, user_id is both primary key as well as foreign key which refers to id of user table associated with User entity.

Entity 2 is as follows:

@Entity
@Table(name = "my_entity")
public class MyEntity implements Serializable {

    private static final long serialVersionUID = 1L;

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

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

    @Column(name = "created_date")
    private Instant createdDate;

    @Column(name = "last_modified_date")
    private Instant lastModifiedDate;

    @ManyToOne
    private A a;

    @OneToOne
    @JoinColumn(unique = true)
    private B b;

In the associated table in mysql i.e. my_entity, primary key is a combination of id of a and id of b. I am not getting how to denote this in Hibernate entity MyEntity.

Regarding the same, I have gone through a few posts: Hibernate foreign key as part of primary key and JPA & Hibernate - Composite primary key with foreign key, but no getting idea how to do these two ?

Joy
  • 4,197
  • 14
  • 61
  • 131

3 Answers3

3

The solution is @MapsId

For example

@Entity
@Table(name = "vm_user")
public class VmUser implements Serializable {

    @Id
    @Column(name = "user_id")    
    private Integer id;

    @MapsId
    @OneToOne
    private User user;  

You can also remove the @JoinColumn(unique = true) because @Id makes it unique already.

public class MyEntityPk implements Serializable {

   private Integer aId;
   private Integer bId;

   // IMPORTANT: Override equals() and hashCode()
}


@IdClass(MyEntityPk.class)
@Entity
@Table(name = "my_entity")
public class MyEntity implements Serializable {

    @Id
    private Integer aId;
    @Id
    private Integer bId;

    @MapsId("aId")
    @ManyToOne
    private A a;

    @MapsId("bId")
    @OneToOne
    private B b;

Please find more information in the Hibernate documentation https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#identifiers-derived

Simon Martinelli
  • 34,053
  • 5
  • 48
  • 82
  • 2
    you declare id as primary key, i think OP want to make user_id as primiary key – GolamMazid Sajib May 02 '20 at 06:55
  • I added the ColumnMapping – Simon Martinelli May 02 '20 at 07:02
  • @SimonMartinelli Would you please suggest an approach for entity 2 as well ? – Joy May 02 '20 at 07:06
  • I add the solution for second entity as well. Important is that the PK class must implement Serializable and override equals and hashCode – Simon Martinelli May 02 '20 at 07:42
  • @SimonMartinelli Yeah. One small doubt in your solution. Don't you have to add any mapping like which id the attribute mapping to ? I mean here we have two Ids annotations and two MapIds annotations. So how would it figure out aId corresponds to A or B, same for bId ? Please correct me, if I am wrong. – Joy May 02 '20 at 07:46
2

You need to use @EmbeddedId and @MapsId ,

@Entity
@Table(name = "vm_user")
public class VmUser implements Serializable {
   @Id
    @Column(name = "user_id")    
    private Integer id;

    @MapsId("user_id")
    @OneToOne
    private User user;  
}

You can do the same thing for MyEntity as below,

@Embeddable
class BKey {
  private int aId;
  private int bId;
}


@Entity
@Table(name = "my_entity")
public class MyEntity implements Serializable {

    @EmbeddedId
    private BKey primaryKey;

    @MapsId("aId")
    @ManyToOne
    private A a;

    @MapsId("bId")
    @OneToOne
    @JoinColumn(unique = true)
    private B b;
}
Vikas
  • 6,868
  • 4
  • 27
  • 41
  • @code-mode I don't have any vm_user column. So I guess vm_user column to be omitted from your answer. Please correct me, if I am wrong. And also, regarding entity 2, would you please suggest an approach ? – Joy May 02 '20 at 07:00
  • Add id for `vm_user` , `vm_user_id`. You can do the same thing for `MyEntity` – Vikas May 02 '20 at 07:03
  • @code-mode, for vm_user table user_id is the primary key. – Joy May 02 '20 at 07:03
  • 1
    Update the answer. I hope it helps. – Vikas May 02 '20 at 07:12
  • @code-mode, one small doubt. In MapsId annotation, "aId" and "bId" refers to the attributes of the class BKey right ? It may not be necessarily same as the actual column names of underlying table. To do that I have to add annotation Column(name = "a_id") and Column(name = "b_id") above those attributes in the class BKey I guess. Please correct me, if I am wrong. – Joy May 02 '20 at 07:36
  • You need to add column annotation if the column name and property name are different. – Vikas May 02 '20 at 07:40
0

VM Users class

public class VmUser implements Serializable {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long id;

@OneToOne
@JoinColumn(name="ID")
private Users user;

Users class

public class Users implements Serializable {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long id;

@OneToOne(mappedBy="user")
private VmUser vmUser;

A class

@Entity
public class A implements Serializable {

@Id
private long id;

@OneToMany(mappedBy="a")
private List<MyEntity> myEntitys;

B Class

@Entity
public class B implements Serializable {

@Id
private long id;

@OneToMany(mappedBy="b")
private List<MyEntity> myEntitys;

MyEntity class

@Entity
public class MyEntity implements Serializable {
private static final long serialVersionUID = 1L;

@EmbeddedId
private MyEntityPK id;


@ManyToOne
@JoinColumn(name="ID1")
private A a;

@ManyToOne
@JoinColumn(name="ID2")
private B b;

MyEntityPK class

@Embeddable
public class MyEntityPK implements Serializable {

@Column(insertable=false, updatable=false)
private long id1;

@Column(insertable=false, updatable=false)
private long id2;
Mohit
  • 126
  • 1
  • 9