6.1 Quản lý phụ thuộc sâu

Và một số điều hữu ích và thú vị hơn về chú thích @OneToMany và những thứ tương tự. Tất cả đều có 4 tùy chọn thường được sử dụng:

  • tầng = CascadeType.ALL
  • mồ côiRemoval = true
  • tìm nạp = FetchType.LAZY

Bây giờ chúng tôi sẽ phân tích chúng chi tiết hơn. Và chúng ta sẽ bắt đầu với điều thú vị nhất - CascadeType . Tham số này xác định điều gì sẽ xảy ra với các thực thể phụ thuộc nếu chúng ta thay đổi thực thể chính.

Đặc tả JPA có các giá trị sau cho tham số này:

  • TẤT CẢ
  • KIÊN TRÌ
  • HỢP NHẤT
  • DI DỜI
  • LÀM CHO KHỎE LẠI
  • TÁCH

Tuy nhiên, Hibernate mở rộng đặc điểm kỹ thuật này thành ba tùy chọn khác:

  • TÁI BẢN
  • SAVE_UPDATE
  • KHÓA

Tất nhiên, có một sự song song mạnh mẽ với cơ sở dữ liệu và CONSTRANIS của chúng. Tuy nhiên, cũng có sự khác biệt. Hibernate cố gắng che giấu công việc thực sự với cơ sở dữ liệu càng nhiều càng tốt, vì vậy các Cascade Hibernate này chính xác là về các đối tượng Thực thể.

6.2 CascadeType

Tham số tầng mô tả điều gì sẽ xảy ra với các đối tượng phụ thuộc nếu chúng ta thay đổi cha mẹ của chúng (đối tượng chính). Thông thường, tham số này được sử dụng cùng với các chú thích mô tả các phụ thuộc đối tượng:

Ví dụ:

OneToOne(cascade = CascadeType.ALL)

Hoặc như thế này:

@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})

Nó cũng có thể được viết như một chú thích riêng:

@Cascade({ org.hibernate.annotations.CascadeType.ALL })

Bây giờ hãy nói thêm về ý nghĩa của những chú thích này.

6.3 TẤT CẢ, TUYỆT VỜI, HỢP NHẤT

CascadeType.ALLcó nghĩa là tất cả các hành động mà chúng ta thực hiện với đối tượng cha phải được lặp lại cho các đối tượng phụ thuộc của nó.

CascadeType.PERSISTcó nghĩa là nếu chúng ta lưu đối tượng cha vào cơ sở dữ liệu, thì điều tương tự cũng phải được thực hiện với các đối tượng phụ thuộc của nó. Ví dụ:


@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @OneToOne(cascade = CascadeType.PERSIST, mappedBy="task")
   private EmployeeTask task;
}

Một ví dụ làm việc với lớp này:


Employee director = new Employee();
EmployeeTask task = new EmployeeTask();
director.task = task;
 
session.persist(director);
session.flush();

Chúng ta chỉ lưu một đối tượng kiểu Employee, đối tượng phụ thuộc của nó là EmployeeTask sẽ tự động được lưu vào cơ sở dữ liệu.

CascadeType.MERGEcó nghĩa là nếu chúng ta cập nhật đối tượng cha trong cơ sở dữ liệu, thì điều tương tự cũng phải được thực hiện với các đối tượng phụ thuộc của nó.

6.4 XÓA, XÓA, TÁCH

CascadeType.REMOVEcó nghĩa là nếu chúng ta xóa một đối tượng cha trong cơ sở dữ liệu, thì điều tương tự cũng phải được thực hiện với các đối tượng phụ thuộc của nó.

CascadeType.DELETEcùng nghĩa. Đây là những từ đồng nghĩa. Chỉ từ thông số kỹ thuật khác nhau.

CascadeType.DETACHcó nghĩa là nếu chúng ta xóa đối tượng cha khỏi phiên, thì điều tương tự cũng phải được thực hiện với các đối tượng phụ thuộc của nó. Ví dụ:


@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @OneToOne(cascade = CascadeType.DETACH, mappedBy="task")
   private EmployeeTask task;
}

Một ví dụ làm việc với lớp này:


Employee director = new Employee();
EmployeeTask task = new EmployeeTask();
director.task = task;
director.task = task;
session.flush();
 
assertThat(session.contains(director)).isTrue();
assertThat(session.contains(task)).isTrue();
 
session.detach(director);
 
assertThat(session.contains(director)).isFalse();
assertThat(session.contains(task)).isFalse();

CascadeType.REFRESHCascadeType.SAVE_UPDATEhoạt động theo cách giống như chúng ta mong đợi - chúng nhân bản các hành động được thực hiện với đối tượng cha sang đối tượng phụ thuộc của nó.

6.5 Tùy chọn loại bỏ trẻ mồ côi

Ngoài ra, đôi khi bạn có thể bắt gặp tham số orphan. Đây là viết tắt của Loại bỏ trẻ mồ côi. Nó được sử dụng để đảm bảo rằng không có thực thể con nào không có thực thể cha.

OneToOne(orphan = true)

Nếu tham số này được đặt thành true, thì thực thể con sẽ bị xóa nếu nó biến mấttất cả các liên kết. Nó không hoàn toàn giống như Cascade.REMOVE.

Bạn có thể gặp tình huống trong đó một số thực thể mẹ đề cập đến một con. Sau đó, có lợi là nó không bị xóa cùng với việc xóa thực thể mẹ, nhưng chỉ khi tất cả các tham chiếu đến nó bị vô hiệu hóa.

Giả sử bạn có một lớp học:


@Entity
@Table(name="user")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @OneToMany(cascade = CascadeType.ALL, orphan = true)
   @JoinColumn(name = "employee_id")
   private Set<EmployeeTask> tasks = new HashSet<EmployeeTask>();
}


Employee director = session.find(Employee.class, 4);
EmployeeTask task = director.tasks.get(0);
director.tasks.remove(task)
session.persist(director);
session.flush();

Đối tượng EmployeeTask sẽ bị xóa vì không còn tham chiếu nào đến nó. Đồng thời, không ai xóa đối tượng mẹ.

6.6 tùy chọn tìm nạp

Tùy chọn tìm nạp cho phép bạn kiểm soát cách các đối tượng phụ thuộc được tải. Nó thường nhận một trong hai giá trị:

  • FetchType.LAZY
  • FetchType.EAGER

Đây là một chủ đề rất thú vị với nhiều cạm bẫy khác nhau, vì vậy tốt hơn là tôi nên nói về nó trong một bài giảng riêng.