从泛型T派生类

11

我有一个参数化的Hibernate DAO,用于执行基本的crud操作。当使用参数化委托来实现给定DAO的基本CRUD操作时。

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

我希望能够在运行时从T中派生出Class,以便在Hibernate中创建条件查询,使得:

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

我知道:

T.getClass()

该类不存在,但是否有任何方法可以在运行时从 T 推导出正确的 Class 对象?

我已经查看了泛型和反射,但没有找到合适的解决方案,也许我漏掉了什么。

谢谢。

2个回答

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

    // ....

}

是的,这是我有的一个解决方案。如果可能的话,我更愿意从 T 派生类,而不添加 Class 依赖性。 - bowsie
8
我了解你的痛苦。不幸的是,编译器会完全删除所有 T 的痕迹。这被称为类型擦除:http://java.sun.com/docs/books/tutorial/java/generics/erasure.html - Adam Paynter
@AdamPaynter,向新手解释擦除真的很困难,为什么你可以使用你眼前看到的<T>呢? - Nishant
@Nishant:你说得对。我学习Java时也遇到了同样的情况。它 看起来 应该在那里!这违反了最小惊讶原则。 :) - Adam Paynter

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


1
这只在创建参数化对象的方法(堆栈位置)中起作用。如果您从另一个方法接收参数化对象,则无法使用它。 - Ran Biron
我不确定我理解了。你能再详细解释一下吗?这对 web 应用程序开发有什么影响吗? - rdk
当您直接对通用类进行子类化时,这很有效。如果您有多个继承级别,则需要在figureOutPersistentClass中通过使用getSuperClass来考虑它们。 - David Harkness

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接