Hibernate Composite Primary Keys with @EmbeddedId
annotation
The @EmbeddedId
annotation in Java Persistence API (JPA) is used for managing composite primary keys. This article will thoroughly explore its use @EmbeddedId
, explaining its functions, advantages, and limitations, illustrated with an example from a project management system.
Hi, this is Paul, and welcome to this article, we explore how to create a Hibernate Entity with composite primary keys with @EmbeddedId
annotation.
Purpose of @EmbeddedId
@EmbeddedId
is employed to denote a composite primary key that comprises multiple columns, useful in scenarios where a single column does not uniquely identify a record. The annotation indicates that a class will be embedded as an entity's identifier, representing this composite primary key.
How @EmbeddedId Works
To grasp the functionality of @EmbeddedId
, let's analyze a practical example involving Project
and ProjectMember
entities for tables:
CREATE TABLE projects
(
id BIGSERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
CREATE TABLE project_members
(
user_name VARCHAR(255),
project_id BIGINT,
PRIMARY KEY (user_name, project_id),
FOREIGN KEY (project_id) REFERENCES projects (id)
);
Definition: An @Embeddable
class is created including all fields of the composite key. In our case, the class ProjectMemberId
includes fields username
and projectId
.
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serializable;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class ProjectMemberId implements Serializable {
@Column(name = "user_name")
private String username;
@Column(name = "project_id")
private Long projectId;
}
Embedding: In the ProjectMember
entity, instead of using a simple @Id
, @EmbeddedId
is used to embed the ProjectMemberId
class. This composite ID is linked to the corresponding fields in the ProjectMember
entity.
import jakarta.persistence.*;
import lombok.*;
@Entity
@Getter
@Setter
@Builder
@ToString(exclude = "project")
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "project_members")
public class ProjectMember {
@EmbeddedId
private ProjectMemberId id;
@ManyToOne
@JoinColumn(name = "project_id", insertable = false, updatable = false)
private Project project;
}
@EmbeddedId
is used to embedProjectMemberId
, linking it to the project through the composite key.@ManyToOne
and@JoinColumn
define the association withProject
, withinsertable
andupdatable
set tofalse
to prevent changes through this entity.
Project Entity:
- Utilizes
@Id
and@GeneratedValue
to manage the uniqueness of each project. - Includes the field
name
and an@OneToMany
association withProjectMember
, allowing a project to have multiple members.
import jakarta.persistence.*;
import lombok.*;
import java.util.Set;
@Entity
@Getter
@Setter
@Builder
@ToString(exclude = "members")
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "projects")
public class Project {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "name", nullable = false)
private String name;
@OneToMany(mappedBy = "project")
private Set<ProjectMember> members;
}
Benefits and Limitations
As noted, using @EmbeddedId
offers flexibility in key design and supports database normalization. However, it also adds complexity to the model and can lead to performance issues if not optimally used.
Conclusion
@EmbeddedId
is a powerful tool in JPA for managing entities with composite primary keys. Careful schema design and performance testing are recommended to make the most of using @EmbeddedId
in your applications.
Thank you for reading until the end. Before you go:
- Please consider clapping and following the writer! 👏
- Follow us on Twitter(X), LinkedIn