'Why is my Entity class inserting two Id's into my table? Spring Boot JPA
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
}
Solution 1:[1]
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
Solution 2:[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
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Oussama ZAGHDOUD |
| Solution 2 |


