Giả sử các bạn đang làm trong một dự án mà database có 2 bảng, ví dụ như student và clazz có cấu trúc như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
CREATE TABLE `clazz` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `student` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `clazz_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`), FOREIGN KEY (`clazz_id`) REFERENCES `clazz` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
Như các bạn thấy, bảng clazz có các cột id, name với primary key là cột id. Bảng student thì có các cột id, name và clazz_id với primary key là id. Trong bảng student này, chúng ta cũng đã định nghĩa một foreign key từ nó tới bảng clazz với ý nghĩa một lớp có thể có nhiều sinh viên, và nhiều sinh viên thì có thể được xếp vào một lớp. Trong JPA, để thể hiện mối quan hệ nhiều sinh viên có cùng lớp, chúng ta sẽ sử dụng annotation @ManyToOne, còn để thể hiện mối quan hệ một lớp có nhiều sinh viên thì chúng ta sẽ sử dụng annotation @OneToMany.
Chúng ta đã tìm hiểu về annotation @ManyToOne trong bài viết trước, bài viết này mình sẽ cùng với các bạn tìm hiểu về annotation @OneToMany các bạn nhé!
Đầu tiên, mình sẽ tạo một Maven project lấy ví dụ ở trên để làm minh họa:
Mình sẽ thêm dependency của Hibernate để sử dụng JPA như sau:
1 2 3 4 5 |
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.2.5.Final</version> </dependency> |
Trong ví dụ này, mình làm việc với MySQL nên mình cũng sẽ thêm dependency của MySQL Driver như sau:
1 2 3 4 5 |
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.5</version> </dependency> |
Tiếp theo, mình sẽ tạo các entity Clazz và Student để thể hiện thông tin của chúng.
Nội dung của entity Clazz lúc 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 26 27 28 29 30 31 32 33 34 35 36 |
package com.huongdanjava.jpaonetomany; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table public class Clazz { @Id @GeneratedValue private Integer id; @Column private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } |
và entity Student:
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
package com.huongdanjava.jpaonetomany; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity @Table public class Student { @Id @GeneratedValue private Integer id; @Column private String name; @ManyToOne @JoinColumn(name = "clazz_id") private Clazz clazz; public Clazz getClazz() { return clazz; } public void setClazz(Clazz clazz) { this.clazz = clazz; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } |
Bây giờ, chúng ta sẽ sử dụng annotation @OneToMany để thể hiện mối quan hệ của bảng clazz với bảng student trong JPA các bạn nhé!
Bởi vì, đây là mối quan hệ một – nhiều nhìn từ đối tượng Clazz nên mình sẽ đặt annotation @OneToMany trong đối tượng Clazz, cụ thể như sau:
1 2 3 4 5 6 7 8 9 10 |
@OneToMany(mappedBy = "clazz") private Collection<Student> students; public Collection<Student> getStudents() { return students; } public void setStudents(Collection<Student> students) { this.students = students; } |
Như các bạn thấy, trong annotation này, mình đã khai báo một thuộc tính là mappedBy với giá trị là clazz. Giá trị “clazz” ở đây là tên biến được định nghĩa với annotation @ManyToOne trong entity Student.
Đến đây, chúng ta đã hoàn thành việc sử dụng annotation @OneToMany để định nghĩa trong entity Clazz rồi. Mình sẽ thử làm ví dụ để xem nó hoạt động thế nào nhé các bạn!
Mình sẽ thêm một tập tin cấu hình persistence.xml:
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.jpaonetomany.Clazz</class> <class>com.huongdanjava.jpaonetomany.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> |
Giả sử, bây giờ trong database, mình có những dữ liệu như sau:
thì với đoạn code này:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.huongdanjava.jpaonetomany; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; public class Example { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaexample"); EntityManager em = emf.createEntityManager(); EntityTransaction transaction = em.getTransaction(); Clazz clazz = em.find(Clazz.class, 1); System.out.println("Number of students: " + clazz.getStudents().size()); em.close(); emf.close(); } } |
Kết quả sẽ như sau:
Tham khảo project trên GitHub: https://github.com/huongdanjavacom/huongdanjava.com/tree/master/jpa-onetomany
Trần Văn Minh
Hi anh Khanh, anh cho em hỏi ví dụ giờ em muốn xóa Class A có id là 1 đó thì nó xóa luôn cả 2 Student trong Class đó.
giờ em muốn xóa được nó thì mà 2 Student kia không bị mất đi, claszz_id chuyển về lại thành null. Thì làm thế nào a?
Khanh Nguyen
Cái này có thể giải quyết bằng cách khi tạo bảng và tạo foreign key, em thêm “ON DELETE SET NULL” nữa là được nhé.
Ví dụ như sau:
FOREIGN KEY (
clazz_id
) REFERENCESclazz
(id
) ON DELETE SET NULLlập trình viên
Viết tiếp đi anh 🙂
Tú Lê
Chào anh,
Em đọc những bài hướng dẫn của anh và em cảm thấy rất thú vị.
Em cũng đang tự học Spring và có rất nhiều khó khăn, liệu anh có thể giúp đỡ em không ạ? nếu có thì em có thể liên hệ anh bằng cách nào?
Cảm ơn!
Khanh Nguyễn
Bạn có thể gửi bất kỳ câu hỏi nào tới Khanh, bạn nhé!
Dùng form Liên hệ trên Menu hoặc post câu hỏi trong group Cộng Đồng Hướng Dẫn Java là được.
Cảm ơn bạn đã ủng hộ Hướng Dẫn Java! 😀