我的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
是否有可能以某种方式正确地做到这一点?
答案 0 :(得分:3)
由于类型擦除,这是不可能的
您需要将Class
实例作为参数。
答案 1 :(得分:1)
您需要构建GenericDao,以便能够确定参数化的具体实体类型。例如,SomeEntityDaoImpl应该能够确定它的实体类型是SomeEntity.class。
无论
在GenericDao中添加一个抽象方法getEntityClass
,并在每个DaoImpl中覆盖该方法以提供适当的实体类,或
使用反射方法自动查找类型参数(我使用了Google Guice中的MoreTypes.getGenericSupertype()
,然后是ParameterizedType.getActualTypeArguments()
。)
然后你不必将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
是抽象的,并且所有实际实现都绑定了T
和K
,那么可以使用反射获取类型参数的值:
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并不能很好地工作。