Composite Primary Key is a table containg two or more columns Primary Keys. To represent them by entity in JPA, we can use the @Embeddable annotation. How is it in details? Let’s find out in this tutorial.
First, I will create a Maven project as an example:
I will use Hibernate as JPA implementation so I will add Hibernate dependency as follows:
1 2 3 4 5 |
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.2.12.Final</version> </dependency> |
MySQL Connector:
1 2 3 4 5 |
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.6</version> </dependency> |
Project Lombok:
1 2 3 4 5 6 |
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> <scope>provided</scope> </dependency> |
Suppose in the database, you have a table student with the structure as follows:
1 2 3 4 5 6 |
CREATE TABLE `student` ( `id` int(11) NOT NULL, `code` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`, `code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
As you can see, in this student table, I am defining it has 3 columns: id, code and name. It has a Composite Primary Key consisting of two Primary Keys: id and code.
To represent the structure of the student table in the entity, we first need to define an object containing the information of the Composite Primary Key using the @Embeddable annotation. The content of this class is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package com.huongdanjava.jpaembeddable; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import javax.persistence.Column; import javax.persistence.Embeddable; import java.io.Serializable; @Embeddable @EqualsAndHashCode @Getter @Setter @AllArgsConstructor public class StudentId implements Serializable { @Column private Integer id; @Column private Integer code; } |
Note that this object must be implemented in the Serializable interface, and the equals() and hashCode() methods must be declared. This represents the uniqueness of the Composite Primary Key for each student record in the database.
Now, we can define the Student entity using the Composite Primary Key object as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.huongdanjava.jpaembeddable; import lombok.Getter; import lombok.Setter; import javax.persistence.Column; import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table @Setter @Getter public class Student { @EmbeddedId private StudentId id; @Column private String name; } |
In above the Student entity, I declared the StudentId object with the @EmbeddedId annotation.@EmbeddedId annotation is used to declare a Primary Key property for complex objects containing multiple Primary Keys. For an entity that has declared a property with the @EmbeddedId annotation, then we cannot use the @Id annotation in that entity.
OK, so we have defined the Student entity with the Composite Primary Key. Now, I will make an example to see how it works.
I will add the configuration file for JPA, persistence.xml, located in the /src/main/resources/META-INF directory with the following contents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence_2_1.xsd"> <persistence-unit name="jpaexample" transaction-type="RESOURCE_LOCAL"> <class>com.huongdanjava.jpaembeddable.Student</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpaexample" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="123456" /> <property name="hibernate.format_sql" value="true" /> <property name="hibernate.use_sql_comments" value="true" /> </properties> </persistence-unit> </persistence> |
Next, I create a new class for example. In this class, I will use the EntityManager object to search the table student for records that have the Primary Key column with certain values. Id will now be the StudentId object.
Details as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.huongdanjava.jpaembeddable; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; public class Application { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaexample"); EntityManager em = emf.createEntityManager(); EntityTransaction transaction = em.getTransaction(); Student student = em.find(Student.class, new StudentId(1, 123)); System.out.println("Student name: " + student.getName()); em.close(); emf.close(); } } |
If in the database, I have the following data:
then the results will look like this:
Trần Minh Quân
Anh Khanh cho em hỏi em muốn dùng Sql server em sẽ cần dependency những gì anh?
Khanh Nguyen
Just use this dependency: https://mvnrepository.com/artifact/com.microsoft/sqljdbc4/3.0