2008-10-13 36 views
9

Tôi có một thực thể [Project] có chứa một tập hợp các thực thể khác [Câu hỏi].Hibernate Delete Cascade

Tôi đã ánh xạ mối quan hệ với thuộc tính tầng của "all-delete-orphan".

Trong DB của tôi, quan hệ được ánh xạ với trường project_id (FK) trên bảng câu hỏi. trường này không thể rỗng vì tôi không muốn một câu hỏi không có dự án.

Khi tôi làm session.delete (dự án) nó ném một ngoại lệ nói rằng project_id không thể là null, nhưng nếu tôi loại bỏ ràng buộc không null vào trường đó, thao tác xóa sẽ hoạt động tốt.

Bất cứ ai cũng biết làm thế nào để giải quyết này?

+0

Bạn có thể sẽ hiển thị các phần liên quan của ánh xạ. Tôi sử dụng tất cả-xóa-mồ côi tất cả các thời gian với các phím ngoài không null và chưa bao giờ có một vấn đề. –

Trả lời

-2

Xóa đang diễn ra trên Dự án đầu tiên và xếp tầng vào Câu hỏi, nhưng xóa dự án bao gồm một null của project_id trong các câu hỏi (cho toàn vẹn tham chiếu. Bạn không nhận được một ngoại lệ về việc xóa đối tượng câu hỏi , nhưng vì thác đang cố gắng null các FK trong câu hỏi (s).

Nhìn vào "Java Persistence with Hibernate", tôi nghĩ rằng những gì bạn thực sự muốn có một kiểu thác của xóa hoặc gỡ bỏ, không xóa-trẻ mồ côi.

+0

Điều đó không giải quyết được bất cứ điều gì –

0

Một chiến lược là đánh dấu khóa ngoài trong cơ sở dữ liệu với on-delete-cascade, vì vậy ngay khi NHibernate yêu cầu cơ sở dữ liệu xóa một dự án, cơ sở dữ liệu sẽ tự thác xóa. Sau đó, bạn phải nói với NHibernate rằng cơ sở dữ liệu chính nó hiện một thác thác.

+0

là posible với nhibernate 1.2? –

11

Trực tiếp từ documentation. Điều này giải thích vấn đề của bạn chính xác tôi tin rằng:

Tuy nhiên, mã này

Parent p = (Parent) session.Load(typeof(Parent), pid); 
// Get one child out of the set 
IEnumerator childEnumerator = p.Children.GetEnumerator(); 
childEnumerator.MoveNext(); 
Child c = (Child) childEnumerator.Current; 

p.Children.Remove(c); 
c.Parent = null; 
session.Flush(); 

sẽ không loại bỏ c từ cơ sở dữ liệu; nó sẽ chỉ xóa liên kết đến p (và gây ra một sự vi phạm ràng buộc NOT NULL, trong trường hợp này). Bạn cần xóa một cách rõ ràng() con.

Parent p = (Parent) session.Load(typeof(Parent), pid); 
// Get one child out of the set 
IEnumerator childEnumerator = p.Children.GetEnumerator(); 
childEnumerator.MoveNext(); 
Child c = (Child) childEnumerator.Current; 

p.Children.Remove(c); 
session.Delete(c); 
session.Flush(); 

Bây giờ, trong trường hợp của chúng tôi, Trẻ em không thể thực sự tồn tại mà không có cha mẹ. Vì vậy, nếu chúng tôi xóa một Trẻ em khỏi bộ sưu tập, chúng tôi thực sự muốn nó bị xóa. Đối với điều này, chúng ta phải sử dụng cascade = "all-delete-orphan".

<set name="Children" inverse="true" cascade="all-delete-orphan"> 
    <key column="parent_id"/> 
    <one-to-many class="Child"/> 
</set> 

Edit:

Liên quan đến những thứ nghịch đảo, tôi tin rằng đây chỉ xác định cách sql được tạo ra, hãy xem doc để biết thêm.

Một điều cần lưu ý là, có bạn đã

not-null="true" 

trên nhiều-một mối quan hệ trong cấu hình Hibernate của bạn?

+0

Xin lỗi. Điều này không có tác dụng, nhưng tôi không hiểu tại sao. Từ các tài liệu nó nói rằng nghịch đảo đúng được sử dụng khi bạn ánh xạ một liên kết hai chiều (và nó không phải là trường hợp của tôi), anyways thêm mà làm cho nó hoạt động độc đáo. Cảm ơn.Nếu bạn chỉnh sửa giải thích tại sao inverse = true hoạt động, tôi sẽ chấp nhận câu trả lời của bạn –

+0

Có ví dụ về điều này từ tài liệu ngủ đông không? Nó có vẻ kỳ lạ với tôi rằng ông hỏi về hibernate và bạn trả lời với một số tài liệu nhibernate. – kbaribeau

+0

Tôi đã thêm một số thông tin bổ sung cho bạn. Vui mừng điều này đã làm việc cho bạn :) – abarax

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