2012-06-27 39 views
6

Làm thế nào tôi có thể unproxy một đối tượng ngủ đông, như vậy mà đa hình sẽ được hỗ trợ?làm thế nào để unproxy một đối tượng ngủ đông

Hãy xem ví dụ sau. Các lớp A và B là hai thực thể ngủ đông. B có hai loại phụ C và D.

List<A> resultSet = executeSomeHibernateQuery(); 
for(A nextA : resultSet) { 
    for(B nextB : nextA.getBAssociations() { 
     if(nextB instanceof C) { 
      // do something for C 
     } else if (nextB instanceof D) { 
      // do something for D 
     } 
    } 
} 

Mã này không thực thi khối C hoặc D, vì bộ sưu tập B bị tải chậm và tất cả các phiên bản B là proxy Hibernate. Tôi muốn một cách để unproxy mỗi trường hợp.

Lưu ý: Tôi nhận ra rằng truy vấn có thể được tối ưu hóa để háo hức tìm nạp tất cả B. Tôi đang tìm một giải pháp thay thế.

+1

Tôi biết đó là một câu hỏi cũ, nhưng vì nó xuất hiện như là kết quả đầu tiên trong tìm kiếm google, tôi sẽ phải bình luận ở đây rằng nếu bạn phải sử dụng 'instanceof', thì có thể bạn đang làm đa hình sai. – drigoangelo

Trả lời

18

Đây là giải pháp của chúng tôi, thêm vào sự kiên trì utils của chúng tôi:

public T unproxy(T proxied) 
{ 
    T entity = proxied; 
    if (entity instanceof HibernateProxy) { 
     Hibernate.initialize(entity); 
     entity = (T) ((HibernateProxy) entity) 
        .getHibernateLazyInitializer() 
        .getImplementation(); 
    } 
    return entity; 
} 
+0

Giải pháp này có phù hợp với bạn không? Tôi đã thực hiện phương pháp tương tự và tôi vẫn có một 'HibernateProxy' như là một lớp của đối tượng của tôi. Đây là câu hỏi của tôi: http://stackoverflow.com/q/11518091/845220 – woyaru

+0

Điều này không giải quyết được vấn đề của 'PersistentCollection'. Thông thường, bạn có thể có 'Danh sách ' đã thực sự được proxified thành 'PersistentCollection'. Nếu được truyền qua phương thức này, phép thử 'entity instanceof HibernateProxy' sẽ thất bại và phương thức sẽ trả về mà không làm bất cứ điều gì. Một giải pháp sẽ là kiểm tra 'instance instanceof PersistentCollection', sử dụng' Hibernate.initialize() ', sau đó lặp lại và unproxy mọi đối tượng của bộ sưu tập. Dễ dàng mô tả hơn là thực hiện mặc dù .. – Aldian

+1

Lưu ý rằng bạn không cần phải kiểm tra thực thể đó không phải là rỗng (xem http://stackoverflow.com/questions/2950319/is-null-check-needed-before-calling -instanceof) – laurent

2

Giải pháp sử dụng HibernateProxy và getImplementationMethod là đúng.

Tuy nhiên, tôi cho rằng bạn đang chạy vào điều này vì bộ sưu tập của bạn được định nghĩa là giao diện và hibernate đang hiển thị proxy cho giao diện.

Điều này dẫn đến câu hỏi thiết kế, tại sao có "if" với "instanceof" thay vì sử dụng phương thức giao diện để thực hiện những gì bạn cần.

Vì vậy, vòng lặp của bạn trở thành:

for(B nextB : nextA.getBAssociations() { 
    nextB.doSomething(); 
} 

Bằng cách đó, hibernate sẽ ủy cuộc gọi đến "doSomething()" để các đối tượng thực hiện thực tế, và bạn không bao giờ biết sự khác biệt.

+0

Điểm tốt nhất, và việc sử dụng di sản của chúng tôi có lẽ ít hơn lý tưởng. Trong trường hợp cụ thể này, chúng tôi thực sự có logic khác tùy thuộc vào loại của từng mục trong bộ sưu tập. Vì vậy, một điều chúng ta có thể làm là thêm các phương thức trừu tượng isC() và isD(), nhưng điều đó cũng cảm thấy hơi khó chịu. FWIW, hệ thống phân cấp của chúng tôi hoạt động cho hầu hết các trường hợp sử dụng của chúng tôi, đây là một phần của 20%. –

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