2009-04-29 130 views
11

我有一个参数化的hibernate dao,它执行基本的crud操作,并且当参数化时用作委托来完成给定dao的基本crud操作。从泛型T派生类

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

我希望能够在运行时创建Hibernate的标准查询在T派生类,使得:

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

我知道:

T.getClass() 

不存在,但有什么办法在运行时从T派生正确的类对象吗?

我已经看过泛型和反射,但还没有拿出一个合适的解决方案,也许我失去了一些东西。

谢谢。

回答

17

您可以将该类作为构造函数参数传递。

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

是的,这是一个解决方案,我有。如果可能的话,我宁愿能够从T派生类,而不添加类依赖。 – bowsie 2009-04-29 11:52:03

+8

@bowsie:我明白你的痛苦。不幸的是,编译器完成删除T的所有痕迹。它被称为类型擦除:http://java.sun.com/docs/books/tutorial/java/generics/erasure.html – 2009-04-29 12:07:18

7

有怎样的方式使用反射来找出类型参数Tclass

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

这里就是这样,我如何使用它:

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(); 
    } 

} 

我想这只是当您的ConcreteEntityDaoHibernateDao<ConcreteEntity,...>的直接超类时有效。

我发现在这里:www.greggbolinger.com/blog/2008/04/17/1208457000000.html