2009-11-07 31 views
41

tôi đã thông báo lỗi này:Tìm thấy tài liệu tham khảo chia sẻ với một bộ sưu tập org.hibernate.HibernateException

error: Found shared references to a collection: Person.relatedPersons

Khi tôi cố gắng thực hiện addToRelatedPersons(anotherPerson):

person.addToRelatedPersons(anotherPerson); 
anotherPerson.addToRelatedPersons(person); 

anotherPerson.save(); 
person.save(); 

miền của tôi:

Person { 

static hasMany = [relatedPersons:Person]; 

} 

bất kỳ ý tưởng nào tại sao điều này xảy ra?

+1

Tôi chạy vào cùng một ngoại lệ, đối với tôi đó là do có cùng một thuộc tính hai lần trong đường dẫn thừa kế của lớp thực thể của tôi – kaefert

+0

Tôi chạy vào cùng một vấn đề với @kaefert (tức là cùng một thuộc tính nhiều hơn một lần trong đường dẫn thừa kế), nhưng tôi có ngoại lệ chỉ khi các tiêu chí tương tự được chạy hai lần (gọi 'list()' hai lần). Khôn lanh. –

Trả lời

49

Hibernate hiển thị lỗi này khi bạn cố gắng tồn tại nhiều hơn một cá thể thực thể chia sẻ cùng một tham chiếu thu thập (tức là nhận dạng bộ sưu tập tương phản với bình đẳng thu thập).

Lưu ý rằng nó có nghĩa là cùng một bộ sưu tập , không yếu tố thu - nói cách khác relatedPersons trên cả personanotherPerson phải giống nhau. Có lẽ bạn đang đặt lại bộ sưu tập đó sau khi thực thể được tải? Hoặc bạn đã khởi tạo cả hai tham chiếu với cùng một cá thể bộ sưu tập?

+3

đã tìm thấy sự cố. Tôi đã nhầm lẫn bằng cách nhập person.relatedPerson = anotherPerson; một nơi nào đó trong mã .... doh. – nightingale2k1

+0

@ nightingale2k1 cách bạn giải quyết ngoại lệ này – Mohamed

+0

có, nhưng tại sao hibernate coi đây là vấn đề? Một thực thể có một bộ sưu tập như một trường ManyToMany và giá trị được đặt bằng cách tra cứu từ một thực thể khác. – Tiina

36

Tôi đã gặp vấn đề tương tự. Trong trường hợp của tôi, vấn đề là ai đó đã sử dụng BeanUtils để sao chép các thuộc tính của một thực thể này sang thực thể khác, vì vậy chúng tôi đã kết thúc có hai thực thể tham chiếu đến cùng một bộ sưu tập.

Cho rằng tôi đã trải qua một thời gian điều tra vấn đề này, tôi muốn giới thiệu danh sách kiểm tra sau đây:

  • Look cho các kịch bản như entity1.setCollection(entity2.getCollection())getCollection lợi nhuận tài liệu tham khảo nội bộ để bộ sưu tập (nếu getCollection() trả về một mới Ví dụ về bộ sưu tập, sau đó bạn không cần phải lo lắng).

  • Hãy xem nếu clone() đã được triển khai chính xác chưa.

  • Tìm kiếm BeanUtils.copyProperties(entity1, entity2).

+0

lớp nào nên triển khai clone()? – vacuum

+0

@vacuum, mô hình miền. –

+0

giải pháp ở đây là gì? – vashishth

4

Giải thích trên thực tế. Nếu bạn cố lưu đối tượng của mình, ví dụ::

Set<Folder> folders = message.getFolders(); 
    folders.remove(inputFolder); 
    folders.add(trashFolder); 
    message.setFiles(folders); 
MESSAGESDAO.getMessageDAO().save(message); 

bạn không cần phải thiết lập đối tượng được cập nhật cho một đối tượng cha mẹ:

message.setFiles(folders); 

đơn giản tiết kiệm đối tượng cha mẹ của bạn như:

