Code ví dụ Hibernate cascade, annotation @Cascade.
(Xem thêm: Hướng dẫn tự học Hibernate)
(Xem lại: Cascade trong Hibernate là gì? Cascade trong JPA là gì?)
Trong bài này mình sẽ hướng dẫn sử dụng cascade để thực hiện insert, delete các class tham chiếu với nhau.
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.
Trong ví dụ này mình sẽ sử dụng cacade để:
- Khi xóa 1 company nó sẽ tự xóa các employee của company đó (mặc định không cho phép, phải xóa các employee trước rồi sau đấy mới xóa được company)
- Khi insert 1 company nó sẽ tự động insert các employee của company đó vào database (mặc định phải tạo company trước, sau đấy set company đó cho các employee và insert lần lượt các employee vào database)
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>HibernateCascadeDemo</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 Cascade</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; // setter - getter @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.*; import org.hibernate.annotations.Cascade; @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.REMOVE, CascadeType.PERSIST}) // @Cascade(value= {org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE}) private Set<Employee> listEmployee = new HashSet<>(); // setter - getter @Override public String toString() { return "Company [id=" + id + ", name=" + name + "]"; } }
- Ở đây mình dùng entityManager nên sẽ sử dụng thuộc tính
cascade
trong@OneToMany
(Nếu bạn sử dụng sesionFactory thì sử dụng annotation@Cascade
) cascade = {CascadeType.REMOVE, CascadeType.PERSIST}
: Tức là khi xóa company thì các employee liên quan cũng bị xóa, khi insert company thì các employee bên trong nó cũng được tự động insert vào database.
(Xem lại: Các loại cascacde trong JPA – Hibernate)
Demo
Demo insert
package stackjava.com.hibernatedemo.dao; 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=1, name=Google] Employee [id=2, name=kai, company=Company [id=1, name=Google]] Employee [id=1, name=sena, company=Company [id=1, name=Google]]
Sau khi insert company, nó sẽ tự động insert các employee bên trong company đó.
Demo delete
Ở ví dụ trên đối tượng company tạo ra có id = 1, nên mình sẽ lấy company theo id = 1 và thực hiện xóa nó khỏi database.
package stackjava.com.hibernatedemo.dao; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import stackjava.com.hibernatedemo.entities.Company; public class DemoDelete { public static void main(String[] args) { EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("persistence"); EntityManager entityManager = entityManagerFactory.createEntityManager(); entityManager.getTransaction().begin(); Company company = entityManager.find(Company.class, 1); entityManager.remove(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=? 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=? Hibernate: delete from employee where id=? Hibernate: delete from company where id=?
Nó tự động xóa các employee liên quan trước khi thực hiện xóa company.
______
Okay, Done!
Download code ví dụ trên tại đây.
References: