2012-10-23 33 views
132

Tôi nghĩ rằng tôi bỏ lỡ hiểu ý nghĩa của tầng trong bối cảnh của mối quan hệ @ManyToOne.JPA @ManyToOne với CascadeType.ALL

Các trường hợp:

public class User { 

    @OneToMany(fetch = FetchType.EAGER) 
    protected Set<Address> userAddresses; 

} 

public class Address { 

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
    protected User addressOwner; 

} 

ý nghĩa của cascade = CascadeType.ALL là gì? Ví dụ: nếu tôi xóa một địa chỉ nhất định khỏi cơ sở dữ liệu, thì thực tế tôi đã thêm cascade = CascadeType.ALL ảnh hưởng đến dữ liệu của tôi như thế nào (người dùng tôi đoán)?

Trả lời

230

Ý nghĩa của CascadeType.ALL là độ bền sẽ lan truyền (xếp chồng) tất cả các hoạt động EntityManager (PERSIST, REMOVE, REFRESH, MERGE, DETACH) cho các thực thể liên quan.

Có vẻ như trong trường hợp của bạn là một ý tưởng tồi, vì việc xóa Address sẽ dẫn đến việc xóa User có liên quan. Khi người dùng có thể có nhiều địa chỉ, các địa chỉ khác sẽ trở thành trẻ mồ côi. Tuy nhiên, trường hợp nghịch đảo (chú thích User) sẽ có ý nghĩa - nếu một địa chỉ thuộc về một người dùng duy nhất, nó là an toàn để tuyên truyền loại bỏ tất cả các địa chỉ thuộc về một người dùng nếu người dùng này bị xóa.

BTW: bạn có thể muốn thêm thuộc tính mappedBy="addressOwner" vào số User của mình để báo hiệu cho nhà cung cấp kiên trì rằng cột tham gia phải nằm trong bảng ADDRESS.

+27

+1 để có giải thích tốt nhất và ngắn nhất về mappedBy mà tôi từng gặp. – Ridcully

+3

Mặc dù vậy, tốt nhất nên có CascadeType.ALL trên @OneToMany. – mvmn

33

See here ví dụ từ tài liệu OpenJPA. CascadeType.ALL nghĩa là nó sẽ thực hiện tất cả các hành động.

Trích:

CascadeType.PERSIST: Khi kiên trì một thực thể, cũng tồn tại các đối tượng tổ chức trong lĩnh vực này. Chúng tôi đề xuất ứng dụng tự do của quy tắc xếp tầng này, bởi vì nếu EntityManager tìm một trường tham chiếu đến một thực thể mới trong quá trình tuôn ra và trường không sử dụng CascadeType.PERSIST thì đó là lỗi.

CascadeType.REMOVE: Khi xóa một thực thể, cũng xóa các thực thể được giữ trong trường này.

CascadeType.REFRESH: Khi làm mới một thực thể, cũng làm mới các thực thể được giữ trong trường này.

CascadeType.MERGE: Khi hợp nhất trạng thái thực thể, cũng hợp nhất các thực thể được giữ trong trường này.

Sebastian

+3

Mới trong JPA, thông tin này hữu ích nhưng những gì về tách ở đây? – Sarz

+1

Trong CascadeType.DETACH, khi tách một thực thể, bạn cũng tách các thực thể được tổ chức bởi thực thể cha. –

15

From the EJB3.0 Specification:

Sử dụng các yếu tố chú thích thác có thể được sử dụng để tuyên truyền hiệu quả của một hoạt động cho các tổ chức liên quan. Chức năng xếp tầng thường được sử dụng nhất trong các mối quan hệ cha-con.

Nếu X là một thực thể được quản lý, thao tác xóa sẽ khiến nó trở thành bị xóa. Thao tác xóa được xếp thành các thực thể được tham chiếu bởi X, nếu các mối quan hệ từ X đến các thực thể khác được chú thích với các thác = REMOVE hoặc cascade = ALL giá trị phần tử chú thích.

Vì vậy, trong một mối quan hệ ngắn gọn, thực thể được xác định với CascadeType.All sẽ đảm bảo rằng tất cả các sự kiện liên tục như tồn tại, làm mới, hợp nhất và xóa xảy ra trên phụ huynh sẽ được chuyển cho trẻ. Việc xác định các tùy chọn CascadeType khác cung cấp cho nhà phát triển mức kiểm soát chi tiết hơn về cách hiệp hội thực thể xử lý sự kiên trì.

Ví dụ: nếu tôi có một đối tượng Sách có chứa Danh sách trang và tôi thêm đối tượng trang trong danh sách này. Nếu chú thích @OneToMany xác định mối liên hệ giữa Sách và Trang được đánh dấu là CascadeType.All, hãy kiên trì Sách sẽ dẫn đến Trang cũng được lưu vào cơ sở dữ liệu.

8

Trong JPA 2.0 nếu bạn muốn xóa địa chỉ nếu bạn xóa địa chỉ đó khỏi thực thể Người dùng, bạn có thể thêm orphanRemoval=true (thay vì CascadeType.REMOVE) vào @OneToMany.

Giải thích khác giữa orphanRemoval=trueCascadeType.REMOVEhere.

6

Như tôi đã giải thích trong this article và trong cuốn sách của tôi, High-Performance Java Persistence, bạn không bao giờ nên sử dụng CascadeType.ALL trên @ManyToOne từ entity state transitions nên tuyên truyền từ các đơn vị chuyên cho những người trẻ.

Bên @ManyToOne luôn là liên kết Con vì nó nên ánh xạ FK cơ bản.

Do đó, hãy di chuyển CascadeType.ALL từ liên kết @ManyToOne đến số @OneToMany nên sử dụng thuộc tính mappedBy vì thuộc tính the most efficient one-to-many mapping. `

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