泛型DAO设计(转本站的yongtree,谢谢)

xiaoxiao2022-06-12  36

 

泛型是JDK1.5的一个新的特性,使用泛型机制编写的程序代码要比那些杂乱的使用Object变量,然后再进行强制类型转换的代码具有更好的安全性和可读性。如果你的系统运行在JDK1.5以上的版本上,建议多使用泛型来代替无休止的对象转换。          在软件设计中我们开始对系统进行三层甚至是多层架构了,目的是职责更加的明确,功能更加的分离。而常常使用的三层架构就是将表现层、业务逻辑层和持久层进行分离,每一层关注点不同,职能更加的清晰。所以DAO的设计模式现在已经被我们所接受,下面就介绍一下泛型DAO的设计和实现。          这次的DAO例子是基于接口的.很多工具, 像Hibernate已经提供了数据库的便携访问,所以我们不是为持久层的轻便而设计接口. 然而, DAO接口在较为复杂的应用中更有意义, 当有几个持久化服务被封装到一个持久层的时候, 我想在很多情况下你应该直接使用Hibernate或者JPA, 而使用外加的DAO层最好的理由是为了实现更高的抽象化(例如:定义方法名findAll(String hql)而不是无数次地重复session.createQuery(...)) 通用DAO接口: package com.baiyyy.util.dao; import java.io.Serializable; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.hibernate.Criteria; import org.hibernate.LockMode; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.DetachedCriteria; /** * 承有业务数据的基础访问接口 * <p> * 承有CRUD (创建,读取,修改和删陿)基本数据的操作在这个接口中都是独立的_ 并且承有的DAO都可以使用这些基本实玿 * * @author yongtree * * @date:2008-03-04 */ public interface IBaseDAO<T, ID extends Serializable> {   /***************************************************************************    * -------------------基本棿索㿁增加㿁修改㿁删除操使---------------------------- *    **************************************************************************/   // --------findById()方法是鿚过get(ID id)得到实体对象-----------------------   /**    * 通过ID来得到实体对豿    *    * @param id    *            实体对象的标识符    * @param lock    *            使用的锁模式    * @return 该主键忼对应的实体对象    */   public T findById(ID id, LockMode lock);   /**    * 通过ID来得到实体对豿    *    * @param id    * @return T    */   public T findById(ID id);   /**    * 通过ID来得到实体对豿(为兼容其他开发成员的原有程序,保留使甿)    *    * @param c    * @param id    * @return T    */   public T findById(Class c, ID id);   // -------------loadById()是调用hibernate的load方法------------   public T loadById(ID id);   /**    * 通过id load对象    *    * @param id    * @param lock    * @return    */   public T loadById(ID id, LockMode lock);   /**    * 获取全部的实使    *    * @return    */   public List<T> loadAll();   /**    * 保存丿个实体对豿    *    * @param entity    */   public T saveEntity(T entity);   /**    * 更新丿个实体对豿    *    * @param entity    */   public void updateEntity(T entity);   public void updateEntity(T entity, LockMode lock);   /**    * 增加或更新集合中的全部实使    *    * @param entities    */   public void saveOrUpdateAll(Collection<T> entities);   /**    * 删除丿个实使    *    * @param entity    * @throws Exception    */   public void deleteEntity(T entity);   public void deleteEntity(T entity, LockMode lock);   /**    * 根据主键删除指定实体    *    * @param id    */   public void deleteEntityById(ID id);   public void deleteEntityById(ID id, LockMode lock);   /**    * 批量删除    *    * @param entities    */   public void deleteAll(Collection<T> entities);   /**    * 通过合并的方式更新对豿    *    * @param entity    *            void    */   public void merge(T entity);   /***************************************************************************    * ------------------------------使用HQL语句-------------------------------- *    **************************************************************************/   /**    * 使用HQL语句进行对象的查诿    *    * @param hsql    *            查询语句    * @return 符合条件的对豿    */   public T getEntity(String hsql);   /**    * 使用HQL语句进行查询    *    * @param hsql    *            查询语句    * @return 符合条件的对象集吿    */   public List<T> getEntities(String hsql);   /**    * 使用带参数的HQL语句进行查询    *    * @param hsql    * @param obj    * @return    */   public List<T> getEntities(String hsql, Object[] values);   public List<T> getEntities(String hql, int start, int number);   public List<T> getEntities(String hql, int start, int number,       Object[] values);   /**    * 使用命名的HQL语句棿索数捿    *    * @param queryName    * @return    */   public List<T> findByNamedQuery(String queryName);   /**    * 使用带参数的命名HSQL语句棿索数捿    *    * @param queryName    * @param values    * @return    */   public List<T> findByNamedQuery(String queryName, Object[] values);   /**    * 使用带命名参数的命名HSQL语句棿索数捿    *    * @param queryName    * @param paramNames    * @param values    * @return    */   public List<T> findByNamedQuery(String queryName, String[] paramNames,       Object[] values);   /**    * 使用HQL语句棿索数据,返回 Iterator    *    * @param queryString    * @return    */   public Iterator<T> iterate(String queryString);   /**    * 使用带参数HSQL语句棿索数据,返回 Iterator    *    * @param queryString    * @param values    * @return    */   public Iterator<T> iterate(String queryString, Object[] values);   /***************************************************************************    * -----------------------------Criteria动濁查诿---------------------------- *    **************************************************************************/   /**    * 创建与会话无关的棿索标准对豿    */   public DetachedCriteria createDetachedCriteria();   /**    * 创建与会话绑定的棿索标准对豿    *    * @return    */   public Criteria createCriteria();   /**    * 使用指定的检索标准检索数捿    *    * @param criteria    * @return    */   public List<T> findByCriteria(DetachedCriteria criteria);   /**    * 使用指定的检索标准检索数据,返回部分记录    *    * @param criteria    * @param firstResult    * @param maxResults    * @return    */   public List<T> findByCriteria(DetachedCriteria criteria, int firstResult,       int maxResults);   /**    * 通过动濁查询条件进行查诿    *    * @param criterion    * @return List<T>    */   @SuppressWarnings("unchecked")   public List<T> findByCriteria(Criterion... criterion);   /**    * 使用指定的检索标准检索数据,返回指定范围的记彿    *    * @param criteria    * @return    */   public Integer getRowCount(DetachedCriteria criteria);   /**    * 使用指定的检索标准检索数据,返回指定统计倿    *    * @param criteria    * @param propertyName    * @param StatName    *            (max,min,avg,sum)    * @return    */   public Object getStatValue(DetachedCriteria criteria, String propertyName,       String StatName);   /**    * 通过给定的一个对象,查找与其匹配的对象,表关联比较多时,用户可以自己根据霿要扩展㿿    *    * @param entity    * @return List<T>    */   public List<T> findByExample(T entity);   /***************************************************************************    * -------------------------Others ----------------------------------------*    **************************************************************************/   /**    * 加锁指定的实使    *    * @param entity    * @param lockMode    */   public void lock(T entity, LockMode lockMode);   /**    * 强制立即更新缓冲数据到数据库(否则仅在事务提交时才更新)    */   public void flush();   /**    * 清空缓存    *    * void    */   public void clear();   /***************************************************************************    * --------------------------------相关知识炿--------------------------------*    *    * 1、Session的load方法和get方法都是通过给定的ID从数据库中加载一个持久化的对象㿂但两个斿*    * 法的区别在于:当数据库不存在于ID对应的记录时,load()方法抛出异常,迌get()方法返回null*    ***************************************************************************/ } 设计完接口,我们就要实现我们创建的接口,我们如果使用Hibernate,那么就做一个hibernate的实现,如果使用JPA,那么就做一个JPA实现。以下采用hibernate进行实现。 通用Hibernate DAO实现: package com.baiyyy.util.dao; /** * @filename:BaseHibernateDAO.java */ import java.io.Serializable; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.hibernate.Criteria; import org.hibernate.LockMode; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.Example; import org.hibernate.criterion.MatchMode; import org.hibernate.criterion.Projections; import com.baiyyy.workflow.pojo.TWfPackage; /** * 用Hibernate实现通用DAO接口 * * @author yongtree * @date 2008-3-10 * @param <T> * @param <ID> */ public class BaseHibernateDAO<T, ID extends Serializable> implements     IBaseDAO<T, ID> {   // 保持实体对象类的类型   private Class<T> persistentClass;   private Session session;   /**    * 构鿠方泿    */   @SuppressWarnings("unchecked")   public BaseHibernateDAO() {     //下面这种方式丿直有错误,不能得到真正的T.class,迌是Object.class     // this.persistentClass=GenericsUtils.getSuperClassGenricType(getClass());     // System.out.println(obj.getClass().getName());   }   @SuppressWarnings("unchecked")   public BaseHibernateDAO(Class clazz) {     this.persistentClass = clazz;   }   /**    * @param session    *            the session to set    */   public void setSession(Session session) {     this.session = session;   }   /**    * 得到当前线程的Session对象的实便    *    * @return    */   protected Session getSession() {     System.out.println("get session");     return HibernateUtil.getCurrentSession();   }   /**    * 得到持久化对象的类型    *    * @return 持久化类的类垿    */   protected Class<T> getPersistentClass() {     return persistentClass;   }   @SuppressWarnings("unchecked")   public T findById(ID id, LockMode lock) {     // TODO Auto-generated method stub     T entity = (T) getSession().get(getPersistentClass(), id, lock);     if (entity != null) {       this.flush();     }     return entity;   }   @SuppressWarnings("unchecked")   public T findById(Class c, ID id) {     // TODO Auto-generated method stub     T entity;     entity = (T) getSession().get(c, id);     return entity;   }   @SuppressWarnings("unchecked")   public T findById(ID id) {     // TODO Auto-generated method stub     T entity = (T) getSession().get(getPersistentClass(), id);     return entity;   }   @SuppressWarnings("unchecked")   public T loadById(ID id) {     // TODO Auto-generated method stub     T entity = (T) getSession().load(getPersistentClass(), id);     return entity;   }   @SuppressWarnings("unchecked")   public T loadById(Class c, ID id) {     // TODO Auto-generated method stub     T entity = (T) getSession().load(c, id);     return entity;   }   @SuppressWarnings("unchecked")   public T loadById(ID id, LockMode lock) {     // TODO Auto-generated method stub     T entity = (T) getSession().load(getPersistentClass(), id, lock);     return entity;   }   @SuppressWarnings("unchecked")   public List<T> loadAll() {     List<T> list = getSession().createQuery(         "from " + getPersistentClass().getName()).list();     return list;   }   public T saveEntity(T entity) {     // TODO Auto-generated method stub     getSession().save(entity);     this.flush();     return entity;   }   public void updateEntity(T entity) {     // TODO Auto-generated method stub     getSession().saveOrUpdate(entity);     this.flush();   }   /**    * 该实现类暂时没有实现更新加锁的操使    */   public void updateEntity(T entity, LockMode lock) {     // TODO Auto-generated method stub     getSession().saveOrUpdate(entity);     this.flush();   }   public void saveOrUpdateAll(Collection<T> entities) {     getSession().saveOrUpdate(entities);     this.flush();   }   public void deleteEntity(T entity) {     // TODO Auto-generated method stub     getSession().delete(entity);     this.flush();   }   /**    * 该实现没有实现加锁删除对象的操作,在spring的DAO实现中已经实玿    */   public void deleteEntity(T entity, LockMode lock) {     // TODO Auto-generated method stub     getSession().delete(entity);     this.flush();   }   public void deleteEntityById(ID id) {     this.deleteEntity(this.loadById(id));     this.flush();   }   // 该实现没有实现加锁的删除,在spring的dao中已经实现了   public void deleteEntityById(ID id, LockMode lock) {     this.deleteEntity(this.loadById(id));     this.flush();   }   public void deleteAll(Collection<T> entities) {     this.flush();     getSession().delete(entities);   }     public void merge(T entity){     getSession().merge(entity);     this.flush();   }   @SuppressWarnings("unchecked")   public T getEntity(String hsql) {     T uniqueResult = (T) getSession().createQuery(hsql).uniqueResult();     // TODO Auto-generated method stub     return uniqueResult;   }   @SuppressWarnings("unchecked")   public List<T> getEntities(String hsql) {     // TODO Auto-generated method stub     List list = getSession().createQuery(hsql).list();     return list;   }   @SuppressWarnings("unchecked")   public List<T> getEntities(String hql, int start, int number,       Object[] values) {     // TODO Auto-generated method stub     Query query = getSession().createQuery(hql);     for (int i = 0; i < values.length; i++) {       query.setParameter(i, values[i]);     }     query.setFirstResult(start);     query.setMaxResults(number);     List list = query.list();     return list;   }   @SuppressWarnings("unchecked")   public List<T> getEntities(String hql, int start, int number) {     // TODO Auto-generated method stub     Query query = getSession().createQuery(hql);     query.setFirstResult(start);     query.setMaxResults(number);     List list = query.list();     return list;   }   @SuppressWarnings("unchecked")   public List<T> getEntities(String hql, Object[] values) {     // TODO Auto-generated method stub     Query query = getSession().createQuery(hql);     for (int i = 0; i < values.length; i++) {       query.setParameter(i, values[i]);     }     return query.list();   }   @SuppressWarnings("unchecked")   public List<T> findByNamedQuery(String queryName) {     // TODO Auto-generated method stub     return getSession().getNamedQuery(queryName).list();   }   @SuppressWarnings("unchecked")   public List<T> findByNamedQuery(String queryName, Object[] values) {     // TODO Auto-generated method stub     Query query = getSession().getNamedQuery(queryName);     for (int i = 0; i < values.length; i++) {       query.setParameter(i, values);     }     return query.list();   }   /**    * 注意:该方法是鿚过设置参数来进行命名查询,承以在传参数时,一定要注意paramNames和values的长度,位置要一丿对应〿    */   @SuppressWarnings("unchecked")   public List<T> findByNamedQuery(String queryName, String[] paramNames,       Object[] values) {     // TODO Auto-generated method stub     Query query = getSession().getNamedQuery(queryName);     for (int i = 0; i < paramNames.length; i++) {       query.setParameter(paramNames[i], values[i]);     }     return query.list();   }   @SuppressWarnings("unchecked")   public Iterator<T> iterate(String hql) {     // TODO Auto-generated method stub     return getSession().createQuery(hql).iterate();   }   @SuppressWarnings("unchecked")   public Iterator<T> iterate(String hql, Object[] values) {     // TODO Auto-generated method stub     Query query = getSession().createQuery(hql);     for (int i = 0; i < values.length; i++) {       query.setParameter(i, values[i]);     }     return query.iterate();   }   public DetachedCriteria createDetachedCriteria() {     // TODO Auto-generated method stub     return DetachedCriteria.forClass(this.persistentClass);   }   public Criteria createCriteria() {     // TODO Auto-generated method stub     return this.createDetachedCriteria().getExecutableCriteria(         this.getSession());   }   /**    * 该方法没有经过验证,不能保证正确,在spring的实现中已经实现亿    */   @SuppressWarnings("unchecked")   public List<T> findByCriteria(DetachedCriteria criteria) {     // TODO Auto-generated method stub     return criteria.getExecutableCriteria(this.getSession()).list();   }   @SuppressWarnings("unchecked")   public List<T> findByCriteria(DetachedCriteria criteria, int firstResult,       int maxResults) {     // TODO Auto-generated method stub     return criteria.getExecutableCriteria(this.getSession())         .setFirstResult(firstResult).setMaxResults(maxResults).list();   }   /**    * 动濁查诿    *    * @param criterion    * @return    */   public @SuppressWarnings("unchecked")   List<T> findByCriteria(Criterion... criterion) {     Criteria crit = getSession().createCriteria(getPersistentClass());     for (Criterion c : criterion) {       if (c != null) {         crit.add(c);       }     }     List list = crit.list();     return list;   }   @SuppressWarnings("unchecked")   public Integer getRowCount(DetachedCriteria criteria) {     // TODO Auto-generated method stub     criteria.setProjection(Projections.rowCount());     List list = this.findByCriteria(criteria, 0, 1);     return (Integer) list.get(0);   }   @SuppressWarnings("unchecked")   public Object getStatValue(DetachedCriteria criteria, String propertyName,       String StatName) {     // TODO Auto-generated method stub     if (StatName.toLowerCase().equals("max"))       criteria.setProjection(Projections.max(propertyName));     else if (StatName.toLowerCase().equals("min"))       criteria.setProjection(Projections.min(propertyName));     else if (StatName.toLowerCase().equals("avg"))       criteria.setProjection(Projections.avg(propertyName));     else if (StatName.toLowerCase().equals("sum"))       criteria.setProjection(Projections.sum(propertyName));     else       return null;     List list = this.findByCriteria(criteria, 0, 1);     return list.get(0);   }   @SuppressWarnings("unchecked")   public List<T> findByExample(T exampleInstance) {     // TODO Auto-generated method stub     Criteria crit = getSession().createCriteria(getPersistentClass());     Example example = Example.create(exampleInstance);     example.ignoreCase().enableLike(MatchMode.ANYWHERE);// 忽略大小写,并进行模糊比辿     example.excludeZeroes();// 对于属濧中有数字类型的,如果exampleInstance的属性忼为0,就把它添加到查询中     crit.add(example);     return crit.list();   }   public void lock(T entity, LockMode lockMode) {     // TODO Auto-generated method stub     getSession().lock(entity, lockMode);   }   public void flush() {     // TODO Auto-generated method stub     getSession().flush();   }   public void clear() {     // TODO Auto-generated method stub     getSession().clear();   } } 到现在为止,Hibernate通用DAO已经建立完成,作为一个通用的工具类,我们希望每个实体DAO都能继承这个DAO。继续发扬接口编程,每一个持久化实体类我们都建立一个接口,并且让这些接口都继承IBaseDAO。 ParticipantDAO的写法: public interface ParticipantDAO extends IBaseDAO<TWfParticipants, Integer>{   //自定义该实体的接口 } ParticipantDAO实现类的写法: public class ParticipantDAOImpl extends     BaseHibernateDAO<TWfParticipants, Integer> implements     ParticipantDAO {   public ParticipantDAOImpl() {     super(TWfParticipants.class);   }    //实现自定义的方法 } 注:在BaseHibernateDAO的无参数构造函数中 public BaseHibernateDAO() {     //下面这种方式一直有错误,不能得到真正的T.class,迌是Object.class     // this.persistentClass=GenericsUtils.getSuperClassGenricType(getClass());   } 这种方式的写法在springside中使用过,但是自己调试始终有错误,始终无法得到T.class,得到的只是Oject.class,不知道怎么解决,还请高人指点。 以下是我的替代方法,可能不是太好。构建一个带有Class参数的构造函数,让每个DAO硬性传入class。 public BaseHibernateDAO(Class clazz) {     this.persistentClass = clazz;   } 然后在子类DAO的构造参数中向父类传递一个class,因为一个DAO对应着一个实体,所以传入一个实体的class也是没有什么不可以的。 public ParticipantDAOImpl() {     super(TWfParticipants.class);   } 补充GenericsUtils.java: public class GenericsUtils {   private static final Log log = LogFactory.getLog(GenericsUtils.class);   private GenericsUtils() {   }   /**    * 通过反射,获得定义Class时声明的父类的范型参数的类型. 如public BookManager extends GenricManager<Book>    *    * @param clazz    *            The class to introspect    * @return the first generic declaration, or <code>Object.class</code> if    *         cannot be determined    */   public static Class getSuperClassGenricType(Class clazz) {     return getSuperClassGenricType(clazz, 0);   }   /**    * 通过反射,获得定义Class时声明的父类的范型参数的类型. 如public BookManager extends GenricManager<Book>    *    * @param clazz    *            clazz The class to introspect    * @param index    *            the Index of the generic ddeclaration,start from 0.    */   public static Class getSuperClassGenricType(Class clazz, int index)       throws IndexOutOfBoundsException {     Type genType = clazz.getGenericSuperclass(); //    Type genType = clazz;     if (!(genType instanceof ParameterizedType)) {       log.warn(clazz.getSimpleName()           + "'s superclass not ParameterizedType");       return clazz;     }     Type[] params = ((ParameterizedType) genType).getActualTypeArguments();     if (index >= params.length || index < 0) {       log.warn("Index: " + index + ", Size of " + clazz.getSimpleName()           + "'s Parameterized Type: " + params.length);       return Object.class;     }     if (!(params[index] instanceof Class)) {       log           .warn(clazz.getSimpleName()               + " not set the actual class on superclass generic parameter");       return Object.class;     }     return (Class) params[index];   } } 在实际的项目中,我们常常忽略了业务逻辑层,我们有人喜欢将大部分的逻辑放在表现层的Java Bean中,也有人喜欢在DAO中编写自己的业务逻辑,虽然功能都能实现,但是职责不明,让我们面对这些杂乱无章的代码,我们无所适从。泛型DAO的设计我感觉很大程度上可以强制程序员不要在DAO中书写自己的逻辑代码,也让我们慢慢的建立自己业务逻辑层(在EJB,spring这样的框架没有引入的情况下)。 当然为了系统的可扩展性、可移植性和系统的松耦合,我们可以采用DAO工厂模式和反射机制来架构我们的系统,由于篇幅有限,这里就不做介绍了。这部分内容我将在以后的时间里进行整理并发布在我的csdn博客和javaeye博客上。 yongtree 2008-3-11 晚
转载请注明原文地址: https://www.6miu.com/read-4933388.html

最新回复(0)