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

时间:2015-04-13 15:16:02

标签: 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.getReference(E.class, id); // <<< Error here!
    }
}

方法getById()应该返回给定Id的某个实体实例。在许多其他情况下,这是非常微不足道的,但在这一情况下,因为编译器返回:

Illegal class literal for the type parameter E

请注意,我想要将所需的类传递给该方法,因为我已经在类定义中执行了此操作。

此课程的用法可能是:

public class MyClassRepositoryHibernate
       extends HibernateRepository<MyClass, Long> {
}

现在,此新存储库适用于MyClass个实例,而Id则使用Long键入。

这可能在Java中吗?

2 个答案:

答案 0 :(得分:2)

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

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

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

疼痛,但由于类型擦除是必要的。

答案 1 :(得分:0)

编译后将删除该类型,因此无法使用。这称为类型擦除。你必须在某处传递Class对象。