2011-08-25 32 views
63

Nói rằng tôi có một một chiều@ManyToOne mối quan hệ như sau:JPA: một chiều nhiều-một và tầng xóa

@Entity 
public class Parent implements Serializable { 

    @Id 
    @GeneratedValue 
    private long id; 
} 

@Entity 
public class Child implements Serializable { 

    @Id 
    @GeneratedValue 
    private long id; 

    @ManyToOne 
    @JoinColumn 
    private Parent parent; 
} 

Nếu tôi có một P phụ huynh và trẻ em C ... C ntham chiếu trở lại P, có cách sạch và đẹp trong JPA để tự động xóa các con C ... C n khi P bị xóa (tức là entityManager.remove(P))?

Những gì tôi đang tìm kiếm là một chức năng tương tự như ON DELETE CASCADE trong SQL.

+1

Ngay cả khi chỉ có 'Trẻ em' có tham chiếu đến 'Cha mẹ' (theo cách đó, tham chiếu là một chiều) là có vấn đề để bạn thêm Danh sách 'Trẻ em' với ánh xạ '@OneToMany' và 'Cascade = ALL 'thuộc tính cho' Phụ huynh '? Tôi cho rằng JPA nên giải quyết rằng ngay cả khó khăn chỉ có 1 bên giữ tham chiếu. – kvDennis

+1

@kvDennis, có những trường hợp bạn không muốn kết hợp chặt chẽ với nhiều phía. Ví dụ. trong các thiết lập giống như ACL nơi quyền bảo mật là "add-on" trong suốt – Bachi

Trả lời

56

Mối quan hệ trong JPA luôn là một chiều, trừ khi bạn kết hợp phụ huynh với trẻ theo cả hai hướng. Cascading REMOVE hoạt động từ cha mẹ cho đứa trẻ sẽ yêu cầu một mối quan hệ từ cha mẹ cho đứa trẻ (không chỉ là đối diện).

Bạn do đó sẽ cần phải làm điều này:

  • Hoặc, thay đổi mối quan hệ một chiều @ManyToOne đến một bi-directional @ManyToOne, hoặc một chiều @OneToMany. Sau đó, bạn có thể xếp các hoạt động XÓA để EntityManager.remove sẽ xóa cha mẹ và con cái. Bạn cũng có thể chỉ định orphanRemoval là true, để xóa bất kỳ trẻ mồ côi nào khi thực thể con trong bộ sưu tập gốc được đặt thành rỗng, tức là xóa con khi nó không có trong bộ sưu tập của cha mẹ bất kỳ.
  • Hoặc, chỉ định ràng buộc khóa ngoài trong bảng con là ON DELETE CASCADE. Bạn sẽ cần gọi EntityManager.clear() sau khi gọi EntityManager.remove(parent) vì bối cảnh kiên trì cần được làm mới - các thực thể con không được phép tồn tại trong ngữ cảnh kiên trì sau khi chúng đã bị xóa trong cơ sở dữ liệu.
+4

có cách nào để thực hiện No2 với chú thích JPA không? – user2573153

+2

Làm cách nào để thực hiện No2 với ánh xạ xml Hibernate? – arg20

+0

câu trả lời dưới đây bạn là cách tốt hơn so với bạn – Enerccio

11

Tạo mối quan hệ hai chiều, như thế này:

@Entity 
public class Parent implements Serializable { 

    @Id 
    @GeneratedValue 
    private long id; 

    @OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE) 
    private Set<Child> children; 
} 
+0

câu trả lời xấu, hai chiều mối quan hệ là khủng khiếp trong JPA bởi vì hoạt động trên bộ trẻ em lớn có số lượng đáng kinh ngạc của thời gian – Enerccio

-1

@Cascade (org.hibernate.annotations.CascadeType.DELETE_ORPHAN)

chú thích Do làm việc cho tôi.

Ví dụ: -

 public class Parent{ 
      @Id 
      @GeneratedValue(strategy=GenerationType.AUTO) 
      @Column(name="cct_id") 
      private Integer cct_id; 
      @OneToMany(cascade=CascadeType.REMOVE, fetch=FetchType.EAGER,mappedBy="clinicalCareTeam", orphanRemoval=true) 
      @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) 
      private List<Child> childs; 
     } 
      public class Child{ 
      @ManyToOne(fetch=FetchType.EAGER) 
      @JoinColumn(name="cct_id") 
      private Parent parent; 
    } 
39

Nếu bạn đang sử dụng chế độ ngủ đông là nhà cung cấp JPA của bạn, bạn có thể sử dụng @OnDelete chú thích. Chú thích này sẽ thêm vào mối quan hệ kích hoạt ON DELETE CASCADE, ủy quyền xóa các trẻ em vào cơ sở dữ liệu.

Ví dụ:

public class Parent { 

     @Id 
     private long id; 

} 


public class Child { 

     @Id 
     private long id; 

     @ManyToOne 
     @OnDelete(action = OnDeleteAction.CASCADE) 
     private Parent parent; 
} 

Với giải pháp này một mối quan hệ một chiều từ đứa trẻ để phụ huynh là đủ để tự động loại bỏ tất cả trẻ em. Giải pháp này không cần bất kỳ người nghe vv Ngoài ra một truy vấn như DELETE FROM Parent WHERE id = 1 sẽ xóa các trẻ em.

+0

Đó là một giải pháp hoàn hảo mà không thay đổi thiết kế @ManyToOne. –

+0

Đây là một câu trả lời tuyệt vời, nó thậm chí không phải là một lựa chọn mà nó là một tính năng quan trọng: – Yoi

+2

Tôi không thể làm cho nó hoạt động theo cách này, có phiên bản cụ thể nào của hibernate hoặc ví dụ chi tiết hơn như thế này không? – Mardari

Các vấn đề liên quan