Code ví dụ Hibernate @ElementCollection, lưu dữ liệu dạng list

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

Code ví dụ Hibernate @ElementCollection, lưu dữ liệu dạng list

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

Code ví dụ Hibernate @ElementCollection, lưu dữ liệu dạng list

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)

File entity
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ảng employee_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 hibernate insert list

 

demo hibernate lưu trữ dạng list

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)
Okay, Done!
Download code ví dụ trên tại đây.
References:
stackjava.com