如何在Java中构建通用实体存储库

如何在Java中构建通用实体存储库,java,generics,Java,Generics,我有一个通用存储库类,如下所示: public class HibernateRepository<E extends Object, EId> implements EntityRepository<E, EId> { // Many things that are working fine @Override public E getById(EId id) { return entityManager

我有一个通用存储库类,如下所示:

public class HibernateRepository<E extends Object, EId>
       implements EntityRepository<E, EId> {

    // Many things that are working fine    

    @Override
    public E getById(EId id) {
        return entityManager.getReference(E.class, id); // <<< Error here!
    }
}
public class HibernateRepository<E extends Object, EId>
   implements EntityRepository<E, EId> {
    private Class<E> clazz;

    public HibernateRepository(Class<E> clazz) {
        this.clazz = clazz;
    }

    @Override
    public E getById(EId id) {
        return entityManager.getReference(clazz, id); // <<< Error here!
    }
}
请注意,我不想将所需的类传递给方法,因为我已经在类定义中这样做了

此类的用法可以是:

public class MyClassRepositoryHibernate
       extends HibernateRepository<MyClass, Long> {
}
公共类MyClassRepositoryHibernate
延长冬眠期{
}
现在,这个新的存储库在
MyClass
实例上工作,并且
Id
是用
Long
键入的


在Java中可能吗?

您必须将实际的类类型传递给
HibernateRepository的构造函数,并在整个方法中使用它。JVM不知道运行时“E”是什么,因此需要提供具体的类类型

通过在构造函数中使用泛型参数类型,可以确保不会错误地实例化对象,如下所示:

public class HibernateRepository<E extends Object, EId>
       implements EntityRepository<E, EId> {

    // Many things that are working fine    

    @Override
    public E getById(EId id) {
        return entityManager.getReference(E.class, id); // <<< Error here!
    }
}
public class HibernateRepository<E extends Object, EId>
   implements EntityRepository<E, EId> {
    private Class<E> clazz;

    public HibernateRepository(Class<E> clazz) {
        this.clazz = clazz;
    }

    @Override
    public E getById(EId id) {
        return entityManager.getReference(clazz, id); // <<< Error here!
    }
}
公共类HibernateRepository
实施实体报告{
私人课堂;
公共休眠存储(类clazz){
this.clazz=clazz;
}
@凌驾
公共E getById(EId id){

返回entityManager.getReference(clazz,id);//类型将在编译后被擦除,因此不可用。这称为类型擦除。您必须将类对象传递到某个位置。

我在类声明中传递它。这还不够吗?从技术上讲,您不需要。这些信息在编译后被擦除,在运行时未知。这就是泛型在j中的实现方式ava.如果您正在子类化
HibernateRepository
,并在子类中为
E
提供一个具体类型,则该信息可用且可以检索。例如,请参阅Spring的
GenericTypeResolver