JPA + Hibernate - @EmbeddedId Example
February 15, 2023
On this page, we will learn to use JPA @EmbeddedId
annotation in our Hibernate application.
1. The
@EmbeddedId
denotes a composite primary key that is an embeddable class. The composite primary key is the combination of database table columns that behave jointly as primary key. We need to create a @Embeddable
class whose properties correspond to composite primary key of the database table. The @EmbeddedId
is applied to a persistent field, property of an entity class or mapped super class to achieve composite primary key.
2. In an entity, there must be only one
@EmbeddedId
annotation. The @Id
annotation cannot be used in the presence of @EmbeddedId
.
3. We can use
@AttributeOverride
annotation to override column mappings declared within the @Embeddable
class.
4. We can use
@MapsId
annotation with @EmbeddedId
annotation to specify a derived primary key.
1. Using @EmbeddedId Annotation
Find an embeddable classNameId
with two fields firstName and lastName. Here NameId
is representing a composite primary key with columns first_name and last_name in database table.
@Embeddable public class NameId { @Column(name = "first_name") private String firstName; @Column(name = "last_name") private String lastName; ------ }
NameId
as an id. Use @EmbeddedId
to make nameId field as an id.
@Entity @Table(name="person") public class Person { @EmbeddedId private NameId nameId; @Column(name = "person_city") private String city; ------ }
@Id
cannot be used with @EmbeddedId
annotation and @EmbeddedId
can be used only one time.
2. Using @EmbeddedId with @AttributeOverride
The@EmbeddedId
can be used with @AttributeOverride
annotation in an entity when composite primary key column names are different from embeddable class.
The
@AttributeOverride
annotation is used to override attributes of embeddable class. Our embeddable class NameId
represents database table columns as first_name and last_name. In employee
table, column names are emp_first_name and emp_last_name. We can use NameId
for Employee
entity by overriding the attributes as following.
@Entity @Table(name = "employee") public class Employee { @EmbeddedId @AttributeOverrides({ @AttributeOverride( name = "firstName", column = @Column(name = "emp_first_name") ), @AttributeOverride( name = "lastName", column = @Column(name = "emp_last_name") ) }) private NameId nameId; ------ }
3. Complete Example
1. Technologies Used1. Java 19
2. Hibernate 6
3. Jakarta Persistence API 3
4. MySQL 5.5
2. MySQL Database
CREATE TABLE `person` ( `first_name` VARCHAR(50) NOT NULL, `last_name` VARCHAR(50) NOT NULL, `person_city` VARCHAR(50) NOT NULL, `landline_num` VARCHAR(20) NOT NULL, `mobile_num` VARCHAR(20) NOT NULL, PRIMARY KEY (`first_name`, `last_name`) ) CREATE TABLE `employee` ( `emp_first_name` VARCHAR(50) NOT NULL, `emp_last_name` VARCHAR(50) NOT NULL, `emp_company` VARCHAR(50) NOT NULL, `landline_num` VARCHAR(50) NOT NULL, `mobile_num` VARCHAR(50) NOT NULL, PRIMARY KEY (`emp_first_name`, `emp_last_name`) )
<dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>6.1.6.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>6.0.0.Alpha7</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.32</version> </dependency> </dependencies>
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="https://jakarta.ee/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd" version="3.0"> <persistence-unit name="com.concretepage"> <description>Procedure Demo</description> <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /> <property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver" /> <property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost/concretepage" /> <property name="jakarta.persistence.jdbc.user" value="root" /> <property name="jakarta.persistence.jdbc.password" value="cp" /> </properties> </persistence-unit> </persistence>
HibernateUtil.java
package com.concretepage.util; import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.Persistence; public class HibernateUtil { private static final EntityManagerFactory emFactory; static { emFactory = Persistence.createEntityManagerFactory("com.concretepage"); } public static EntityManager getEntityManager(){ return emFactory.createEntityManager(); } }
package com.concretepage.entity; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; @Embeddable public class NameId { @Column(name = "first_name") private String firstName; @Column(name = "last_name") private String lastName; public NameId() {} public NameId(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } // setters and getters }
package com.concretepage.entity; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; @Embeddable public class ContactNumber { @Column(name = "landline_num") private String landline; @Column(name = "mobile_num") private String mobile; public ContactNumber() {} public ContactNumber(String landline, String mobile) { this.landline = landline; this.mobile = mobile; } // setters and getters }
package com.concretepage.entity; import jakarta.persistence.Column; import jakarta.persistence.Embedded; import jakarta.persistence.EmbeddedId; import jakarta.persistence.Entity; import jakarta.persistence.Table; @Entity @Table(name="person") public class Person { @EmbeddedId private NameId nameId; @Embedded private ContactNumber contactNum; @Column(name = "person_city") private String city; public Person() {} public Person(NameId nameId, ContactNumber contactNum, String city) { this.nameId = nameId; this.contactNum = contactNum; this.city = city; } // setters and getters }
package com.concretepage.entity; import jakarta.persistence.AttributeOverride; import jakarta.persistence.AttributeOverrides; import jakarta.persistence.Column; import jakarta.persistence.Embedded; import jakarta.persistence.EmbeddedId; import jakarta.persistence.Entity; import jakarta.persistence.Table; @Entity @Table(name = "employee") public class Employee { @EmbeddedId @AttributeOverrides({ @AttributeOverride( name = "firstName", column = @Column(name = "emp_first_name") ), @AttributeOverride( name = "lastName", column = @Column(name = "emp_last_name") ) }) private NameId nameId; @Embedded private ContactNumber contactNum; @Column(name="emp_company") private String company; public Employee() {} public Employee(NameId nameId, ContactNumber contactNum, String company) { this.nameId = nameId; this.contactNum = contactNum; this.company = company; } // setters and getters }
package com.concretepage; import com.concretepage.entity.ContactNumber; import com.concretepage.entity.Employee; import com.concretepage.entity.NameId; import com.concretepage.entity.Person; import com.concretepage.util.HibernateUtil; import jakarta.persistence.EntityManager; public class Main { public static void main(String[] args) { EntityManager entityManager = HibernateUtil.getEntityManager(); entityManager.getTransaction().begin(); NameId personName = new NameId("Mahesh", "Sharma"); ContactNumber personContactNum = new ContactNumber("121212", "3232323232"); Person person = new Person(personName, personContactNum, "Bangalore"); NameId empName = new NameId("Ajeet", "Bharati"); ContactNumber empContactNum = new ContactNumber("212121", "4343434343"); Employee employee = new Employee(empName, empContactNum, "ABC"); entityManager.persist(person); entityManager.persist(employee); entityManager.getTransaction().commit(); entityManager.close(); } }
