0

I have two Entity classes User and UserProfile. The User table has a primary key for the User ID which is a long data type. This User ID is supposed to be the primary key in user_profile as well. User also has email as a column, which I want to be linked to the user_profile also. The issue I am having is that for some reason, a column named id is being inserted into my table when I already have the primary key user_id set in the user_profile table. Does anyone know what I am doing wrong?

User:

import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

@Entity
@Table( name = "users",
        uniqueConstraints = {
                @UniqueConstraint(columnNames = "username"),


        })
@SecondaryTable(name = "user_profile")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)

    private Long id;

    @Column(name = "username")
    @NotBlank
    @Size(max = 20)
    private String username;

    @Column(name = "email", table = "user_profile")
    @NotBlank
    @Size(max = 50)
    @Email
    private String email;

    @NotBlank
    @Size(max = 120)
    private String password;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable( name = "user_roles",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Set<Role> roles = new HashSet<>();
    
    //getter methods
    //setter methods
    }

User_Profile:

import javax.persistence.*;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;

@Entity
@Table(name = "user_profile")
public class UserProfile {

    @Id
    private Long id;
    @OneToOne(fetch = FetchType.LAZY)
    @MapsId
    private User user;

//    @JoinColumn(name = "email")
//    @OneToOne(fetch = FetchType.LAZY)
//    private User email;


    @Column(name = "profile_img") //S3 image Link
    private String profile_img;

    @Column(name = "profile_banner") //S3 image Link
    private String profile_banner;

//getter methods
//setter methods
}

User table: ![enter image description here

User_Profile table: enter image description here

Stephen Aranda
  • 173
  • 2
  • 14

2 Answers2

2

I was not aware of @MapsId, learned something new. A simple search and found following can someone please explain me @MapsId in hibernate?

I tried with dummy code. It looks like we are mixing @SecondaryTable and @MapsId together.

The duplicate column is from SecondaryTable annotation. i don't have full context of requirement here, mostly https://www.baeldung.com/jpa-mapping-single-entity-to-multiple-tables should solve the need. @Oussama ZAGHDOUD also mentioned this in his response.

In summary, use @MapsId when you want to keep two separate entity class for 2 tables and @SecondaryTable combines 2 tables into one entity class. Both acts same way, primary key of one table works as primary key and foreign key of 2nd table.

With @MapsId only I was getting following sql

    Hibernate: create table user_profile (profile_banner varchar(255), profile_img varchar(255), user_user_id bigint not null, primary key (user_user_id))
Hibernate: create table users (user_id bigint generated by default as identity, email varchar(50), password varchar(120), username varchar(20), primary key (user_id))
Hibernate: alter table users add constraint UKr43af9ap4edm43mmtq01oddj6 unique (username)
Hibernate: alter table user_profile add constraint FKqkgvrni6161p23yj2lbp9xxlk foreign key (user_user_id) references users

With @SecondaryTable

Hibernate: create table user_profile (email varchar(50), profile_banner varchar(255), profile_img varchar(255), user_id bigint not null, primary key (user_id))
Hibernate: create table users (user_id bigint generated by default as identity, password varchar(120), username varchar(20), primary key (user_id))
Hibernate: alter table users add constraint UKr43af9ap4edm43mmtq01oddj6 unique (username)
Hibernate: alter table user_profile add constraint FKuganfwvnbll4kn2a3jeyxtyi foreign key (user_id) references users

Entity class will look like below

package com.example.demo.entity;

import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

@Entity
@Table( name = "users",
        uniqueConstraints = {
                @UniqueConstraint(columnNames = "username")
        })
@SecondaryTable(name = "user_profile", pkJoinColumns = @PrimaryKeyJoinColumn(name = "user_id"))
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="user_id")
    private Long userId;

    @Column(name = "username")
    @NotBlank
    @Size(max = 20)
    private String username;

    @Column(name = "email", table = "user_profile")
    @NotBlank
    @Size(max = 50)
    @Email
    private String email;

    @Column(name = "profile_img", table = "user_profile") //S3 image Link
    private String profile_img;

    @Column(name = "profile_banner", table = "user_profile") //S3 image Link
    private String profile_banner;

    @NotBlank
    @Size(max = 120)
    private String password;

    //getter methods
    //setter methods
}
Sachin
  • 51
  • 6
  • Thank you for the link and the help! I have been scratching my head on this, but I saw that they passed a string in MapsId in that link just now and was gonna try that as well. I am getting a red line under "user_id") for some reason. I appreciate your help – Stephen Aranda Apr 02 '22 at 01:27
  • were you able to figure something out? I am still having issues unfortunatley – Stephen Aranda Apr 02 '22 at 08:10
  • @StephenAranda updated answer with working example – Sachin Apr 06 '22 at 18:05
2

You can avoid the usage of SecondaryTable and use just OneToOne and mappedBy and @PrimaryKeyJoinColumn :

@Entity
@Table(@Table( name = "users",
   uniqueConstraints = { @UniqueConstraint(columnNames = "username")  }))
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id")
    Long userId;

    @OneToOne(mappedBy = "user")
    UserProfile userProfile;
    // Other fields
    // getters and setters
}

 @Entity
 @Table(name = "user_profile")
 public class UserProfile {


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id")
    Long userId;

    @OneToOne
    @PrimaryKeyJoinColumn(name = "user_id")
    User user;

    // other fields
    // getters and setters
}

more details here https://www.baeldung.com/jpa-mapping-single-entity-to-multiple-tables

Oussama ZAGHDOUD
  • 1,767
  • 5
  • 15
  • Thanks! Any idea how I can attach the email column that's in my user table and link it so that its a column (not primary key) in user_profile table? – Stephen Aranda Apr 02 '22 at 05:01