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
@JoinTablecấ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_positionnê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@Embeddablevớ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 = truecủa@OneToMany)



