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



My GenericDao has:

 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

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

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

您需要构建GenericDao,以便它能够找出它已被参数化的具体实体类型。例如,SomeEntityDaoImpl应该能够计算出它的实体类型是SomeEntity.class。

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

  2. 使用反射方法自动查找类型参数(我使用的是来自Google Guice的MoreTypes.getGenericSupertype(),其次是ParameterizedType.getActualTypeArguments())

那么您就不需要传递Class文字给get(),因为DaoImpl可以自己调用getEntityClass()。

我的实现:
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());
   }
}

如果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并不能很好地工作。

最新更新