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 }

浙公网安备 33010602011771号