2010-01-14 19 views
13

tôi có những thực thểHibernate - thanh toán bù trừ một bộ sưu tập với tất cả-xóa-mồ côi và sau đó thêm vào nó gây ra ConstraintViolationException

class Foo{ 
    Set<Bar> bars; 
} 

class Bar{ 
    Foo parent; 
    String localIdentifier; 
} 

Với bản đồ này (xin lỗi, không có chú thích, tôi cũ lỗi thời):

<class name="Foo"> 
    ... 
    <set name="bars" cascade="all-delete-orphan" lazy="false" inverse="true"> 
     <key>...</key> 
     <one-to-many class="Bar"/> 
    </set> 
</class> 


<class name="Bar"> 
    ... 
    <property name="localIdentifier" column="local_identifier"/> 
    <many-to-one name="parent" column="parent_id" /> 
</class> 

tôi cũng có một hạn chế duy nhất trên 2 cột: local_identifierparent_id (không phải là một Constrain độc đáo trên từng, nhưng một Constrain độc đáo duy nhất có chứa cả hai, ví dụ như không có 2 hàng với cùng phụ huynh và cùng localIdentifier được phép)

alter table bar add constraint unique_bar unique (parent_id, local_identifier) 

Và mã này có sử dụng chúng:

//foo is persistent, foo id = 1 
Bars bars = foo.getBars(); 
bars.clear(); // bars contained 1 item [parent_id = 1, local_identifier = "a"] 
Bar newBar = new Bar(); 
newBar.setParent(foo); 
newBar.setLocalIdentifier("a"); 
bars.add(newBar); 

Bây giờ, đối với một số lý do, Hibernate không thực hiện mọi thứ theo thứ tự chúng được gọi. Nó không thực hiện clear() (xóa) trước khi add() (insert) nhưng ngược lại, đầu tiên nó sẽ cố gắng để chèn, nhận được một ConstraintViolationException

tôi biết thêm một chút session.flush() sau bars.clear();, có thể khắc phục điều này, nhưng trong trường hợp này , Tôi không có quyền truy cập vào phiên theo cách không xấu.

Vì vậy, là tuôn ra là giải pháp duy nhất? hoặc là có một phiên bản Hibernate tôn trọng thứ tự của hành động?

Cập nhật: Bằng cách này, dereferencing bộ sưu tập sẽ dẫn đến một HibernateException từ https://www.hibernate.org/117.html#A3:

tôi nhận được HibernateException: Đừng dereference một bộ sưu tập với thác = "all-xóa -orphan " Điều này sẽ xảy ra nếu bạn tải một đối tượng với một bộ sưu tập cascade =" all-delete-orphan " và sau đó xóa tham chiếu vào bộ sưu tập. Không thay thế bộ sưu tập này, sử dụng rõ ràng() để thuật toán xóa bỏ trẻ mồ côi có thể phát hiện thay đổi của bạn.

+2

Tôi nghĩ rằng xả nước là lựa chọn duy nhất ở đây – ruchirhhi

+0

Tương đối [Hibernate Forum topic] (https://forum.hibernate.org/viewtopic.php?t=934483). –

Trả lời

8

Tôi đoán không có thay thế cho đỏ bừng

Từ here:

Hibernate đang vi phạm một hạn chế duy nhất!

Hibernate không hoàn toàn là thông minh với các ràng buộc duy nhất vì nó là có khóa ngoài. Đôi khi bạn có thể cần đưa ra một chút gợi ý.

Vi phạm chế duy nhất có thể xảy ra nếu hai đối tượng đều là cập nhật, ai được "giải phóng" một giá trị và người kia là "thu thập" cùng giá trị . Giải pháp thay thế là tuôn ra() phiên theo cách thủ công sau khi cập nhật đối tượng đầu tiên và trước khi cập nhật giây.

(Đây là loại vấn đề hiếm khi xảy ra trong thực tế.)

1

Nếu bạn muốn tránh xả phiên ở đây, hãy thử thay thế toàn bộ danh sách (new List<Bar>() thay vì Clear()). Hibernate nên thực sự loại bỏ tất cả các mục trong một lần chụp trước khi thêm mới. Chỉ cần thử, không chắc chắn nếu nó hoạt động.

+1

THanks, nhưng không: https://www.hibernate.org/117.html#A3 Tôi sẽ cập nhật câu hỏi –

1

Nếu bạn đang sử dụng oracle, bạn cũng có thể sử dụng chế deferrable hoãn việc kiểm tra các ràng buộc đến khi giao dịch được thực hiện. Không chắc chắn nếu/làm thế nào điều này được hỗ trợ bởi cơ sở dữ liệu khác.

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