Composite Primary Key là những table có từ 2 cột trở lên là Primary Key. Để thể hiện chúng bằng entity trong JPA, chúng ta có thể sử dụng annotation @Embeddable. Cụ thể là như thế nào? Hãy cùng nhau tìm hiểu trong bài viết này nhé các bạn!
Đầu tiên, mình sẽ tạo một Maven project để làm ví dụ:
Mình sẽ sử dụng Hibernate làm implementation của JPA nên sẽ thêm Hibernate dependency như sau:
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> |
Giả sử trong database mình đang có một table student với cấu trúc như sau:
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; |
Như các bạn thấy, trong table student này, mình đang định nghĩa nó có 3 cột: id, code và name; trong đó nó có 1 Composite Primary Key bao gồm 2 cột primary key: id và code.
Để thể hiện cấu trúc của table student trong entity, đầu tiên chúng ta cần định nghĩa một đối tượng chứa thông tin của Composite Primary Key trước sử dụng annotation @Embeddable. Nội dung của class này như sau:
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; } |
Các bạn lưu ý là đối tượng này phải được implement interface Serializable và các phương thức equals() và hashCode() phải được khai báo. Điều này thể hiện tính duy nhất của đối tượng Composite Primary Key ứng với mỗi record của table student trong database.
Và giờ, chúng ta có thể định nghĩa entity Student sử dụng đối tượng Composite Primary Key như sau:
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; } |
Trong entity Student trên, mình đã khai báo đối tượng StudentId với annotation @EmbeddedId. Annotation@EmbeddedId được sử dụng để khai báo thuộc tính primary key cho những đối tượng phức tạp gồm nhiều primary key. Với một entity đã khai báo một thuộc tính với annotation @EmbeddedId thì chúng ta không được sử dụng annotation @Id trong entity đó nữa.
OK, vậy là chúng ta đã định nghĩa xong entity Student với Composite Primary Key. Giờ, mình sẽ làm một ví dụ để xem nó hoạt động như thế nào nhé các bạn!
Mình sẽ thêm tập tin cấu hình cho JPA, persistence.xml, nằm trong thư mục /src/main/resources/META-INF với nội dung như sau:
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> |
Tiếp theo, mình tạo mới một class ví dụ. Trong class này, mình sẽ sử dụng đối tượng EntityManager để tìm kiếm trong table student những record có những cột primary key bằng những giá trị nào đó. Id lúc này sẽ là đối tượng StudentId.
Cụ thể như sau:
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(); } } |
Nếu như trong database, mình đang có dữ liệu như sau:
thì khi chạy, kết quả sẽ như sau: