2010-08-22 21 views
5

tôi có một thực thể chứa hai thực thể khác có mối quan hệ @ManyToOne.Hibernate và NonUniqueObjectException

@Entity 
public class A extends Serializable{ 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Long id; 

    @ManyToOne 
    @Cascade(CascadeType.SAVE_UPDATE) 
    private B b; 

    @ManyToOne 
    @Cascade(CascadeType.SAVE_UPDATE) 
    private C c; 

} 

Nếu tôi cố gắng tiết kiệm một Một ví dụ mà có "B_ID" và "C_ID" của người khác Một hồ sơ tôi nhận được ngoại lệ:

org.hibernate.NonUniqueObjectException: một đối tượng khác nhau với cùng giá trị định danh đã được gắn liền với phiên

Ví dụ:

A table 
| ID | B_ID | C_ID | 
| 1 |  1 | null | // this works 
| 2 | null |  1 | // this works 
| 3 |  1 |  x | // this throws the exception 
| 4 |  x |  1 | // this throws the exception 

x=any value of existent B/C_ID 

B_ID và C_ID không phải là duy nhất trong mô hình của tôi và (B_ID + C_ID) không phải là một ràng buộc duy nhất !!

Tôi có thể làm gì?

Cảm ơn trước.

Trả lời

15

Hibernate không phàn nàn về tính duy nhất của cơ sở dữ liệu ở đây, nó phàn nàn rằng hiện tại Session đã chứa một đối tượng có cùng ID như một đối tượng mới mà bạn đang cố lưu. Nó sẽ không cho phép điều này - Hibernate có một yêu cầu nghiêm ngặt rằng một ID đã cho không thể được đại diện bởi hai đối tượng khác nhau trong phạm vi của một phiên duy nhất.

Tại một số thời điểm, ứng dụng của bạn đã lưu dor tải một thực thể có cùng ID đó và đối tượng đó đã được "đăng ký" với phiên. Thật khó để nói trong trường hợp cụ thể mà ID của nó phàn nàn về, vì văn bản ngoại lệ không rõ ràng. Thử tạm thời xóa các chỉ thị xếp tầng và xem liệu nó có còn xảy ra hay không, cố gắng thu hẹp nó xuống. Nếu cần, bạn có thể buộc phiên "quên" về bất kỳ đối tượng hiện có nào cho một ID đã cho (sử dụng Session.evict() trong API Hibernate, hoặc EntityManager.detach() trong API JPA 2.0), nhưng đó không phải là giải pháp rất thanh lịch.

Để nhắc lại - ngoại lệ này không có gì để làm với các ràng buộc cơ sở dữ liệu, đó là về Hibernate bảo vệ tính nhất quán của trạng thái trong bộ nhớ trong của nó.

+0

Cảm ơn, những thứ duy nhất tôi tải từ db là B và C, và tôi sử dụng chúng trong đối tượng A. Nhưng B và C có CascadeType.SAVE_UPDATE, vì vậy họ không được lưu lại, nhưng chỉ cập nhật ... tôi hy vọng ... – blow

+0

Các vấn đề xuất hiện lúc bắt đầu quá, khi phiên là mới. – blow

+0

loại bỏ các chỉ thị thác hoạt động tốt, nhưng ... TẠI SAO ??? Nếu không có "Cascade.SAVE_UPDATE" hibernate nên cố gắng để tiết kiệm "A" và "B" đã được trình bày trong db và do đó ném một ngoại lệ, nhưng nó hoạt động thay vì ... tại sao? – blow