在没有泛型支持的情况下查询实体,不但要指定主键值还需要指定实体类型,不但方法入参比较复杂,调用者还需要对返回的结果对象进行强制类型转换,这两种缺点都可以通过在基类中引入泛型得到彻底的克服。
代码清单 13 HibernateBaseDao<T>:DAO基类
③-1通过代理模板类、泛型反射获取实体类的类型的机制得到了优雅的接口package com.baobaotao.dao; import java.io.Serializable; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; public class HibernateBaseDao<T> extends HibernateDaoSupport implements BaseDao<T>...{ private Class<T> entityClass; ①实体类的类型 public HibernateBaseDao() ...{②通过反射机制获取泛型对应的实体类的类型 Type genType = getClass().getGenericSuperclass(); Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); entityClass = (Class)params[0]; }
基类HibernateBaseDao<T>扩展于HibernateDaoSupport并实现了通用接口。此外,还可以在该类中提供更多方便的操作方法化解子类的实现难度。这样,子类仅需要指定泛型对应的实体类就拥有了各种通用的数据操作能力。如果实体DAO的数据操作仅是一些常见的CRUD等操作,子类甚至可以不编写一行代码,实体DAO编码生产率将提到极大的提高,抽象性上升了一个新的台阶。通过扩展HibernateBaseDao<T>我们可以得到一个被极大简化的ForumHibernateDao版本:public T get(Serializable id) ...{ return (T)getHibernateTemplate().load(entityClass, id); } public List<T> getAll() ...{③-2 return getHibernateTemplate().loadAll(entityClass); } public void save(Object o) ...{ getHibernateTemplate().saveOrUpdate(o); } public void remove(Object o) ...{ getHibernateTemplate().delete(o); } public void update(Object o) ...{ getHibernateTemplate().update(o); } … }
①通过扩展泛型的DAO基类自动拥有常见功能的操作package com.baobaotao.dao.hibernate; …
通过扩展HibernateBaseDao<T>基类并借由泛型指定实体类,ForumHibernateDao立即拥有了对Forum实例进行CRUD操作的功能,并且这些功能都是泛型版本的:如当你调用ForumHibernateDao#get(Serializable id)时,将直接返回Forum类型的实体对象。因此在ForumHibernateDao类中你仅需要对那些非通用的数据操作提供自定义方法就大功告成了。按照相似的方式,我们还可以轻松完成对TopicHibernateDao、PostHibernateDao的改造,你将发现DAO层的代码质量拥有了一个不小的飞跃。public class ForumHibernateDao extends HibernateBaseDao<Forum> implements ForumDao...{ public long getForumNum() ...{②非常见的数据访问方法 Iterator iter = getHibernateTemplate().iterate( "select count(f.forumId) from Forum f"); return ((Long)iter.next()); } }