用hibernate的Java泛型问题,如何处理T get(K id)

时间:2011-12-28 03:22:36

标签: java hibernate generics

我的GenericDao有:

 public T get(K id);

现在我的GenericDaoImpl有:

public T get(K id) {
    return super.getHibernateTemplate().get(???, id);
  }

我试过了:

get(T.class, id);

但是我收到编译时错误:

cannot select from a type variable

是否有可能以某种方式正确地做到这一点?

4 个答案:

答案 0 :(得分:3)

由于类型擦除,这是不可能的 您需要将Class实例作为参数。

答案 1 :(得分:1)

您需要构建GenericDao,以便能够确定参数化的具体实体类型。例如,SomeEntityDaoImpl应该能够确定它的实体类型是SomeEntity.class。

无论

  1. 在GenericDao中添加一个抽象方法getEntityClass,并在每个DaoImpl中覆盖该方法以提供适当的实体类,或

  2. 使用反射方法自动查找类型参数(我使用了Google Guice中的MoreTypes.getGenericSupertype(),然后是ParameterizedType.getActualTypeArguments()。)

  3. 然后你不必将Class文字传递给get(),因为DaoImpl可以自己调用getEntityClass()。

答案 2 :(得分:1)

我的实施:

public abstract class DAOImpl <T, PK extends Serializable> implements DAO<T, PK>  {


  protected abstract Class<T> getEntityClass();

  public T findById(PK id){
    return (T)getHibernateTemplate().get(getEntityClass(),id);
  }

  protected DetachedCriteria createDetachedCriteria(){
    return DetachedCriteria.forClass(getEntityClass());
  }

  @SuppressWarnings("unchecked")
  public List<T> findAll(){
    return  getHibernateTemplate().findByCriteria(createDetachedCriteria());
   }

}

答案 3 :(得分:0)

如果GenericDaoImpl是抽象的,并且所有实际实现都绑定了TK,那么可以使用反射获取类型参数的值:

abstract class GenericDaoImpl<K, T> {

  public T get(K id) {
    Class<?> valueClazz = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    return super.getHibernateTemplate().get(valueClazz, id);
  }

}

class StringDao extends GenericDaoImpl<Integer, String> {
}

我在ideone创建了一个稍微修改过的示例,但它只打印了类型类,在本例中为String。

这仅适用于StringDao(以及所有其他DAO)是GenericDaoImpl的直接子类时,因此它有点脆弱。就像我说的那样,如果GenericDaoImpl不是抽象的,而是意味着直接使用它将无法工作。在这种情况下,我认为你应该考虑你正在做的是正确的方法。根据我的经验,以这种方式通用的DAO并不能很好地工作。