Set<Folder> folders = message.getFolders(); 
    folders.remove(inputFolder); 
    folders.add(trashFolder); 
    // Not set updated object here 
MESSAGESDAO.getMessageDAO().save(message); 
2

Trong trường hợp của tôi, tôi đã sao chép và dán mã từ các lớp khác của tôi, vì vậy tôi đã không nhận thấy rằng mã getter bị viết xấu:

@OneToMany(fetch = FetchType.LAZY, mappedBy = "credito") 
public Set getConceptoses() { 
    return this.letrases; 
} 

public void setConceptoses(Set conceptoses) { 
    this.conceptoses = conceptoses; 
} 

Tất cả các tài liệu tham khảo conceptoses nhưng nếu bạn nhìn vào get nói letrases

1

Đọc trực tuyến là nguyên nhân của lỗi này có thể cũng là một Hibernate lỗi, như workaround rằng có vẻ như để làm việc, đó là đặt một:

session.clear() 

Bạn phải đặt rõ ràng sau khi nhận dữ liệu NĐ trước khi cam kết và chặt chẽ, xem ví dụ:

//getting data 
SrReq sr = (SrReq) crit.uniqueResult(); 
SrSalesDetailDTO dt=SrSalesDetailMapper.INSTANCE.map(sr); 
//CLEAR    
session.clear(); 
//close session 
session.getTransaction().commit(); 
session.close(); 
return dt; 

tôi sử dụng giải pháp này cho chọn cơ sở dữ liệu, để cập nhật hoặc chèn tôi không biết nếu giải pháp này có thể làm việc hoặc có thể gây ra vấn đề.

Vấn đề của tôi là bình đẳng ở mức 100% về điều này: http://www.progtown.com/topic128073-hibernate-many-to-many-on-two-tables.html

0

Hãy để tôi giải thích điều này rõ ràng những gì lỗi này là,

Hãy để tôi bắt đầu với một ví dụ,

xem xét một thực thể

public class foo{ 
private<user> user; 
/* with getters and setters */ 
} 

Và xem xét er an Business Logic class

class foo1{ 
. 
. 
List<User> user = new ArrayList<>(); 
user = foo.getUser(); 
. 
. 
} 

Ở đây người dùng và người dùng foo.get đang chia sẻ cùng một tham chiếu. trong khi lưu hai tham chiếu tạo ra một xung đột.

Việc sử dụng hợp lý nên được như thế:

class foo1 { 
. 
. 
List<User> user = new ArrayList<>(); 
user.addAll(foo.getUser); 
. 
. 
} 

Điều này tránh sự xung đột

0

tôi phải đối mặt với ngoại lệ tương tự trong ứng dụng của tôi. Sau khi nhìn vào stacktrace nó đã được rõ ràng rằng ngoại lệ đã được ném trong một lớp FlushEntityEventListener. Trong Hibernate 4.3.7 MSLocalSessionFactory bean nomore hỗ trợ thuộc tính eventListeners. Do đó, người ta phải tìm kiếm một cách explictly đăng ký dịch vụ từ các bean phiên hibernate riêng lẻ và sau đó thiết lập các trình lắng nghe sự kiện tùy chỉnh được yêu cầu. Trong quá trình thêm người nghe sự kiện tùy chỉnh, chúng tôi cần đảm bảo rằng trình nghe sự kiện mặc định tương ứng được xóa khỏi phiên ngủ đông tương ứng. Nếu trình nghe sự kiện mặc định không bị xóa thì trường hợp phát sinh của hai trình xử lý sự kiện đã đăng ký với cùng một sự kiện. Trong trường hợp này trong khi lặp qua các trình lắng nghe này, đối với người nghe đầu tiên bất kỳ bộ sưu tập nào trong phiên sẽ được gắn cờ là đã đạt đến và trong khi xử lý cùng một bộ sưu tập với người nghe thứ hai sẽ ném ngoại lệ hibernate này. Vì vậy, hãy chắc chắn rằng khi đăng ký người nghe tùy chỉnh, người nghe mặc định tương ứng sẽ bị xóa khỏi sổ đăng ký.

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