2009-04-29 29 views
11

Tôi có dao dao ngủ đông tham số thực hiện các thao tác cơ bản, và khi tham số được sử dụng như một đại biểu để thực hiện các hoạt động crud cơ bản cho một dao đã cho.Lớp phát sinh từ Generic T

public class HibernateDao <T, ID extends Serializable> implements GenericDao<T, ID> 

Tôi muốn để có thể lấy được lớp từ T trong thời gian chạy để tạo ra tiêu chí truy vấn trong Hibernate, chẳng hạn rằng:

public T findByPrimaryKey(ID id) { 
    return (T) HibernateUtil.getSession().load(T.getClass(), id); 
} 

tôi biết:

T.getClass() 

không tồn tại, nhưng có cách nào để lấy được đối tượng Class đúng từ T lúc chạy không?

Tôi đã nhìn vào generics và phản ánh nhưng đã không đưa ra một giải pháp phù hợp, có lẽ tôi đang thiếu một cái gì đó.

Cảm ơn.

Trả lời

17

Bạn có thể có Lớp được truyền làm đối số hàm tạo.

public class HibernateDao <T, ID extends Serializable> implements GenericDao<T, ID> { 

    private final Class<? extends T> type; 

    public HibernateDao(Class<? extends T> type) { 
     this.type = type; 
    } 

    // .... 

} 
+0

Vâng, đây là một giải pháp mà tôi có. Tôi muốn có thể lấy được lớp từ T nếu có thể, mà không cần thêm sự phụ thuộc vào Lớp. – bowsie

+8

@bowsie: Tôi hiểu nỗi đau của bạn. Thật không may, trình biên dịch hoàn thành xóa tất cả dấu vết của T. Nó được gọi là loại tẩy xoá: http://java.sun.com/docs/books/tutorial/java/generics/erasure.html –

+0

Ahh được rồi, cảm ơn Adam. – bowsie

7

Có là cách làm thế nào để tìm ra class kiểu lập luận T sử dụng phản ánh:

private Class<T> persistentClass = (Class<T>) 
    ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 

Dưới đây là cách làm thế nào tôi sử dụng nó:

public class GenericDaoJPA<T> implements GenericDao<T> { 

    @PersistenceContext 
    protected EntityManager entityManager; 

    protected Class<T> persistentClass = figureOutPersistentClass(); 

    private Class<T> figureOutPersistentClass() { 
     Class<T> clazz = (Class<T>)((ParameterizedType) (getClass().getGenericSuperclass())).getActualTypeArguments()[0]; 
     log.debug("persistentClass set to {}", clazz.getName()); 
     return clazz; 
    } 

    public List<T> findAll() { 
     Query q = entityManager.createQuery("SELECT e FROM " + persistentClass.getSimpleName() + " e"); 
     return (List<T>) q.getResultList(); 
    } 

} 

Tôi cho rằng chỉ này hoạt động khi ConcreteEntityDao của bạn là một siêu lớp trực tiếp của HibernateDao<ConcreteEntity,...>.

Tôi đã tìm thấy nó ở đây: www.greggbolinger.com/blog/2008/04/17/1208457000000.html

+1

điều này chỉ hoạt động theo phương thức (vị trí ngăn xếp) tạo đối tượng được tham số hóa. Nó không hoạt động nếu bạn nhận được đối tượng được tham số hóa từ phương thức khác. –

+0

Tôi không chắc mình hiểu. Bạn có thể giải thích nó chi tiết hơn một chút không? Có bất kỳ ý nghĩa nào đối với việc phát triển ứng dụng web không? – rdk

+0

Điều này làm việc tuyệt vời khi bạn phân lớp trực tiếp lớp chung. Nếu bạn có nhiều cấp độ thừa kế, bạn sẽ cần phải tính toán chúng trong 'figureOutPersistentClass' bằng cách sử dụng' getSuperClass'. –

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