2012-11-24 32 views
5

Tôi đang sử dụng Hibernate với proxy và tôi nhận các đối tượng thuộc các lớp như test.DBUser$$EnhancerByCGLIB$$40e99a2d.Làm cách nào để truy xuất lớp proxy từ lớp proxy?

Có phương pháp Hibernate để truy xuất lớp cơ sở (test.DBUser trong trường hợp này) từ lớp được ủy quyền không? Tôi biết về Hibernate.getClass(), nhưng phải mất Object, trong khi tôi đang tìm một phương thức lấy làm đầu vào là Class.

+1

Tại sao bạn cần điều này ngay từ đầu? Proxy mở rộng lớp cơ sở của bạn, vì vậy mọi phương thức bạn có thể gọi trên một thể hiện của lớp cơ sở cũng có thể được gọi trên proxy, và sẽ quay trở lại làm điều tương tự. –

+0

Tôi đã nghiên cứu vấn đề này cho một câu hỏi khác về việc truyền các đối tượng được hỗ trợ ngủ đông vào thư viện GSON. Thư viện làm cho một số cuộc gọi đi qua những người triển khai proxy 'Class', và chỉ sau đó là' Object' proxy, và tôi muốn có thể bắt đầu làm một cái gì đó với 'Class'. – Flavio

Trả lời

3

Tôi phát hiện ra, điều này dễ hơn tôi nghĩ: chỉ cần gọi getSuperclass() trên lớp được ủy quyền để lấy lớp gốc chưa được chứng minh. Tôi không chắc chắn như thế nào chung này, nhưng nó xuất hiện để làm việc.

0

Các lớp như test.DBUser$$EnhancerByCGLIB$$40e99a2ddynamic proxies. Khái niệm "lớp thực sự đằng sau" không có ý nghĩa nhiều trong hầu hết các trường hợp. Mỗi lần một proxy được tạo ra, nó có thể là thể hiện của bất kỳ lớp nào như Hibernate định nghĩa nó.

Bạn là gì thực sự yêu cầu là tĩnh Map của { Class<Proxy>, Class<RealObject>}. Tôi không tin rằng có một điều như vậy và tôi không tin rằng có một nhu cầu cho điều này. Chỉ cần nhìn vào nguồn gốc của Hibernate.getClass():

339  public static Class getClass(Object proxy) { 
340  if (proxy instanceof HibernateProxy) { 
341   return ((HibernateProxy) proxy).getHibernateLazyInitializer() 
342     .getImplementation() 
343     .getClass(); 
344  } 
345  else { 
346   return proxy.getClass(); 
347  } 
348 } 

Nó sẽ là rẻ hơn nhiều nhiều việc phải làm một tra cứu bản đồ tĩnh để có được những lớp học thực tế, nhưng Hibernate đi tất cả các cách để initializer lười biếng để có được những lớp thực hiện.

0

Không có phương pháp như vậy. Bạn sẽ cần phải viết một lớp helper để lấy đối tượng được bao bọc và do đó thông tin lớp từ bên trong proxy. Nếu bạn chỉ cần đối tượng trong kịch bản nhất định, hãy cố gắng xóa tất cả tải xuống chậm. Hibernate sau đó sẽ cung cấp cho bạn đối tượng đơn giản.

Cân nhắc cố gắng không cần đối tượng. Có lẽ bạn có thể thiết kế lại ứng dụng để bạn không cần nó, ví dụ bằng cách thêm một trường chứa thông tin mong muốn khi chạy.

3

Trong khi tôi thực sự thích sự đơn giản của cách tiếp cận được đăng bởi Flavio, tôi không thể sử dụng nó trong mã sản xuất trừ khi tài liệu được hỗ trợ. Ngoài ra, nếu bạn gọi .getImplementation() trên LazyInitializer, nó sẽ buộc khởi tạo proxy nếu nó chưa được, đó là một tác động hiệu suất tiêu cực. Tôi đã đưa ra cách tiếp cận này giải quyết cả hai mối quan ngại này:

public static Class<?> getClassForHibernateObject(Object object) { 
    if (object instanceof HibernateProxy) { 
    LazyInitializer lazyInitializer = 
     ((HibernateProxy) object).getHibernateLazyInitializer(); 
    return lazyInitializer.getPersistentClass(); 
    } else { 
    return object.getClass(); 
    } 
} 
Các vấn đề liên quan