2014-10-13 12 views
5

Tôi đang cố gắng xóa một thực thể, có liên quan đến các quan hệ khác nhau (Chỉ @ManyToOne) - Tuy nhiên, Hibernate không xóa bất cứ điều gì - sau khi gọi em.remove mọi thứ vẫn không thay đổi.Hibernate EntityManager: loại bỏ thực thể tham chiếu không hoạt động


Tôi có 5 đơn vị (E1 - E5), tham khảo các thực thể (E6) trong câu hỏi như thế này:

@Entity 
public class EX { 
    @OneToMany(mappedBy = "eX", fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.REMOVE }) 
    private Set<E6> e6s; 
} 

E6 chính nó có điều ngược lại @ManyToOne Quan hệ:

public class E6{ 

    @ManyToOne(optional = false) 
    private E1 e1;  

    @ManyToOne(optional = false) 
    private E2 e2; 

    @ManyToOne(optional = false) 
    private E3 e3; 

    @ManyToOne(optional = false) 
    private E4 e4; 

    @ManyToOne(optional = false) 
    private E5 e5; 
} 

(trái các id, cột bổ sung, v.v ...)


Bất cứ khi nào tôi gọi em.remove(instanceOfE6), chỉ cần không có gì xảy ra. Tôi đã thêm Hibernate SQL-Output và không thể thấy một lần thử thực hiện truy vấn DELETE.

Kể từ khi xóa có thể xảy ra từ một yêu cầu ajax và tươi EntityManager, tôi đã thêm một cuộc gọi đến hợp nhất trước khi xóa, gây otherwhise tôi nhận được một Entity không được quản lý ngoại lệ:

em.remove(em.merge(instanceOfE6)); 

Nhưng không có gì . Nhà nước vẫn không thay đổi.

Vì vậy, tôi đã cố gắng thêm phương thức @PreRemove để xóa tất cả các mối quan hệ trước khi xóa thực thể ... Phương thức sẽ không bao giờ được gọi.

Tôi đã thử nhiều hoạt động Cascade khác nhau (bao gồm Cascade.ALL) - nhưng vì tất cả những gì tôi cần là xóa và vẫn tồn tại, điều đó cũng sẽ hoạt động.


Tôi nghĩ về việc sử dụng một Bản Tuyên Bố Xóa bản địa (mỗi thực thể có một id thay thế, vì vậy mà có thể làm việc rất có thể) - nhưng vì tất cả những gì xảy ra từ bên trong một AJAX gọi, tôi không muốn sử dụng , vì tôi muốn có bản cập nhật Persistence-Cache mà không cần tìm nạp lại mọi Thực thể liên quan ...

Bất kỳ ý tưởng nào?

Nếu bạn cần thêm nguồn, chỉ cần thả cho tôi nhận xét.


Tôi cũng đã cố gắng để loại bỏ các thực thể trong câu hỏi từ tất cả các mối quan hệ (đối tượng khôn ngoan), và gọi em.merge() trên một trong những đơn vị còn lại, hy vọng rằng Hibernate sẽ whipe thực thể bỏ liên kết - không may mắn.

+1

Bạn đã cam kết giao dịch chưa? –

+0

Bạn đã gọi 'em.flush()'? – jmvivo

+0

@DavidLevesque Chạy Hibernate ở chế độ tự động ... – dognose

Trả lời

13

tôi đã tìm ra vấn đề (s) - Thực tế đã có hai trong số họ: (Rời này ở đây, nếu ai đó tình cờ gặp một vấn đề tương tự)

Như tôi đã đề cập, việc xóa nên đã xảy ra trong một ajax yêu cầu. Do đó, gọi điện đơn giản

em.remove(instanceOfE6); 

dẫn đến một ngoại lệ java.lang.IllegalArgumentException: Removing a detached instance.Vì vậy, tôi đã thử phương pháp tiếp cận bằng cách hợp nhất:

em.remove(em.merge(instanceOfE6)); 

không gây ra lỗi - nhưng đơn giản là không hiệu quả. Tôi cho phép theo dõi-đăng cho ngủ đông như đã đề cập trong bài viết này: JPA/Hibernate remove entity sometimes not working để tìm ra những gì đã xảy ra, và quả thật, cố gắng để loại bỏ các thực thể dẫn đến:

TRACE [org...DefaultPersistEventListener] un-scheduling entity deletion ... 

Rõ ràng là thực thể để loại bỏ vẫn còn kết nối với các đơn vị khác , dẫn đến vấn đề hibernate hủy bỏ việc xóa, vì vậy tôi đã cố gắng để loại bỏ các mối quan hệ trước khi xóa. Như bạn có thể thấy từ ví dụ về E6, tôi đã sử dụng @ManyToOne(optional = false), có nghĩa là tôi không thể đặt tham chiếu đi thành không, hoặc sẽ gây ra ngoại lệ khi gọi merge.

Nỗ lực đầu tiên của tôi để làm sạch các mối quan hệ chỉ là "làm sạch bộ", bởi vì tôi giả định rằng việc làm sạch các mối quan hệ đi của thực thể tôi muốn xóa là không cần thiết. Nó không phải là, nhưng tôi sẽ phác thảo này một cách chi tiết một chút sau:

Vì vậy, mã ngay bây giờ trông giống như

instanceOfE6.getE1().getE6s().remove(instanceOfE6); 
instanceOfE6.getE2().getE6s().remove(instanceOfE6); 
instanceOfE6.getE3().getE6s().remove(instanceOfE6); 
instanceOfE6.getE4().getE6s().remove(instanceOfE6); 
instanceOfE6.getE5().getE6s().remove(instanceOfE6); 

em.remove(em.merge(instanceOfE6)); 

Cùng một vấn đề: xóa bị hủy bỏ. Tôi đã bỏ lỡ sự thật hiển nhiên, gọi số điện thoại merge sẽ là ofc. khôi phục các mục nhập bên trong các bộ tôi vừa xóa, vì instanceOfE6 STILL không có tham chiếu nullable trên các thực thể khác. Do đó việc xóa đã bị hủy bỏ một lần nữa.

Cuối cùng là giải pháp ofc. là để làm việc hợp nhất trước khi tháo các tài liệu tham khảo và xóa thức:

if (!em.contains(instanceOfE6)){ 
    instanceOfE6 = em.merge(instanceOfE6); 
} 

instanceOfE6.getE1().getE6s().remove(instanceOfE6); 
instanceOfE6.getE2().getE6s().remove(instanceOfE6); 
instanceOfE6.getE3().getE6s().remove(instanceOfE6); 
instanceOfE6.getE4().getE6s().remove(instanceOfE6); 
instanceOfE6.getE5().getE6s().remove(instanceOfE6); 

em.remove(instanceOfE6); 

Tôi không hoàn toàn chắc chắn nếu tôi đã giải thích tất cả mọi thứ chính xác 100%, nhưng ít nhất tôi có thể tái tạo và sửa chữa các Issue bởi thay đổi mã qua lại.

+2

Bạn là một phao cứu sinh. Đã đấu tranh với cái này trong hai giờ. Cảm ơn bạn rất nhiều. Mọi người, xem ra cho cây thực thể (tôi đã phải viết groupToRemove.getParent(). GetSubgroups(). Remove (groupToRemove), và đã phải bản đồ cha mẹ với cascade = CascadeType.MERGE). Chúc mừng – jpangamarca

+1

'groupToRemove.getParent(). GetSubgroups(). Remove (groupToRemov‌ e)' đó là chính xác những gì tôi đã làm. Trông có vẻ lạ ... nhưng đi vào nó: Nó hợp lý :-) – dognose

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