DAO基类设计

由于一般的实体类对应 的DAO都必须拥有CRUD操作,与其在每个dao接口中重复定义这些方法,不如提供一个通用的DAO接口,具体的DAO接口可以扩展这个通用DAO接口并定义实体类相关其他操作方法。

BaseDao<T>基类对所有实体DAO接口的通用方法进行抽象并提供泛型的支持,用Hibernate为例,如下:

  1 package com.yutu.dao;
  2 
  3 import java.io.Serializable;
  4 import java.lang.reflect.ParameterizedType;
  5 import java.lang.reflect.Type;
  6 import java.util.List;
  7 import java.util.regex.Matcher;
  8 import java.util.regex.Pattern;
  9 
 10 import org.hibernate.Query;
 11 import org.hibernate.Session;
 12 import org.springframework.beans.factory.annotation.Autowired;
 13 import org.springframework.orm.hibernate3.HibernateTemplate;
 14 import org.springframework.orm.hibernate3.SessionFactoryUtils;
 15 import org.springframework.util.Assert;
 16 
 17 import com.yutu.domain.Board;
 18 /**
 19  * 利用反射
 20  * 定义一个baseDAO ,封装一些通用的方法,如CURD 子类dao只
 21  * 需继承他,就可要拥有增、删、改、查方法,简化dao,和减少重复
 22  * @Class<? super T> getSuperclass():返回本类的父类
 23  * @Type getGenericSuperclass():返回本类的父类,包含泛型参数信息 
 24  * @ParameterizedType 表示参数化类型,如 Collection<String>。 
 25  *  @AA.class.isAssignableFrom(BB.class)的作用是判定AA表示的类或接口
 26  *  是否同参数BB指定的类表示的类或接口相同,
 27  *  或AA是否是BB的父类。
 28  *  public boolean isPrimitive()判定指定的 Class 对象是否表示一个基本类型。
 29  *  Type[] getActualTypeArguments() 得到真正泛型参数类型 如 BaseDAO<T> 中的 T
 30  * 
 31  * DAO基类,其它DAO可以直接继承这个DAO,不但可以复用共用的方法,还可以获得泛型的好处。
 32  */
 33 public class BaseDao<T> {
 34     @Autowired
 35     private HibernateTemplate hibernateTemplate;
 36     private Class<T> entityClass;//对应具体类
 37     /**
 38      * 通过反射获取子类确定的泛型类
 39      */
 40     @SuppressWarnings("unchecked")
 41     public BaseDao(){
 42         Type genType=getClass().getGenericSuperclass();
 43         Type[] params =((ParameterizedType)genType).getActualTypeArguments();
 44         entityClass=(Class)params[0];
 45     }
 46     /**
 47      * 根据ID加载PO实例
 48      * 
 49      * @param id
 50      * @return 返回相应的持久化PO实例
 51      */
 52     public T load(Serializable id) {
 53         return (T) getHibernateTemplate().load(entityClass, id);
 54     }
 55 
 56     /**
 57      * 根据ID获取PO实例
 58      * 
 59      * @param id
 60      * @return 返回相应的持久化PO实例
 61      */
 62     public T get(Serializable id) {
 63         return (T) getHibernateTemplate().get(entityClass, id);
 64     }
 65 
 66     /**
 67      * 获取PO的所有对象
 68      * 
 69      * @return
 70      */
 71     public List<T> loadAll() {
 72         return getHibernateTemplate().loadAll(entityClass);
 73     }
 74     
 75     /**
 76      * 保存PO
 77      * 
 78      * @param entity
 79      */
 80     public void save(T entity) {
 81         getHibernateTemplate().save(entity);
 82     }
 83 
 84     /**
 85      * 删除PO
 86      * 
 87      * @param entity
 88      */
 89     public void remove(T entity) {
 90         getHibernateTemplate().delete(entity);
 91     }
 92 
 93     /**
 94      * 更改PO
 95      * 
 96      * @param entity
 97      */
 98     public void update(T entity) {
 99         getHibernateTemplate().update(entity);
100     }
101 
102     /**
103      * 执行HQL查询
104      * 
105      * @param sql
106      * @return 查询结果
107      */
108     public List find(String hql) {
109         return this.getHibernateTemplate().find(hql);
110     }
111 
112     /**
113      * 执行带参的HQL查询
114      * 
115      * @param sql
116      * @param params
117      * @return 查询结果
118      */
119     public List find(String hql, Object... params) {
120         return this.getHibernateTemplate().find(hql,params);
121     }
122     
123     /**
124      * 对延迟加载的实体PO执行初始化
125      * @param entity
126      */
127     public void initialize(Object entity) {
128         this.getHibernateTemplate().initialize(entity);
129     }
130     
131     
132     /**
133      * 分页查询函数,使用hql.
134      *
135      * @param pageNo 页号,从1开始.
136      */
137     public Page pagedQuery(String hql, int pageNo, int pageSize, Object... values) {
138         Assert.hasText(hql);
139         Assert.isTrue(pageNo >= 1, "pageNo should start from 1");
140         // Count查询
141         String countQueryString = " select count (*) " + removeSelect(removeOrders(hql));
142         List countlist = getHibernateTemplate().find(countQueryString, values);
143         long totalCount = (Long) countlist.get(0);
144 
145         if (totalCount < 1)
146             return new Page();
147         // 实际查询返回分页对象
148         int startIndex = Page.getStartOfPage(pageNo, pageSize);
149         Query query = createQuery(hql, values);
150         List list = query.setFirstResult(startIndex).setMaxResults(pageSize).list();
151 
152         return new Page(startIndex, totalCount, pageSize, list);
153     }
154 
155     /**
156      * 创建Query对象. 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置.
157      * 留意可以连续设置,如下:
158      * <pre>
159      * dao.getQuery(hql).setMaxResult(100).setCacheable(true).list();
160      * </pre>
161      * 调用方式如下:
162      * <pre>
163      *        dao.createQuery(hql)
164      *        dao.createQuery(hql,arg0);
165      *        dao.createQuery(hql,arg0,arg1);
166      *        dao.createQuery(hql,new Object[arg0,arg1,arg2])
167      * </pre>
168      *
169      * @param values 可变参数.
170      */
171     public Query createQuery(String hql, Object... values) {
172         Assert.hasText(hql);
173         Query query = getSession().createQuery(hql);
174         for (int i = 0; i < values.length; i++) {
175             query.setParameter(i, values[i]);
176         }
177         return query;
178     }
179     /**
180      * 去除hql的select 子句,未考虑union的情况,用于pagedQuery.
181      *
182      * @see #pagedQuery(String,int,int,Object[])
183      */
184     private static String removeSelect(String hql) {
185         Assert.hasText(hql);
186         int beginPos = hql.toLowerCase().indexOf("from");
187         Assert.isTrue(beginPos != -1, " hql : " + hql + " must has a keyword 'from'");
188         return hql.substring(beginPos);
189     }
190     
191     /**
192      * 去除hql的orderby 子句,用于pagedQuery.
193      *
194      * @see #pagedQuery(String,int,int,Object[])
195      */
196     private static String removeOrders(String hql) {
197         Assert.hasText(hql);
198         Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", Pattern.CASE_INSENSITIVE);
199         Matcher m = p.matcher(hql);
200         StringBuffer sb = new StringBuffer();
201         while (m.find()) {
202             m.appendReplacement(sb, "");
203         }
204         m.appendTail(sb);
205         return sb.toString();
206     }
207 
208     public HibernateTemplate getHibernateTemplate() {
209         return hibernateTemplate;
210     }
211 
212     public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
213         this.hibernateTemplate = hibernateTemplate;
214     }
215     public  Session getSession() {
216         return SessionFactoryUtils.getSession(hibernateTemplate.getSessionFactory(),true);
217     }
218 }

 


通过扩展BaseDao<T>,我们可以得到一个简化了的FlightDao如下:

 1 package org.spring.basedao;
 2 
 3 import org.spring.pojo.Flight;
 4 
 5 public class FlightDao extends BaseDAO<Flight>{//通过泛型指定实体类为Flight
 6     //子类只需编写特定的DAO方法就可以了,通用方法从基类继承
 7     public Long getNum(){
 8         //TODO do something...
 9         return null;
10     }
11 }
View Code

 

posted @ 2014-09-25 17:01  心飞翔,光阴已逝  阅读(362)  评论(0)    收藏  举报