orphanRemoval là gì? Code ví dụ Hibernate orphanRemoval = true

orphanRemoval là gì? Code ví dụ Hibernate orphanRemoval = true.

(Xem thêm: Hướng dẫn tự học Hibernate)

(Xem thêm: Sự khác nhau giữa orphanRemoval = true với cascadeType = REMOVE)

OrphanRemoval là gì?

orphanRemoval là một thuộc tính bên trong annotation @OneToMany@OneToOne.

orphanRemoval là một đặc tả trong ORM. Nó đánh dấu rằng các phần tử con sẽ bị xóa khi bạn xóa nó khỏi collection của phần tử cha.

Ví dụ mình có mối quan hệ sau:

orphanRemoval là gì? Code ví dụ Hibernate orphanRemoval = true

Mối quan hệ giữa company và employee là one to many.

@Entity
@Table(name = "company")
public class Company {
  //...	

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "company", cascade = {CascadeType.ALL}, orphanRemoval = true)
  private Set<Employee> listEmployee = new HashSet<>();

  //...
  
}

Mối đối tượng company sẽ chứa 1 tập hợp các đối tượng employee, khi một đối tượng employee bị xóa khỏi tập hợp đó thì nó sẽ bị xóa khỏi database.

Code ví dụ orphanRemoval = true

Các công nghệ sử dụng:

Tạo Database

CREATE SCHEMA `hibernate-demo` ;

CREATE TABLE `hibernate-demo`.`company` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NULL,
  `address` VARCHAR(255) NULL,
  PRIMARY KEY (`id`));

  
CREATE TABLE `hibernate-demo`.`employee` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `company_id` INT NULL,
  `name` VARCHAR(45) NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `emp-company`
    FOREIGN KEY (`company_id`)
    REFERENCES `hibernate-demo`.`company` (`id`));

Quan hệ giữa company và employee là 1-nhiều.

Cấu trúc project

orphanRemoval là gì? Code ví dụ Hibernate orphanRemoval = true

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>HibernateOrphanRemoval</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 OrphanRemoval</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" />
      <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)

(Xem lại: Code ví dụ Hibernate Session, SessionFactory)

Các file entities

package stackjava.com.hibernatedemo.entities;

import javax.persistence.*;

@Entity
@Table(name = "employee")
public class Employee {

  @Id
  @Column(name = "id")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer id;
  
  @Column(name = "name")
  private String name;
  
  @ManyToOne
  @JoinColumn(name = "company_id", nullable = false)
  private Company company;

  // getter - setter

  @Override
  public String toString() {
    return "Employee [id=" + id + ", name=" + name + ", company=" + company + "]";
  }
}
package stackjava.com.hibernatedemo.entities;

import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;

@Entity
@Table(name = "company")
public class Company {

  @Id
  @Column(name = "id")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer id;

  @Column(name = "name")
  private String name;
  
  @OneToMany(fetch = FetchType.LAZY, mappedBy = "company", cascade = {CascadeType.ALL}, orphanRemoval = true)
  private Set<Employee> listEmployee = new HashSet<>();

  // getter - setter

  @Override
  public String toString() {
    return "Company [id=" + id + ", name=" + name + "]";
  }
  
}

Mặc định orphanRemoval = false. Ở đây mình sẽ chuyển thành orphanRemoval = true

Demo Insert

Mình sẽ thực hiện insert 1 company với nhiều employee.

package stackjava.com.hibernatedemo;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import stackjava.com.hibernatedemo.entities.Company;
import stackjava.com.hibernatedemo.entities.Employee;

public class DemoInsert {

  public static void main(String[] args) {
    EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("persistence");
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    entityManager.getTransaction().begin();

    Company company = new Company();
    company.setName("Google");
    
    Employee emp1 = new Employee();
    emp1.setName("kai");
    emp1.setCompany(company);
    
    Employee emp2 = new Employee();
    emp2.setName("sena");
    emp2.setCompany(company);
    
    company.getListEmployee().add(emp1);
    company.getListEmployee().add(emp2);
    entityManager.persist(company);
    
    entityManager.getTransaction().commit();		
    
    System.out.println("-------------------");
    System.out.println(company);
    System.out.println(emp1);
    System.out.println(emp2);
    
    entityManager.close();
    entityManagerFactory.close();
  }

}

Kết quả:

Hibernate: insert into company (name) values (?)
Hibernate: insert into employee (company_id, name) values (?, ?)
Hibernate: insert into employee (company_id, name) values (?, ?)
-------------------
Company [id=4, name=Google]
Employee [id=8, name=kai, company=Company [id=4, name=Google]]
Employee [id=7, name=sena, company=Company [id=4, name=Google]]

Đối tượng company id = 4 và 2 đối tượng employee có id = 7,8 được lưu vào database.

Demo orphanremoval

Bây giờ mình sẽ lấy đối tượng company vừa tạo ở trên, và xóa đối tượng employee có id = 7 khỏi danh sách các employee của company đó.

package stackjava.com.hibernatedemo;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import stackjava.com.hibernatedemo.entities.Company;

public class DemoOrphanRemoval {

  public static void main(String[] args) {
    EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("persistence");
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    entityManager.getTransaction().begin();

    Company company = entityManager.find(Company.class, 7);
    System.out.println(company);
    
    company.getListEmployee().removeIf(employee -> employee.getId() == 7);
    entityManager.persist(company);
    
    entityManager.getTransaction().commit();
    entityManager.close();
    entityManagerFactory.close();
  }

}

Kết quả:

Hibernate: select company0_.id as id1_0_0_, company0_.name as name2_0_0_ from company company0_ where company0_.id=?
Company [id=4, name=Google]
Hibernate: select listemploy0_.company_id as company_3_1_0_, listemploy0_.id as id1_1_0_, listemploy0_.id as id1_1_1_, listemploy0_.company_id as company_3_1_1_, listemploy0_.name as name2_1_1_ from employee listemploy0_ where listemploy0_.company_id=?
Hibernate: delete from employee where id=?

Sau khi remove đối tượng employee có id = 7 khỏi company và thực hiện persist company đó, thì đối tượng company đó sẽ bị xóa khỏi database.

 

Okay, Done!

Download code ví dụ trên tại đây.

 

References:

http://mrbool.com/hibernate-framework-orphanremoval-with-hibernate

https://docs.oracle.com/cd/E19798-01/821-1841/giqxy/

stackjava.com