Code ví dụ Hibernate @ElementCollection, lưu dữ liệu dạng list.
(Xem thêm: Hướng dẫn tự học Hibernate | So sánh sự khác nhau giữa @ElementCollection và @OneTomany)
Annotation @ElementCollection
được dùng thay thế cho @OneToMany
trong những trường hợp mapping 1-nhiều mà không cần phải tạo class java mapping tương ứng cho tất cả các bảng.
Các công nghệ sử dụng:
Tạo database MySQL
Database chứa table employee
có quan hệ 1-n với table employee_position
CREATE SCHEMA `hibernate-demo-2` ; CREATE TABLE `hibernate-demo-2`.`employee` ( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(45) NULL, PRIMARY KEY (`id`)); CREATE TABLE `hibernate-demo-2`.`employee_position` ( `employee_id` INT NOT NULL, `position` VARCHAR(45) NOT NULL, PRIMARY KEY (`employee_id`, `position`));
Cấu trúc Project
Các thư viện sử dụng
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>stackjava.com</groupId> <artifactId>HibernateOneToManyExample</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.source>1.8</maven.compiler.source> <hibernate.version>5.3.6.Final</hibernate.version> </properties> <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</version> </dependency> </dependencies> </project>
File cấu hình hibernate, kết nối tới MySQL
<persistence 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/persistence_2_1.xsd" version="2.1"> <persistence-unit name="persistence"> <description>Demo Hibernate Element Collection</description> <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/hibernate-demo-2" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="admin1234" /> <property name="hibernate.show_sql" value="true" /> </properties> </persistence-unit> </persistence>
Trong ví dụ này mình sử dụng entityManager
nên sẽ khai báo file persistence.xml
nếu các bạn sử dụng hibernateSession
thì có thể khai báo file hibernate.cfg.xml
(Xem lại: Code ví dụ Hibernate EntityManager, EntityManagerFactory)
package stackjava.com.hibernatedemo.entities; import java.util.List; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.Table; @Entity @Table(name = "employee") public class Employee { @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(name = "name") private String name; @Column(name = "position") @ElementCollection @JoinTable(name = "employee_position", joinColumns = @JoinColumn(name = "employee_id")) private List<String> positions; // getter - setter @Override public String toString() { return "Employee [id=" + id + ", name=" + name + ", position=" + positions + "]"; } }
- Phần mapping giữa employee với position ta dùng annotation
@ElementCollection
(một đối tượng employee chứa 1 tập các position) - Annotation
@JoinTable
cấu hình các thông tin mapping trong bảng, ví dụ bảng chứa collection là bảngemployee_position
, column thực hiện mapping tới table employee làemployee_id
- Ở đây giá trị postion chỉ là 1 column trong table
employee_position
nên mình cần chỉ rõ ra nó sẽ nhận giá trị ở column nào bằng annotation@Column(name = "position")
. Trường hợp nó nhận nhiều hơn 1 giá trị thì ta sẽ tạo 1 class với annotation@Embeddable
với các field tương ứng các column đó)
Demo 1:
Insert đối tượng employee với 1 danh sách position
package stackjava.com.hibernatedemo.dao; import java.util.ArrayList; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import stackjava.com.hibernatedemo.entities.Employee; public class DemoSave { public static void main(String[] args) { EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("persistence"); EntityManager entityManager = entityManagerFactory.createEntityManager(); entityManager.getTransaction().begin(); Employee emp = new Employee(); emp.setName("kai"); entityManager.persist(emp); List<String> positions = new ArrayList<>(); positions.add("Developer"); positions.add("Tester"); emp.setPositions(positions); entityManager.getTransaction().commit(); System.out.println(emp); entityManager.close(); entityManagerFactory.close(); } }
Kết quả:
Hibernate: insert into employee (name) values (?) Hibernate: insert into employee_position (employee_id, position) values (?, ?) Hibernate: insert into employee_position (employee_id, position) values (?, ?) Employee [id=1, name=kai, position=[Developer, Tester]]
Khi thực hiện insert đối tượng emp
vào database nó sẽ tự động insert bản ghi tương ứng với 2 position trong đối tượng employee
vào table employee_position
Demo 2:
Khi thực hiện select đối tượng employee nó sẽ tự động select các bản ghi ở trong table employee_position
tương ứng và đưa vào list position của đối tượng employee đó.
package stackjava.com.hibernatedemo.dao; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import stackjava.com.hibernatedemo.entities.Employee; public class DemoSelect { public static void main(String[] args) { EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("persistence"); EntityManager entityManager = entityManagerFactory.createEntityManager(); entityManager.getTransaction().begin(); System.out.println("------------ demo select ----------------"); Employee emp = entityManager.find(Employee.class, 1); System.out.println(emp); System.out.println("------------ demo after remove one position ----------------"); emp.getPositions().remove("Tester"); entityManager.persist(emp); entityManager.getTransaction().commit(); System.out.println(emp); entityManager.close(); entityManagerFactory.close(); } }
- Khi select đối tượng Employee nó sẽ tự động select các bản ghi ở table employee_position
- Khi xóa 1 position trong danh sách positions của đối tượng Employee và save vào database nó sẽ tự động xóa bản ghi tương ứng khỏi table employee_position (cái này tương tự với
orphanRemoval = true
của@OneToMany
)