以前从springside2.0上搞下来的很好用的,基本实现dao零编码只要配置xml文件就行了。
先看图:
一共4层,com.demonstration.hibernate.basedao是我加的用来进一步解耦hibernate和spring的耦合。 原来的官方解释如下: SpringSide对Hibernate做了三层封装:
第一层:HibernateGenericDao,基于spring的HibernateDaoSupport,但加入了分页函数与各种Finder函数,并使用泛型避免了返回值强制类型转换。
第二层:HibernateEntityDao,基于HibernateGenericDao,用泛型声明Dao所管理的Entity类,默认拥有该entity的CRUD方法。
第三层:HibernateExtendDao,基于HibernateEntityDao,主要扩展各种选择性的功能。
关于三个类的详细注解请看JavaDoc,大致描述如下:
1 HibernateGenericDao 在Spring HibernateDaoSupport基础上封装的DAO,功能如下:
1.应用泛型:使得find(), get() 这些函数不再返回Object,而是返回T,不再需要强制类型转换。
2.提供各种finder的简便函数 应用了JDK5可变参数的hsql查询函数:List find(String hql, Object... values),支持find(hql),find(hql, param1); find(hql,param1,param2);find(hql,new Object[] {param1,param2}) 四种接口。
简单查询的简化函数:findBy(Class entityClass,String name,Object value) ,findUniqueBy(Class entityClass,String name, Object value),findByLike(Class entityClass,String name,Object value)
3.获得设置好的Query和Criteria:createQuery(String hql,Object... values) 和 createCriteria(Class<T> entityClass,Criterion... criterions)
Spring并没有很好的接口封装支持firstResult, maxResult, fetchsize,cache,cacheRegion 等多个查询参数,所以springside宁愿返回已设置好查询条件的Query和Criteria,让大家继续剩下的参数设置,最后再执行 list(),注意那几个参数可以连续设置的,如:
createQuery(hql,param1).setFirstResult(10).setMaxResult(20).list(); 4.分页函数:Page pagedQuery(Criteria criteria, int pageNo, int pageSize) 和Page pagedQuery(String hql, int pageNo, int pageSize, Object... args)
Page是SpringSide自行封装的一个典型Page类,pagedQuery与hibernate自身分页查询的差别是先运行一次count,获得符合条件的总记录数。
如果查询不需要总记录数,用普通的hibernate API,加上setFirstResult(),setMaxResult()就解决,不需要pagedQuery()。
5.判别对象属性在数据库中唯一的函数:isUnique(Class<T> entityClass,Object entity,String names)。
2. HibernateEntityDao 所有UserManager, ProductManager之类只管理一类对象的Manager类的基类,只需要在类定义处声明Entity类型即可
public class BookManager extends HibernateEntityDao<Book> { } 通过<Book>的定义,避免了HibernateGenericDao类各方法中必有的Class entityClass参数。
如果需要操作其他的Entity,比如BookManager可能需要处理Category(图书目录),可以注入CategoryManager。无需担心事务的问题,JavaEE的默认事务模型已能很好处理。
如果没有对应的CategoryManager,或者各种原因不想注入的话,可以使用BookManager继承自 HibernateGenericDao的带entityClass参数的函数来操作Category的增删改,如Category category= this.get(Category.class, 1);
3. HibernateExtendDao 此类演示SpringSide 所作的一些扩展,大家可以按照自己的需要进行修改和扩展。
1. 支持对象不能被直接删除,只能设置状态列为无效。 接口UndeleteableEntityOperation,定义了要支持此功能必须实现的函数。
可以有接口(UndeletableEntity)和annotation(@Undeletable)两种形式来定义无效列,annotation列形式还可以定义标识对象已删除的状态属性的名称,用接口则必须实现setStatus()接口,在里面操作实际的状态属性。
第四层就是把HibernateEntityDao和HibernateExtendDao以属性注入的方式注入到basedao,IBasedao就全局接口程序中使用的就是它,这个接口的实现全调用HibernateEntityDao和HibernateExtendDao的方法。方便以后的更改和替换,这样IBasedao接口不变就不要修改业务层的代码了。
代码如下(从下到上):
1 Page.java
2 package com.demonstration.hibernate.dao.support;
3 import java.io.Serializable;
4 import java.util.ArrayList;
5 /**
6 * 分页对象. 包含当前页数据及分页信息如总记录数.
7 *
8 * @author springside
9 *
10 */
11 @SuppressWarnings("serial")
12 public class Page implements Serializable {
13 private static int DEFAULT_PAGE_SIZE = 20;
14 private int pageSize = DEFAULT_PAGE_SIZE; // 每页的记录数
15 private long start; // 当前页第一条数据在List中的位置,从0开始
16 private Object data; // 当前页中存放的记录,类型一般为List
17 private long totalCount; // 总记录数
18 /**
19 * 构造方法,只构造空页.
20 */
21 @SuppressWarnings("unchecked")
22 public Page() {
23 this(0, 0, DEFAULT_PAGE_SIZE, new ArrayList());
24 }
25 /**
26 * 默认构造方法.
27 *
28 * @param start 本页数据在数据库中的起始位置
29 * @param totalSize 数据库中总记录条数
30 * @param pageSize 本页容量
31 * @param data 本页包含的数据
32 */
33 public Page(long start, long totalSize, int pageSize, Object data) {
34 this.pageSize = pageSize;
35 this.start = start;
36 this.totalCount = totalSize;
37 this.data = data;
38 }
39 /**
40 * 取总记录数.
41 */
42 public long getTotalCount() {
43 return this.totalCount;
44 }
45 /**
46 * 取总页数.
47 */
48 public long getTotalPageCount() {
49 if (totalCount % pageSize == 0)
50 return totalCount / pageSize;
51 else
52 return totalCount / pageSize + 1;
53 }
54 /**
55 * 取每页数据容量.
56 */
57 public int getPageSize() {
58 return pageSize;
59 }
60 /**
61 * 取当前页中的记录.
62 */
63 public Object getResult() {
64 return data;
65 }
66 /**
67 * 取该页当前页码,页码从1开始.
68 */
69 public long getCurrentPageNo() {
70 return start / pageSize + 1;
71 }
72 /**
73 * 该页是否有下一页.
74 */
75 public boolean hasNextPage() {
76 return this.getCurrentPageNo() < this.getTotalPageCount() - 1;
77 }
78 /**
79 * 该页是否有上一页.
80 */
81 public boolean hasPreviousPage() {
82 return this.getCurrentPageNo() > 1;
83 }
84 /**
85 * 获取任一页第一条数据在数据集的位置,每页条数使用默认值.
86 *
87 * @see #getStartOfPage(int,int)
88 */
89 protected static int getStartOfPage(int pageNo) {
90 return getStartOfPage(pageNo, DEFAULT_PAGE_SIZE);
91 }
92 /**
93 * 获取任一页第一条数据在数据集的位置.
94 *
95 * @param pageNo 从1开始的页号
96 * @param pageSize 每页记录条数
97 * @return 该页第一条数据
98 */
99 public static int getStartOfPage(int pageNo, int pageSize) {
100 return (pageNo - 1) * pageSize;
101 }
102 }
103 GenericsUtils.java
104 package com.demonstration.hibernate.dao.support;
105 import java.lang.reflect.ParameterizedType;
106 import java.lang.reflect.Type;
107 import org.apache.commons.logging.Log;
108 import org.apache.commons.logging.LogFactory;
109 /**
110 * Generics的util类.
111 *
112 * @author springside
113 *
114 */
115 public class GenericsUtils {
116 private static final Log log = LogFactory.getLog(GenericsUtils.class);
117 private GenericsUtils() {
118 }
119 /**
120 * 通过反射,获得定义Class时声明的父类的范型参数的类型. 如public BookManager extends GenricManager<Book>
121 *
122 * @param clazz The class to introspect
123 * @return the first generic declaration, or <code>Object.class</code> if cannot be determined
124 */
125 @SuppressWarnings("unchecked")
126 public static Class getSuperClassGenricType(Class clazz) {
127 return getSuperClassGenricType(clazz, 0);
128 }
129 /**
130 * 通过反射,获得定义Class时声明的父类的范型参数的类型. 如public BookManager extends GenricManager<Book>
131 *
132 * @param clazz clazz The class to introspect
133 * @param index the Index of the generic ddeclaration,start from 0.
134 * @return the index generic declaration, or <code>Object.class</code> if cannot be determined
135 */
136 @SuppressWarnings("unchecked")
137 public static Class getSuperClassGenricType(Class clazz, int index) {
138 Type genType = clazz.getGenericSuperclass();
139 if (!(genType instanceof ParameterizedType)) {
140 log.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
141 return Object.class;
142 }
143 Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
144 if (index >= params.length || index < 0) {
145 log.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
146 + params.length);
147 return Object.class;
148 }
149 if (!(params[index] instanceof Class)) {
150 log.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
151 return Object.class;
152 }
153 return (Class) params[index];
154 }
155 }
156
157
158 BeanUtils.java
159
160 package com.demonstration.hibernate.dao.support;
161 import java.lang.reflect.Field;
162 import java.lang.reflect.Method;
163 import java.util.ArrayList;
164 import java.util.List;
165 import org.apache.commons.lang.StringUtils;
166 import org.apache.commons.logging.Log;
167 import org.apache.commons.logging.LogFactory;
168 import org.springframework.util.Assert;
169 import org.springframework.util.ReflectionUtils;
170 /**
171 * 扩展Apache Commons BeanUtils, 提供一些反射方面缺失功能的封装.
172 * @author springside
173 *
174 */
175 public class BeanUtils extends org.apache.commons.beanutils.BeanUtils {
176 protected static final Log logger = LogFactory.getLog(BeanUtils.class);
177 private BeanUtils() {
178 }
179 /**
180 * 循环向上转型,获取对象的DeclaredField.
181 *
182 * @throws NoSuchFieldException 如果没有该Field时抛出.
183 */
184 public static Field getDeclaredField(Object object, String propertyName) throws NoSuchFieldException {
185 Assert.notNull(object);
186 Assert.hasText(propertyName);
187 return getDeclaredField(object.getClass(), propertyName);
188 }
189 /**
190 * 循环向上转型,获取对象的DeclaredField.
191 *
192 * @throws NoSuchFieldException 如果没有该Field时抛出.
193 */
194 @SuppressWarnings("unchecked")
195 public static Field getDeclaredField(Class clazz, String propertyName) throws NoSuchFieldException {
196 Assert.notNull(clazz);
197 Assert.hasText(propertyName);
198 for (Class superClass = clazz; superClass != Object.class; superClass = superClass.getSuperclass()) {
199 try {
200 return superClass.getDeclaredField(propertyName);
201 } catch (NoSuchFieldException e) {
202 // Field不在当前类定义,继续向上转型
203 }
204 }
205 throw new NoSuchFieldException("No such field: " + clazz.getName() + '.' + propertyName);
206 }
207 /**
208 * 暴力获取对象变量值,忽略private,protected修饰符的限制.
209 *
210 * @throws NoSuchFieldException 如果没有该Field时抛出.
211 */
212 public static Object forceGetProperty(Object object, String propertyName) throws NoSuchFieldException {
213 Assert.notNull(object);
214 Assert.hasText(propertyName);
215 Field field = getDeclaredField(object, propertyName);
216 boolean accessible = field.isAccessible();
217 field.setAccessible(true);
218 Object result = null;
219 try {
220 result = field.get(object);
221 } catch (IllegalAccessException e) {
222 logger.info("error wont' happen");
223 }
224 field.setAccessible(accessible);
225 return result;
226 }
227 /**
228 * 暴力设置对象变量值,忽略private,protected修饰符的限制.
229 *
230 * @throws NoSuchFieldException 如果没有该Field时抛出.
231 */
232 public static void forceSetProperty(Object object, String propertyName, Object newValue)
233 throws NoSuchFieldException {
234 Assert.notNull(object);
235 Assert.hasText(propertyName);
236 Field field = getDeclaredField(object, propertyName);
237 boolean accessible = field.isAccessible();
238 field.setAccessible(true);
239 try {
240 field.set(object, newValue);
241 } catch (IllegalAccessException e) {
242 logger.info("Error won't happen");
243 }
244 field.setAccessible(accessible);
245 }
246 /**
247 * 暴力调用对象函数,忽略private,protected修饰符的限制.
248 *
249 * @throws NoSuchMethodException 如果没有该Method时抛出.
250 */
251 @SuppressWarnings("unchecked")
252 public static Object invokePrivateMethod(Object object, String methodName, Object... params)
253 throws NoSuchMethodException {
254 Assert.notNull(object);
255 Assert.hasText(methodName);
256 Class[] types = new Class[params.length];
257 for (int i = 0; i < params.length; i++) {
258 types[i] = params[i].getClass();
259 }
260 Class clazz = object.getClass();
261 Method method = null;
262 for (Class superClass = clazz; superClass != Object.class; superClass = superClass.getSuperclass()) {
263 try {
264 method = superClass.getDeclaredMethod(methodName, types);
265 break;
266 } catch (NoSuchMethodException e) {
267 // 方法不在当前类定义,继续向上转型
268 }
269 }
270 if (method == null)
271 throw new NoSuchMethodException("No Such Method:" + clazz.getSimpleName() + methodName);
272 boolean accessible = method.isAccessible();
273 method.setAccessible(true);
274 Object result = null;
275 try {
276 result = method.invoke(object, params);
277 } catch (Exception e) {
278 ReflectionUtils.handleReflectionException(e);
279 }
280 method.setAccessible(accessible);
281 return result;
282 }
283 /**
284 * 按Filed的类型取得Field列表.
285 */
286 @SuppressWarnings("unchecked")
287 public static List<Field> getFieldsByType(Object object, Class type) {
288 List<Field> list = new ArrayList<Field>();
289 Field[] fields = object.getClass().getDeclaredFields();
290 for (Field field : fields) {
291 if (field.getType().isAssignableFrom(type)) {
292 list.add(field);
293 }
294 }
295 return list;
296 }
297 /**
298 * 按FiledName获得Field的类型.
299 */
300 @SuppressWarnings("unchecked")
301 public static Class getPropertyType(Class type, String name) throws NoSuchFieldException {
302 return getDeclaredField(type, name).getType();
303 }
304 /**
305 * 获得field的getter函数名称.
306 */
307 @SuppressWarnings("unchecked")
308 public static String getGetterName(Class type, String fieldName) {
309 Assert.notNull(type, "Type required");
310 Assert.hasText(fieldName, "FieldName required");
311 if (type.getName().equals("boolean")) {
312 return "is" + StringUtils.capitalize(fieldName);
313 } else {
314 return "get" + StringUtils.capitalize(fieldName);
315 }
316 }
317 /**
318 * 获得field的getter函数,如果找不到该方法,返回null.
319 */
320 @SuppressWarnings("unchecked")
321 public static Method getGetterMethod(Class type, String fieldName) {
322 try {
323 return type.getMethod(getGetterName(type, fieldName));
324 } catch (NoSuchMethodException e) {
325 logger.error(e.getMessage(), e);
326 }
327 return null;
328 }
329 }
330
331
332 IUndeleteableEntityOperation.java
333
334 package com.demonstration.hibernate.dao.extend;
335 import java.util.List;
336 import org.hibernate.criterion.Criterion;
337 /**
338 * 定义如果支持Entity不被直接删除必须支持的Operation.
339 *
340 * @author springside
341 *
342 */
343 public interface IUndeleteableEntityOperation<T> {
344 /*
345 * Undelete Entity用到的几个常量,因为要同时兼顾Interface与Annotation,所以集中放此.
346 */
347 String UNVALID_VALUE = "-1";
348 String NORMAL_VALUE = "0";
349 String STATUS = "status";
350 /**
351 * 取得所有状态为有效的对象.
352 */
353 List<T> getAllValid();
354 /**
355 * 删除对象,但如果是Undeleteable的entity,设置对象的状态而不是直接删除.
356 */
357 void remove(Object entity);
358 /**
359 * 获取过滤已删除对象的hql条件语句.
360 */
361 String getUnDeletableHQL();
362 /**
363 * 获取过滤已删除对象的Criterion条件语句.
364 */
365 Criterion getUnDeletableCriterion();
366 }
367
368 IUndeletableEntity.java
369 package com.demonstration.hibernate.dao.extend;
370 /**
371 * 标识商业对象不能被删除,只能被设为无效的接口.
372 *
373 * @author springside
374 *
375 */
376 public interface IUndeletableEntity {
377 void setStatus(String status);
378 }
379
380 IUndeletable.java
381 package com.demonstration.hibernate.dao.extend;
382 import java.lang.annotation.ElementType;
383 import java.lang.annotation.Retention;
384 import java.lang.annotation.RetentionPolicy;
385 import java.lang.annotation.Target;
386 /**
387 * 标识商业对象不能被删除,只能被设为无效的Annoation.
388 * <p/>
389 * 相比inferface的标示方式,annotation 方式更少侵入性,可以定义任意属性代表status,而默认为status属性.
390 */
391 @Target({ElementType.TYPE})
392 @Retention(RetentionPolicy.RUNTIME)
393 public @interface IUndeletable {
394 String status() default IUndeleteableEntityOperation.STATUS;
395 }
396
397 HibernateEntityExtendDao.java
398 package com.demonstration.hibernate.dao.extend;
399 import java.util.List;
400 import java.util.Map;
401 import org.apache.commons.beanutils.PropertyUtils;
402 import org.hibernate.Criteria;
403 import org.hibernate.criterion.Criterion;
404 import org.hibernate.criterion.Restrictions;
405 import org.springframework.util.Assert;
406 import org.springframework.util.ReflectionUtils;
407 import com.demonstration.hibernate.dao.HibernateEntityDao;
408
409 /**
410 * 加强版的entity dao.
411 * <p>自动处理Undeletable Entity.<br>
412 * Undeletable Entity 在删除时只把状态设为无效,不会真正执行删除.<br>
413 * Undeletable Entity 可以通过annotation或接口两种形式来声明.<br>
414 * 其中annotation模式不限制状态列的属性名必须为"status",可以用注释来确定任意属性为状态属性.<br>
415 * </p>
416 *
417 * @author springside
418 *
419 * @see HibernateEntityDao
420 * @see EntityInfo
421 * @see IUndeleteableEntityOperation
422 * @see IUndeletable
423 * @see IUndeletableEntity
424 */
425 @SuppressWarnings("unchecked")
426 public class HibernateEntityExtendDao<T> extends HibernateEntityDao<T> implements IUndeleteableEntityOperation<T> {
427 /**
428 * 保存所管理的Entity的信息.
429 */
430 protected EntityInfo entityInfo;
431 /**
432 * 构造函数,初始化entity信息.
433 */
434 public HibernateEntityExtendDao() {
435 entityInfo = new EntityInfo(entityClass);
436 }
437 /**
438 * 取得所有状态为有效的对象.
439 *
440 * @see IUndeleteableEntityOperation#getAllValid()
441 */
442 public List<T> getAllValid() {
443 Criteria criteria = createCriteria();
444 if (entityInfo.isUndeletable)
445 criteria.add(getUnDeletableCriterion());
446 return criteria.list();
447 }
448 /**
449 * 获取过滤已删除对象的hql条件语句.
450 *
451 * @see IUndeleteableEntityOperation#getUnDeletableHQL()
452 */
453 public String getUnDeletableHQL() {
454 return entityInfo.statusProperty + "<>" + UNVALID_VALUE;
455 }
456 /**
457 * 获取过滤已删除对象的Criterion条件语句.
458 *
459 * @see UndeleteableEntityOperation#
460 */
461 public Criterion getUnDeletableCriterion() {
462 return Restrictions.not(Restrictions.eq(entityInfo.statusProperty, UNVALID_VALUE));
463 }
464 /**
465 * 重载保存函数,在保存前先调用onValid(T),进行书名不重复等数据库相关的校验.
466 *
467 * @see #onValid(Object)
468 * @see HibernateEntityDao#save(Object)
469 */
470 @Override
471 public void save(Object entity) {
472 Assert.isInstanceOf(getEntityClass(), entity);
473 onValid((T) entity);
474 super.save(entity);
475 }
476 /**
477 * 删除对象,如果是Undeleteable的entity,设置对象的状态而不是直接删除.
478 *
479 * @see HibernateEntityDao#remove(Object)
480 */
481 @Override
482 public void remove(Object entity) {
483 if (entityInfo.isUndeletable) {
484 try {
485 PropertyUtils.setProperty(entity, entityInfo.statusProperty, UNVALID_VALUE);
486 save(entity);
487 } catch (Exception e) {
488 ReflectionUtils.handleReflectionException(e);
489 }
490 } else
491 super.remove(entity);
492 }
493 /**
494 * 与数据库相关的校验,比如判断名字在数据库里有没有重复, 在保存时被调用,在子类重载.
495 *
496 * @see #save(Object)
497 */
498 public void onValid(T entity) {
499 }
500 /**
501 * 根据Map中的条件的Criteria查询.
502 *
503 * @param map Map中仅包含条件名与条件值,默认全部相同,可重载。
504 */
505 public List<T> find(Map map) {
506 Criteria criteria = createCriteria();
507 return find(criteria, map);
508 }
509 /**
510 * 根据Map中的条件的Criteria查询.
511 *
512 * @param map Map中仅包含条件名与条件值,默认全部相同,可重载.
513 */
514 public List<T> find(Criteria criteria, Map map) {
515 Assert.notNull(criteria);
516 criteria.add(Restrictions.allEq(map));
517 return criteria.list();
518 }
519 }
520
521
522 EntityInfo.java
523 package com.demonstration.hibernate.dao.extend;
524 /**
525 * 装载Entity信息的内部类.
526 *
527 * @author springside
528 *
529 */
530 class EntityInfo {
531 boolean isUndeletable = false; // entity是否undeleteable的标志
532 String statusProperty; // 标识状态的属性名
533 @SuppressWarnings("unchecked")
534 public EntityInfo(Class entityClass) {
535 init(entityClass);
536 }
537 /**
538 * 初始函数,判断EntityClass是否UndeletableEntity.
539 */
540 @SuppressWarnings("unchecked")
541 private void init(Class entityClass) {
542 // 通过EntityClass的interface判断entity是否undeletable
543 if (IUndeletableEntity.class.isAssignableFrom(entityClass)) {
544 isUndeletable = true;
545 statusProperty = IUndeleteableEntityOperation.STATUS;
546 }
547 // 通过EntityClass的annotation判断entity是否undeletable
548 if (entityClass.isAnnotationPresent(IUndeletable.class)) {
549 isUndeletable = true;
550 IUndeletable anno = (IUndeletable) entityClass.getAnnotation(IUndeletable.class);
551 statusProperty = anno.status();
552 }
553 }
554 }
555
556 IEntityDao.java
557 package com.demonstration.hibernate.dao;
558 import java.io.Serializable;
559 import java.util.List;
560 /**
561 * 针对单个Entity对象的操作定义.不依赖于具体ORM实现方案.
562 *
563 * @author springside
564 *
565 */
566 public interface IEntityDao<T> {
567 T get(Serializable id);
568 List<T> getAll();
569 void save(Object o);
570 void remove(Object o);
571 void removeById(Serializable id);
572 /**
573 * 获取Entity对象的主键名.
574 */
575 @SuppressWarnings("unchecked")
576 String getIdName(Class clazz);
577 }
578
579 HibernateGenericDao.java
580 package com.demonstration.hibernate.dao;
581 import java.io.Serializable;
582 import java.lang.reflect.InvocationTargetException;
583 import java.util.ArrayList;
584 import java.util.List;
585 import java.util.regex.Matcher;
586 import java.util.regex.Pattern;
587 import org.apache.commons.beanutils.PropertyUtils;
588 import org.hibernate.Criteria;
589 import org.hibernate.Query;
590 import org.hibernate.criterion.CriteriaSpecification;
591 import org.hibernate.criterion.Criterion;
592 import org.hibernate.criterion.DetachedCriteria;
593 import org.hibernate.criterion.Order;
594 import org.hibernate.criterion.Projection;
595 import org.hibernate.criterion.Projections;
596 import org.hibernate.criterion.Restrictions;
597 import org.hibernate.impl.CriteriaImpl;
598 import org.hibernate.metadata.ClassMetadata;
599 import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
600 import org.springframework.util.Assert;
601 import org.springframework.util.ReflectionUtils;
602 import com.demonstration.hibernate.dao.support.BeanUtils;
603 import com.demonstration.hibernate.dao.support.Page;
604
605 /**
606 * Hibernate Dao的泛型基类.
607 * <p/>
608 * 继承于Spring的<code>HibernateDaoSupport</code>,提供分页函数和若干便捷查询方法,并对返回值作了泛型类型转换.
609 *
610 * @author springside
611 *
612 * @see HibernateDaoSupport
613 * @see HibernateEntityDao
614 */
615 @SuppressWarnings("unchecked")
616 public class HibernateGenericDao extends HibernateDaoSupport {
617 /**
618 * 根据ID获取对象. 实际调用Hibernate的session.load()方法返回实体或其proxy对象. 如果对象不存在,抛出异常.
619 */
620 public <T> T get(Class<T> entityClass, Serializable id) {
621 return (T) getHibernateTemplate().load(entityClass, id);
622 }
623 /**
624 * 获取全部对象.
625 */
626 public <T> List<T> getAll(Class<T> entityClass) {
627 return getHibernateTemplate().loadAll(entityClass);
628 }
629 /**
630 * 获取全部对象,带排序字段与升降序参数.
631 */
632 public <T> List<T> getAll(Class<T> entityClass, String orderBy, boolean isAsc) {
633 Assert.hasText(orderBy);
634 if (isAsc)
635 return getHibernateTemplate().findByCriteria(
636 DetachedCriteria.forClass(entityClass).addOrder(Order.asc(orderBy)));
637 else
638 return getHibernateTemplate().findByCriteria(
639 DetachedCriteria.forClass(entityClass).addOrder(Order.desc(orderBy)));
640 }
641 /**
642 * 保存对象.
643 */
644 public void save(Object o) {
645 getHibernateTemplate().saveOrUpdate(o);
646 }
647 /**
648 * 删除对象.
649 */
650 public void remove(Object o) {
651 getHibernateTemplate().delete(o);
652 }
653 /**
654 * 根据ID删除对象.
655 */
656 public <T> void removeById(Class<T> entityClass, Serializable id) {
657 remove(get(entityClass, id));
658 }
659 public void flush() {
660 getHibernateTemplate().flush();
661 }
662 public void clear() {
663 getHibernateTemplate().clear();
664 }
665 /**
666 * 创建Query对象. 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置.
667 * 留意可以连续设置,如下:
668 * <pre>
669 * dao.getQuery(hql).setMaxResult(100).setCacheable(true).list();
670 * </pre>
671 * 调用方式如下:
672 * <pre>
673 * dao.createQuery(hql)
674 * dao.createQuery(hql,arg0);
675 * dao.createQuery(hql,arg0,arg1);
676 * dao.createQuery(hql,new Object[arg0,arg1,arg2])
677 * </pre>
678 *
679 * @param values 可变参数.
680 */
681 public Query createQuery(String hql, Object... values) {
682 Assert.hasText(hql);
683 Query query = getSession().createQuery(hql);
684 for (int i = 0; i < values.length; i++) {
685 query.setParameter(i, values[i]);
686 }
687 return query;
688 }
689 /**
690 * 创建Criteria对象.
691 *
692 * @param criterions 可变的Restrictions条件列表,见{@link #createQuery(String,Object...)}
693 */
694 public <T> Criteria createCriteria(Class<T> entityClass, Criterion... criterions) {
695 Criteria criteria = getSession().createCriteria(entityClass);
696 for (Criterion c : criterions) {
697 criteria.add(c);
698 }
699 return criteria;
700 }
701 /**
702 * 创建Criteria对象,带排序字段与升降序字段.
703 *
704 * @see #createCriteria(Class,Criterion[])
705 */
706 public <T> Criteria createCriteria(Class<T> entityClass, String orderBy, boolean isAsc, Criterion... criterions) {
707 Assert.hasText(orderBy);
708 Criteria criteria = createCriteria(entityClass, criterions);
709 if (isAsc)
710 criteria.addOrder(Order.asc(orderBy));
711 else
712 criteria.addOrder(Order.desc(orderBy));
713 return criteria;
714 }
715 /**
716 * 根据hql查询,直接使用HibernateTemplate的find函数.
717 *
718 * @param values 可变参数,见{@link #createQuery(String,Object...)}
719 */
720 public List find(String hql, Object... values) {
721 Assert.hasText(hql);
722 return getHibernateTemplate().find(hql, values);
723 }
724 /**
725 * 根据属性名和属性值查询对象.
726 *
727 * @return 符合条件的对象列表
728 */
729 public <T> List<T> findBy(Class<T> entityClass, String propertyName, Object value) {
730 Assert.hasText(propertyName);
731 return createCriteria(entityClass, Restrictions.eq(propertyName, value)).list();
732 }
733 /**
734 * 根据属性名和属性值查询对象,带排序参数.
735 */
736 public <T> List<T> findBy(Class<T> entityClass, String propertyName, Object value, String orderBy, boolean isAsc) {
737 Assert.hasText(propertyName);
738 Assert.hasText(orderBy);
739 return createCriteria(entityClass, orderBy, isAsc, Restrictions.eq(propertyName, value)).list();
740 }
741 /**
742 * 根据属性名和属性值查询唯一对象.
743 *
744 * @return 符合条件的唯一对象 or null if not found.
745 */
746 public <T> T findUniqueBy(Class<T> entityClass, String propertyName, Object value) {
747 Assert.hasText(propertyName);
748 return (T) createCriteria(entityClass, Restrictions.eq(propertyName, value)).uniqueResult();
749 }
750 /**
751 * 分页查询函数,使用hql.
752 *
753 * @param pageNo 页号,从1开始.
754 */
755 public Page pagedQuery(String hql, int pageNo, int pageSize, Object... values) {
756 Assert.hasText(hql);
757 Assert.isTrue(pageNo >= 1, "pageNo should start from 1");
758 // Count查询
759 String countQueryString = " select count (*) " + removeSelect(removeOrders(hql));
760 List countlist = getHibernateTemplate().find(countQueryString, values);
761 long totalCount = (Long) countlist.get(0);
762 if (totalCount < 1)
763 return new Page();
764 // 实际查询返回分页对象
765 int startIndex = Page.getStartOfPage(pageNo, pageSize);
766 Query query = createQuery(hql, values);
767 List list = query.setFirstResult(startIndex).setMaxResults(pageSize).list();
768 return new Page(startIndex, totalCount, pageSize, list);
769 }
770
771 /**
772 * @author Scott.wanglei
773 * @since 2008-7-21
774 * @param hql 查询sql
775 * @param start 分页从哪一条数据开始
776 * @param pageSize 每一个页面的大小
777 * @param values 查询条件
778 * @return page对象
779 */
780 public Page dataQuery(String hql, int start, int pageSize, Object... values){
781 // Count查询
782 String countQueryString = " select count (*) " + removeSelect(removeOrders(hql));
783 List countlist = getHibernateTemplate().find(countQueryString, values);
784 long totalCount = (Long) countlist.get(0);
785 if (totalCount < 1)
786 return new Page();
787 // 实际查询返回分页对象
788 int startIndex = start;
789 Query query = createQuery(hql, values);
790 List list = query.setFirstResult(startIndex).setMaxResults(pageSize).list();
791 return new Page(startIndex, totalCount, pageSize, list);
792 }
793 /**
794 * 分页查询函数,使用已设好查询条件与排序的<code>Criteria</code>.
795 *
796 * @param pageNo 页号,从1开始.
797 * @return 含总记录数和当前页数据的Page对象.
798 */
799 public Page pagedQuery(Criteria criteria, int pageNo, int pageSize) {
800 Assert.notNull(criteria);
801 Assert.isTrue(pageNo >= 1, "pageNo should start from 1");
802 CriteriaImpl impl = (CriteriaImpl) criteria;
803 // 先把Projection和OrderBy条件取出来,清空两者来执行Count操作
804 Projection projection = impl.getProjection();
805 List<CriteriaImpl.OrderEntry> orderEntries;
806 try {
807 orderEntries = (List) BeanUtils.forceGetProperty(impl, "orderEntries");
808 BeanUtils.forceSetProperty(impl, "orderEntries", new ArrayList());
809 } catch (Exception e) {
810 throw new InternalError(" Runtime Exception impossibility throw ");
811 }
812 // 执行查询
813 int totalCount = (Integer) criteria.setProjection(Projections.rowCount()).uniqueResult();
814 // 将之前的Projection和OrderBy条件重新设回去
815 criteria.setProjection(projection);
816 if (projection == null) {
817 criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
818 }
819 try {
820 BeanUtils.forceSetProperty(impl, "orderEntries", orderEntries);
821 } catch (Exception e) {
822 throw new InternalError(" Runtime Exception impossibility throw ");
823 }
824 // 返回分页对象
825 if (totalCount < 1)
826 return new Page();
827 int startIndex = Page.getStartOfPage(pageNo, pageSize);;
828 List list = criteria.setFirstResult(startIndex).setMaxResults(pageSize).list();
829 return new Page(startIndex, totalCount, pageSize, list);
830 }
831 /**
832 * 分页查询函数,根据entityClass和查询条件参数创建默认的<code>Criteria</code>.
833 *
834 * @param pageNo 页号,从1开始.
835 * @return 含总记录数和当前页数据的Page对象.
836 */
837 public Page pagedQuery(Class entityClass, int pageNo, int pageSize, Criterion... criterions) {
838 Criteria criteria = createCriteria(entityClass, criterions);
839 return pagedQuery(criteria, pageNo, pageSize);
840 }
841 /**
842 * 分页查询函数,根据entityClass和查询条件参数,排序参数创建默认的<code>Criteria</code>.
843 *
844 * @param pageNo 页号,从1开始.
845 * @return 含总记录数和当前页数据的Page对象.
846 */
847 public Page pagedQuery(Class entityClass, int pageNo, int pageSize, String orderBy, boolean isAsc,
848 Criterion... criterions) {
849 Criteria criteria = createCriteria(entityClass, orderBy, isAsc, criterions);
850 return pagedQuery(criteria, pageNo, pageSize);
851 }
852 /**
853 * 判断对象某些属性的值在数据库中是否唯一.
854 *
855 * @param uniquePropertyNames 在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password"
856 */
857 public <T> boolean isUnique(Class<T> entityClass, Object entity, String uniquePropertyNames) {
858 Assert.hasText(uniquePropertyNames);
859 Criteria criteria = createCriteria(entityClass).setProjection(Projections.rowCount());
860 String[] nameList = uniquePropertyNames.split(",");
861 try {
862 // 循环加入唯一列
863 for (String name : nameList) {
864 criteria.add(Restrictions.eq(name, PropertyUtils.getProperty(entity, name)));
865 }
866 // 以下代码为了如果是update的情况,排除entity自身.
867 String idName = getIdName(entityClass);
868 // 取得entity的主键值
869 Serializable id = getId(entityClass, entity);
870 // 如果id!=null,说明对象已存在,该操作为update,加入排除自身的判断
871 if (id != null)
872 criteria.add(Restrictions.not(Restrictions.eq(idName, id)));
873 } catch (Exception e) {
874 ReflectionUtils.handleReflectionException(e);
875 }
876 return (Integer) criteria.uniqueResult() == 0;
877 }
878 /**
879 * 取得对象的主键值,辅助函数.
880 */
881 public Serializable getId(Class entityClass, Object entity) throws NoSuchMethodException, IllegalAccessException,
882 InvocationTargetException {
883 Assert.notNull(entity);
884 Assert.notNull(entityClass);
885 return (Serializable) PropertyUtils.getProperty(entity, getIdName(entityClass));
886 }
887 /**
888 * 取得对象的主键名,辅助函数.
889 */
890 public String getIdName(Class clazz) {
891 Assert.notNull(clazz);
892 ClassMetadata meta = getSessionFactory().getClassMetadata(clazz);
893 Assert.notNull(meta, "Class " + clazz + " not define in hibernate session factory.");
894 String idName = meta.getIdentifierPropertyName();
895 Assert.hasText(idName, clazz.getSimpleName() + " has no identifier property define.");
896 return idName;
897 }
898 /**
899 * 去除hql的select 子句,未考虑union的情况,用于pagedQuery.
900 *
901 * @see #pagedQuery(String,int,int,Object[])
902 */
903 private static String removeSelect(String hql) {
904 Assert.hasText(hql);
905 int beginPos = hql.toLowerCase().indexOf("from");
906 Assert.isTrue(beginPos != -1, " hql : " + hql + " must has a keyword 'from'");
907 return hql.substring(beginPos);
908 }
909 /**
910 * 去除hql的orderby 子句,用于pagedQuery.
911 *
912 * @see #pagedQuery(String,int,int,Object[])
913 */
914 private static String removeOrders(String hql) {
915 Assert.hasText(hql);
916 Pattern p = Pattern.compile("order//s*by[//w|//W|//s|//S]*", Pattern.CASE_INSENSITIVE);
917 Matcher m = p.matcher(hql);
918 StringBuffer sb = new StringBuffer();
919 while (m.find()) {
920 m.appendReplacement(sb, "");
921 }
922 m.appendTail(sb);
923 return sb.toString();
924 }
925
926 }
927 HibernateEntityDao.java
928 package com.demonstration.hibernate.dao;
929 import java.io.Serializable;
930 import java.util.List;
931 import org.hibernate.Criteria;
932 import org.hibernate.criterion.Criterion;
933 import com.demonstration.hibernate.dao.support.GenericsUtils;
934 /**
935 * 负责为单个Entity对象提供CRUD操作的Hibernate DAO基类. <p/> 子类只要在类定义时指定所管理Entity的Class,
936 * 即拥有对单个Entity对象的CRUD操作.
937 *
938 * <pre>
939 * public class UserManager extends HibernateEntityDao<User> {
940 * }
941 * </pre>
942 *
943 * @author springside
944 *
945 * @see HibernateGenericDao
946 */
947 @SuppressWarnings("unchecked")
948 public class HibernateEntityDao<T> extends HibernateGenericDao implements
949 IEntityDao<T> {
950 protected Class<T> entityClass;// DAO所管理的Entity类型.
951 /**
952 * 在构造函数中将泛型T.class赋给entityClass.
953 */
954 public HibernateEntityDao() {
955 entityClass = GenericsUtils.getSuperClassGenricType(getClass());
956 }
957 /**
958 * 重载构造函数 让spring提供构造函数注入
959 */
960 public HibernateEntityDao(Class<T> type) {
961 this.entityClass = type;
962 }
963
964 /**
965 * 取得entityClass.JDK1.4不支持泛型的子类可以抛开Class<T> entityClass,重载此函数达到相同效果。
966 */
967 protected Class<T> getEntityClass() {
968 return entityClass;
969 }
970
971 public void setEntityClass(Class<T> type){
972 this.entityClass=type;
973 }
974 /**
975 * 根据ID获取对象.
976 *
977 * @see HibernateGenericDao#getId(Class,Object)
978 */
979 public T get(Serializable id) {
980 return get(getEntityClass(), id);
981 }
982 /**
983 * 获取全部对象
984 *
985 * @see HibernateGenericDao#getAll(Class)
986 */
987 public List<T> getAll() {
988 return getAll(getEntityClass());
989 }
990 /**
991 * 获取全部对象,带排序参数.
992 *
993 * @see HibernateGenericDao#getAll(Class,String,boolean)
994 */
995 public List<T> getAll(String orderBy, boolean isAsc) {
996 return getAll(getEntityClass(), orderBy, isAsc);
997 }
998 /**
999 * 根据ID移除对象.
1000 *
1001 * @see HibernateGenericDao#removeById(Class,Serializable)
1002 */
1003 public void removeById(Serializable id) {
1004 removeById(getEntityClass(), id);
1005 }
1006 /**
1007 * 取得Entity的Criteria.
1008 *
1009 * @see HibernateGenericDao#createCriteria(Class,Criterion[])
1010 */
1011 public Criteria createCriteria(Criterion... criterions) {
1012 return createCriteria(getEntityClass(), criterions);
1013 }
1014 /**
1015 * 取得Entity的Criteria,带排序参数.
1016 *
1017 * @see HibernateGenericDao#createCriteria(Class,String,boolean,Criterion[])
1018 */
1019 public Criteria createCriteria(String orderBy, boolean isAsc,
1020 Criterion... criterions) {
1021 return createCriteria(getEntityClass(), orderBy, isAsc, criterions);
1022 }
1023 /**
1024 * 根据属性名和属性值查询对象.
1025 *
1026 * @return 符合条件的对象列表
1027 * @see HibernateGenericDao#findBy(Class,String,Object)
1028 */
1029 public List<T> findBy(String propertyName, Object value) {
1030 return findBy(getEntityClass(), propertyName, value);
1031 }
1032 /**
1033 * 根据属性名和属性值查询对象,带排序参数.
1034 *
1035 * @return 符合条件的对象列表
1036 * @see HibernateGenericDao#findBy(Class,String,Object,String,boolean)
1037 */
1038 public List<T> findBy(String propertyName, Object value, String orderBy,
1039 boolean isAsc) {
1040 return findBy(getEntityClass(), propertyName, value, orderBy, isAsc);
1041 }
1042 /**
1043 * 根据属性名和属性值查询单个对象.
1044 *
1045 * @return 符合条件的唯一对象 or null
1046 * @see HibernateGenericDao#findUniqueBy(Class,String,Object)
1047 */
1048 public T findUniqueBy(String propertyName, Object value) {
1049 return findUniqueBy(getEntityClass(), propertyName, value);
1050 }
1051 /**
1052 * 判断对象某些属性的值在数据库中唯一.
1053 *
1054 * @param uniquePropertyNames
1055 * 在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password"
1056 * @see HibernateGenericDao#isUnique(Class,Object,String)
1057 */
1058 public boolean isUnique(Object entity, String uniquePropertyNames) {
1059 return isUnique(getEntityClass(), entity, uniquePropertyNames);
1060 }
1061 /**
1062 * 消除与 Hibernate Session 的关联
1063 *
1064 * @param entity
1065 */
1066 public void evit(Object entity) {
1067 getHibernateTemplate().evict(entity);
1068 }
1069 }
1070
1071 IBaseDao.java
1072 /**
1073 *
1074 */
1075 package com.demonstration.hibernate.basedao;
1076 import java.io.Serializable;
1077 import java.lang.reflect.InvocationTargetException;
1078 import java.util.List;
1079 import java.util.Map;
1080 import org.hibernate.Criteria;
1081 import org.hibernate.Query;
1082 import org.hibernate.criterion.Criterion;
1083 import com.demonstration.hibernate.dao.HibernateEntityDao;
1084 import com.demonstration.hibernate.dao.HibernateGenericDao;
1085 import com.demonstration.hibernate.dao.extend.IUndeleteableEntityOperation;
1086 import com.demonstration.hibernate.dao.support.Page;
1087
1088 /**
1089 * @author
1090 *
1091 * 提供hibernate dao的所有操作,
1092 * 实现类由spring注入HibernateEntityDao和HibernateEntityExtendDao来实现
1093 * 最大限度的解耦hibernate持久层的操作
1094 */
1095 public interface IBaseDao<T> {
1096 /**
1097 * 根据ID获取对象.
1098 *
1099 * @see HibernateGenericDao#getId(Class,Object)
1100 */
1101 public T get(Serializable id);
1102
1103 /**
1104 * 获取全部对象
1105 *
1106 * @see HibernateGenericDao#getAll(Class)
1107 */
1108 public List<T> getAll();
1109
1110 /**
1111 * 获取全部对象,带排序参数.
1112 *
1113 * @see HibernateGenericDao#getAll(Class,String,boolean)
1114 */
1115 public List<T> getAll(String orderBy, boolean isAsc);
1116
1117 /**
1118 * 根据ID移除对象.
1119 *
1120 * @see HibernateGenericDao#removeById(Class,Serializable)
1121 */
1122 public void removeById(Serializable id);
1123
1124 /**
1125 * 取得Entity的Criteria.
1126 *
1127 * @see HibernateGenericDao#createCriteria(Class,Criterion[])
1128 */
1129 public Criteria createCriteria(Criterion... criterions);
1130
1131 /**
1132 * 取得Entity的Criteria,带排序参数.
1133 *
1134 * @see HibernateGenericDao#createCriteria(Class,String,boolean,Criterion[])
1135 */
1136 public Criteria createCriteria(String orderBy, boolean isAsc,
1137 Criterion... criterions);
1138
1139 /**
1140 * 根据属性名和属性值查询对象.
1141 *
1142 * @return 符合条件的对象列表
1143 * @see HibernateGenericDao#findBy(Class,String,Object)
1144 */
1145 public List<T> findBy(String propertyName, Object value);
1146
1147 /**
1148 * 根据属性名和属性值查询对象,带排序参数.
1149 *
1150 * @return 符合条件的对象列表
1151 * @see HibernateGenericDao#findBy(Class,String,Object,String,boolean)
1152 */
1153 public List<T> findBy(String propertyName, Object value, String orderBy,
1154 boolean isAsc);
1155
1156 /**
1157 * 根据属性名和属性值查询单个对象.
1158 *
1159 * @return 符合条件的唯一对象 or null
1160 * @see HibernateGenericDao#findUniqueBy(Class,String,Object)
1161 */
1162 public T findUniqueBy(String propertyName, Object value);
1163
1164 /**
1165 * 判断对象某些属性的值在数据库中唯一.
1166 *
1167 * @param uniquePropertyNames
1168 * 在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password"
1169 * @see HibernateGenericDao#isUnique(Class,Object,String)
1170 */
1171 public boolean isUnique(Object entity, String uniquePropertyNames);
1172
1173 /**
1174 * 消除与 Hibernate Session 的关联
1175 *
1176 * @param entity
1177 */
1178 public void evit(Object entity);
1179
1180 /*******************************************************************************************/
1181
1182 /**
1183 * 取得所有状态为有效的对象.
1184 *
1185 * @see IUndeleteableEntityOperation#getAllValid()
1186 */
1187 public List<T> getAllValid();
1188
1189 /**
1190 * 获取过滤已删除对象的hql条件语句.
1191 *
1192 * @see IUndeleteableEntityOperation#getUnDeletableHQL()
1193 */
1194 public String getUnDeletableHQL();
1195
1196 /**
1197 * 获取过滤已删除对象的Criterion条件语句.
1198 *
1199 * @see UndeleteableEntityOperation#
1200 */
1201 public Criterion getUnDeletableCriterion();
1202
1203 /**
1204 * 重载保存函数,在保存前先调用onValid(T),进行书名不重复等数据库相关的校验.
1205 *
1206 * @see #onValid(Object)
1207 * @see HibernateEntityDao#save(Object)
1208 */
1209 public void saveOnValid(Object entity);
1210
1211 /**
1212 * 删除对象,如果是Undeleteable的entity,设置对象的状态而不是直接删除.
1213 *
1214 * @see HibernateEntityDao#remove(Object)
1215 */
1216 public void removeUndeleteable(Object entity);
1217
1218 /**
1219 * 与数据库相关的校验,比如判断名字在数据库里有没有重复, 在保存时被调用,在子类重载.
1220 *
1221 * @see #save(Object)
1222 */
1223 public void onValid(T entity);
1224
1225 /**
1226 * 根据Map中的条件的Criteria查询.
1227 *
1228 * @param map Map中仅包含条件名与条件值,默认全部相同,可重载。
1229 */
1230 @SuppressWarnings("unchecked")
1231 public List<T> find(Map map);
1232
1233 /**
1234 * 根据Map中的条件的Criteria查询.
1235 *
1236 * @param map Map中仅包含条件名与条件值,默认全部相同,可重载.
1237 */
1238 @SuppressWarnings("unchecked")
1239 public List<T> find(Criteria criteria, Map map);
1240
1241 /*******************************************************************************************/
1242
1243 /**
1244 * 根据ID获取对象. 实际调用Hibernate的session.load()方法返回实体或其proxy对象. 如果对象不存在,抛出异常.
1245 */
1246 public T get(Class<T> entityClass, Serializable id);
1247
1248 /**
1249 * 获取全部对象.
1250 */
1251 public List<T> getAll(Class<T> entityClass);
1252
1253 /**
1254 * 获取全部对象,带排序字段与升降序参数.
1255 */
1256 public List<T> getAll(Class<T> entityClass, String orderBy, boolean isAsc);
1257
1258 /**
1259 * 保存对象.
1260 */
1261 public void save(Object o);
1262
1263 /**
1264 * 删除对象.
1265 */
1266 public void remove(Object o);
1267
1268 public void flush();
1269
1270 public void clear();
1271
1272 /**
1273 * 创建Query对象. 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置.
1274 * 留意可以连续设置,如下:
1275 * <pre>
1276 * dao.getQuery(hql).setMaxResult(100).setCacheable(true).list();
1277 * </pre>
1278 * 调用方式如下:
1279 * <pre>
1280 * dao.createQuery(hql)
1281 * dao.createQuery(hql,arg0);
1282 * dao.createQuery(hql,arg0,arg1);
1283 * dao.createQuery(hql,new Object[arg0,arg1,arg2])
1284 * </pre>
1285 *
1286 * @param values 可变参数.
1287 */
1288 public Query createQuery(String hql, Object... values);
1289
1290 /**
1291 * 创建Criteria对象.
1292 *
1293 * @param criterions 可变的Restrictions条件列表,见{@link #createQuery(String,Object...)}
1294 */
1295 public Criteria createCriteria(Class<T> entityClass, Criterion... criterions);
1296
1297 /**
1298 * 创建Criteria对象,带排序字段与升降序字段.
1299 *
1300 * @see #createCriteria(Class,Criterion[])
1301 */
1302 public Criteria createCriteria(Class<T> entityClass, String orderBy, boolean isAsc, Criterion... criterions);
1303
1304 /**
1305 * 根据hql查询,直接使用HibernateTemplate的find函数.
1306 *
1307 * @param values 可变参数,见{@link #createQuery(String,Object...)}
1308 */
1309 @SuppressWarnings("unchecked")
1310 public List find(String hql, Object... values);
1311
1312 /**
1313 * 根据属性名和属性值查询对象.
1314 *
1315 * @return 符合条件的对象列表
1316 */
1317 public List<T> findBy(Class<T> entityClass, String propertyName, Object value);
1318
1319 /**
1320 * 根据属性名和属性值查询对象,带排序参数.
1321 */
1322 public List<T> findBy(Class<T> entityClass, String propertyName, Object value, String orderBy, boolean isAsc);
1323
1324 /**
1325 * 根据属性名和属性值查询唯一对象.
1326 *
1327 * @return 符合条件的唯一对象 or null if not found.
1328 */
1329 public T findUniqueBy(Class<T> entityClass, String propertyName, Object value);
1330
1331 /**
1332 * 分页查询函数,使用hql.
1333 *
1334 * @param pageNo 页号,从1开始.
1335 */
1336 public Page pagedQuery(String hql, int pageNo, int pageSize, Object... values);
1337
1338 /**
1339 * @author Scott.wanglei
1340 * @since 2008-7-21
1341 * @param hql 查询sql
1342 * @param start 分页从哪一条数据开始
1343 * @param pageSize 每一个页面的大小
1344 * @param values 查询条件
1345 * @return page对象
1346 */
1347 public Page dataQuery(String hql, int start, int pageSize, Object... values);
1348
1349 /**
1350 * 分页查询函数,使用已设好查询条件与排序的<code>Criteria</code>.
1351 *
1352 * @param pageNo 页号,从1开始.
1353 * @return 含总记录数和当前页数据的Page对象.
1354 */
1355 public Page pagedQuery(Criteria criteria, int pageNo, int pageSize);
1356
1357 /**
1358 * 分页查询函数,根据entityClass和查询条件参数创建默认的<code>Criteria</code>.
1359 *
1360 * @param pageNo 页号,从1开始.
1361 * @return 含总记录数和当前页数据的Page对象.
1362 */
1363 @SuppressWarnings("unchecked")
1364 public Page pagedQuery(Class entityClass, int pageNo, int pageSize, Criterion... criterions);
1365
1366 /**
1367 * 分页查询函数,根据entityClass和查询条件参数,排序参数创建默认的<code>Criteria</code>.
1368 *
1369 * @param pageNo 页号,从1开始.
1370 * @return 含总记录数和当前页数据的Page对象.
1371 */
1372 @SuppressWarnings("unchecked")
1373 public Page pagedQuery(Class entityClass, int pageNo, int pageSize, String orderBy, boolean isAsc,
1374 Criterion... criterions);
1375
1376 /**
1377 * 判断对象某些属性的值在数据库中是否唯一.
1378 *
1379 * @param uniquePropertyNames 在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password"
1380 */
1381 public boolean isUnique(Class<T> entityClass, Object entity, String uniquePropertyNames);
1382
1383 /**
1384 * 取得对象的主键值,辅助函数.
1385 */
1386 @SuppressWarnings("unchecked")
1387 public Serializable getId(Class entityClass, Object entity) throws NoSuchMethodException, IllegalAccessException,
1388 InvocationTargetException ;
1389
1390 /**
1391 * 取得对象的主键名,辅助函数.
1392 */
1393 @SuppressWarnings("unchecked")
1394 public String getIdName(Class clazz);
1395 }
1396
1397 BaseDao.java
1398 /**
1399 *
1400 */
1401 package com.demonstration.hibernate.basedao;
1402 import java.io.Serializable;
1403 import java.lang.reflect.InvocationTargetException;
1404 import java.util.List;
1405 import java.util.Map;
1406 import org.hibernate.Criteria;
1407 import org.hibernate.Query;
1408 import org.hibernate.criterion.Criterion;
1409 import com.demonstration.hibernate.dao.HibernateEntityDao;
1410 import com.demonstration.hibernate.dao.HibernateGenericDao;
1411 import com.demonstration.hibernate.dao.extend.HibernateEntityExtendDao;
1412 import com.demonstration.hibernate.dao.extend.IUndeleteableEntityOperation;
1413 import com.demonstration.hibernate.dao.support.Page;
1414
1415 /**
1416 * @author
1417 *
1418 * IBaseDao的实现类通过spring注入HibernateEntityDao和HibernateEntityExtendDao来实现
1419 */
1420 public class BaseDao<T> implements IBaseDao<T> {
1421 protected Class<T> entityClass;// DAO所管理的Entity类型.
1422 private HibernateEntityDao<T> hedao;
1423 private HibernateEntityExtendDao<T> hexdao;
1424
1425
1426 public void setHedao(HibernateEntityDao<T> hedao) {
1427 hedao.setEntityClass(entityClass);
1428 this.hedao=hedao;
1429 }
1430 public void setHexdao(HibernateEntityExtendDao<T> hexdao) {
1431 hexdao.setEntityClass(entityClass);
1432 this.hexdao=hexdao;
1433 }
1434
1435 /**
1436 *让spring提供构造函数注入
1437 */
1438 public BaseDao(Class<T> type) {
1439 this.entityClass = type;
1440 }
1441
1442 public BaseDao(){}
1443 /**
1444 * 根据ID获取对象.
1445 *
1446 * @see HibernateGenericDao#getId(Class,Object)
1447 */
1448 public T get(Serializable id) {
1449 return hedao.get(id);
1450 }
1451 /**
1452 * 获取全部对象
1453 *
1454 * @see HibernateGenericDao#getAll(Class)
1455 */
1456 public List<T> getAll() {
1457 return hedao.getAll();
1458 }
1459
1460 /**
1461 * 获取全部对象,带排序参数.
1462 *
1463 * @see HibernateGenericDao#getAll(Class,String,boolean)
1464 */
1465 public List<T> getAll(String orderBy, boolean isAsc) {
1466 return hedao.getAll(orderBy, isAsc);
1467 }
1468 /**
1469 * 根据ID移除对象.
1470 *
1471 * @see HibernateGenericDao#removeById(Class,Serializable)
1472 */
1473 public void removeById(Serializable id) {
1474 hedao.removeById(id);
1475 }
1476 /**
1477 * 取得Entity的Criteria.
1478 *
1479 * @see HibernateGenericDao#createCriteria(Class,Criterion[])
1480 */
1481 public Criteria createCriteria(Criterion... criterions) {
1482 return hedao.createCriteria(criterions);
1483 }
1484 /**
1485 * 取得Entity的Criteria,带排序参数.
1486 *
1487 * @see HibernateGenericDao#createCriteria(Class,String,boolean,Criterion[])
1488 */
1489 public Criteria createCriteria(String orderBy, boolean isAsc,
1490 Criterion... criterions) {
1491 return hedao.createCriteria(orderBy, isAsc, criterions);
1492 }
1493 /**
1494 * 根据属性名和属性值查询对象.
1495 *
1496 * @return 符合条件的对象列表
1497 * @see HibernateGenericDao#findBy(Class,String,Object)
1498 */
1499 public List<T> findBy(String propertyName, Object value) {
1500 return hedao.findBy(propertyName, value);
1501 }
1502 /**
1503 * 根据属性名和属性值查询对象,带排序参数.
1504 *
1505 * @return 符合条件的对象列表
1506 * @see HibernateGenericDao#findBy(Class,String,Object,String,boolean)
1507 */
1508 public List<T> findBy(String propertyName, Object value, String orderBy,
1509 boolean isAsc) {
1510 return hedao.findBy(propertyName, value, orderBy, isAsc);
1511 }
1512 /**
1513 * 根据属性名和属性值查询单个对象.
1514 *
1515 * @return 符合条件的唯一对象 or null
1516 * @see HibernateGenericDao#findUniqueBy(Class,String,Object)
1517 */
1518 public T findUniqueBy(String propertyName, Object value) {
1519 return hedao.findUniqueBy(propertyName, value);
1520 }
1521 /**
1522 * 判断对象某些属性的值在数据库中唯一.
1523 *
1524 * @param uniquePropertyNames
1525 * 在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password"
1526 * @see HibernateGenericDao#isUnique(Class,Object,String)
1527 */
1528 public boolean isUnique(Object entity, String uniquePropertyNames) {
1529 return hedao.isUnique(entity, uniquePropertyNames);
1530 }
1531 /**
1532 * 消除与 Hibernate Session 的关联
1533 *
1534 * @param entity
1535 */
1536 public void evit(Object entity) {
1537 hedao.evit(entity);
1538 }
1539 /**
1540 * 取得所有状态为有效的对象.
1541 *
1542 * @see IUndeleteableEntityOperation#getAllValid()
1543 */
1544 public List<T> getAllValid() {
1545 return hexdao.getAllValid();
1546 }
1547 /**
1548 * 获取过滤已删除对象的hql条件语句.
1549 *
1550 * @see IUndeleteableEntityOperation#getUnDeletableHQL()
1551 */
1552 public String getUnDeletableHQL() {
1553 return hexdao.getUnDeletableHQL();
1554 }
1555 /**
1556 * 获取过滤已删除对象的Criterion条件语句.
1557 *
1558 * @see UndeleteableEntityOperation#
1559 */
1560 public Criterion getUnDeletableCriterion() {
1561 return hexdao.getUnDeletableCriterion();
1562 }
1563 /**
1564 * 重载保存函数,在保存前先调用onValid(T),进行书名不重复等数据库相关的校验.
1565 *
1566 * @see #onValid(Object)
1567 * @see HibernateEntityDao#save(Object)
1568 */
1569 public void saveOnValid(Object entity) {
1570 hexdao.save(entity);
1571 }
1572 /**
1573 * 删除对象,如果是Undeleteable的entity,设置对象的状态而不是直接删除.
1574 *
1575 * @see HibernateEntityDao#remove(Object)
1576 */
1577 public void removeUndeleteable(Object entity) {
1578 hexdao.remove(entity);
1579 }
1580 /**
1581 * 与数据库相关的校验,比如判断名字在数据库里有没有重复, 在保存时被调用,在此可重写.
1582 *
1583 * @see #save(Object)
1584 */
1585 public void onValid(T entity) {
1586
1587 }
1588 /**
1589 * 根据Map中的条件的Criteria查询.
1590 *
1591 * @param map Map中仅包含条件名与条件值,默认全部相同,可重载。
1592 */
1593 @SuppressWarnings("unchecked")
1594 public List<T> find(Map map) {
1595 return hexdao.find(map);
1596 }
1597 /**
1598 * 根据Map中的条件的Criteria查询.
1599 *
1600 * @param map Map中仅包含条件名与条件值,默认全部相同,可重载.
1601 */
1602 @SuppressWarnings("unchecked")
1603 public List<T> find(Criteria criteria, Map map) {
1604 return hexdao.find(criteria, map);
1605 }
1606 /**
1607 * 根据ID获取对象. 实际调用Hibernate的session.load()方法返回实体或其proxy对象. 如果对象不存在,抛出异常.
1608 */
1609 public T get(Class<T> entityClass, Serializable id) {
1610 return hedao.get(entityClass, id);
1611 }
1612 /**
1613 * 获取全部对象.
1614 */
1615 public List<T> getAll(Class<T> entityClass) {
1616 return hedao.getAll(entityClass);
1617 }
1618 /**
1619 * 获取全部对象,带排序字段与升降序参数.
1620 */
1621 public List<T> getAll(Class<T> entityClass, String orderBy, boolean isAsc) {
1622 return hedao.getAll(entityClass, orderBy, isAsc);
1623 }
1624 /**
1625 * 保存对象.
1626 */
1627 public void save(Object o) {
1628 hedao.save(o);
1629 }
1630 /**
1631 * 删除对象.
1632 */
1633 public void remove(Object o) {
1634 hedao.remove(o);
1635 }
1636
1637 public void flush(){
1638 hedao.flush();
1639 }
1640
1641 public void clear(){
1642 hedao.clear();
1643 }
1644 /**
1645 * 创建Query对象. 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置.
1646 * 留意可以连续设置,如下:
1647 * <pre>
1648 * dao.getQuery(hql).setMaxResult(100).setCacheable(true).list();
1649 * </pre>
1650 * 调用方式如下:
1651 * <pre>
1652 * dao.createQuery(hql)
1653 * dao.createQuery(hql,arg0);
1654 * dao.createQuery(hql,arg0,arg1);
1655 * dao.createQuery(hql,new Object[arg0,arg1,arg2])
1656 * </pre>
1657 *
1658 * @param values 可变参数.
1659 */
1660 public Query createQuery(String hql, Object... values) {
1661
1662 return hedao.createQuery(hql, values);
1663 }
1664 /**
1665 * 创建Criteria对象.
1666 *
1667 * @param criterions 可变的Restrictions条件列表,见{@link #createQuery(String,Object...)}
1668 */
1669 public Criteria createCriteria(Class<T> entityClass,
1670 Criterion... criterions) {
1671
1672 return hedao.createCriteria(entityClass, criterions);
1673 }
1674 /**
1675 * 创建Criteria对象,带排序字段与升降序字段.
1676 *
1677 * @see #createCriteria(Class,Criterion[])
1678 */
1679 public Criteria createCriteria(Class<T> entityClass, String orderBy,
1680 boolean isAsc, Criterion... criterions) {
1681 return hedao.createCriteria(entityClass, orderBy, isAsc, criterions);
1682 }
1683 /**
1684 * 根据hql查询,直接使用HibernateTemplate的find函数.
1685 *
1686 * @param values 可变参数,见{@link #createQuery(String,Object...)}
1687 */
1688 @SuppressWarnings("unchecked")
1689 public List find(String hql, Object... values) {
1690 return hedao.find(hql, values);
1691 }
1692 /**
1693 * 根据属性名和属性值查询对象.
1694 *
1695 * @return 符合条件的对象列表
1696 */
1697 public List<T> findBy(Class<T> entityClass, String propertyName,
1698 Object value) {
1699
1700 return hedao.findBy(entityClass, propertyName, value);
1701 }
1702 /**
1703 * 根据属性名和属性值查询对象,带排序参数.
1704 */
1705 public List<T> findBy(Class<T> entityClass, String propertyName,
1706 Object value, String orderBy, boolean isAsc) {
1707 return hedao.findBy(entityClass, propertyName, value, orderBy, isAsc);
1708 }
1709 /**
1710 * 根据属性名和属性值查询唯一对象.
1711 *
1712 * @return 符合条件的唯一对象 or null if not found.
1713 */
1714 public T findUniqueBy(Class<T> entityClass, String propertyName,
1715 Object value) {
1716 return hedao.findUniqueBy(propertyName, value);
1717 }
1718 /**
1719 * 分页查询函数,使用hql.
1720 *
1721 * @param pageNo 页号,从1开始.
1722 */
1723 public Page pagedQuery(String hql, int pageNo, int pageSize,
1724 Object... values) {
1725 return hedao.pagedQuery(hql, pageNo, pageSize, values);
1726 }
1727 /**
1728 * @author Scott.wanglei
1729 * @since 2008-7-21
1730 * @param hql 查询sql
1731 * @param start 分页从哪一条数据开始
1732 * @param pageSize 每一个页面的大小
1733 * @param values 查询条件
1734 * @return page对象
1735 */
1736 public Page dataQuery(String hql, int start, int pageSize, Object... values) {
1737 return hedao.dataQuery(hql, start, pageSize, values);
1738 }
1739 /**
1740 * 分页查询函数,使用已设好查询条件与排序的<code>Criteria</code>.
1741 *
1742 * @param pageNo 页号,从1开始.
1743 * @return 含总记录数和当前页数据的Page对象.
1744 */
1745 public Page pagedQuery(Criteria criteria, int pageNo, int pageSize) {
1746 return hedao.pagedQuery(criteria, pageNo, pageSize);
1747 }
1748
1749 /**
1750 * 分页查询函数,根据entityClass和查询条件参数创建默认的<code>Criteria</code>.
1751 *
1752 * @param pageNo 页号,从1开始.
1753 * @return 含总记录数和当前页数据的Page对象.
1754 */
1755 @SuppressWarnings("unchecked")
1756 public Page pagedQuery(Class entityClass, int pageNo, int pageSize,
1757 Criterion... criterions) {
1758 return hedao.pagedQuery(entityClass, pageNo, pageSize, criterions);
1759 }
1760 @SuppressWarnings("unchecked")
1761 public Page pagedQuery(Class entityClass, int pageNo, int pageSize,
1762 String orderBy, boolean isAsc, Criterion... criterions) {
1763 return hedao.pagedQuery(entityClass, pageNo, pageSize, orderBy, isAsc, criterions);
1764 }
1765 /**
1766 * 判断对象某些属性的值在数据库中是否唯一.
1767 *
1768 * @param uniquePropertyNames 在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password"
1769 */
1770 public boolean isUnique(Class<T> entityClass, Object entity,
1771 String uniquePropertyNames) {
1772 return hedao.isUnique(entity, uniquePropertyNames);
1773 }
1774 /**
1775 * 取得对象的主键值,辅助函数.
1776 */
1777 @SuppressWarnings("unchecked")
1778 public Serializable getId(Class entityClass, Object entity)
1779 throws NoSuchMethodException, IllegalAccessException,
1780 InvocationTargetException {
1781 return hedao.getId(entityClass, entity);
1782 }
1783 /**
1784 * 取得对象的主键名,辅助函数.
1785 */
1786 @SuppressWarnings("unchecked")
1787 public String getIdName(Class clazz) {
1788 return hedao.getIdName(clazz);
1789 }
1790 }
1791
1792 使用时候的xml配置:
1793 <?xml version="1.0" encoding="UTF-8"?>
1794 <beans xmlns="http://www.springframework.org/schema/beans"
1795 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1796 xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">
1797 <bean id="hedao"
1798 class="com.demonstration.hibernate.dao.HibernateEntityDao" scope="prototype">
1799 <property name="sessionFactory">
1800 <ref bean="sessionFactory" />
1801 </property>
1802 </bean>
1803 <bean id="hexdao"
1804 class="com.demonstration.hibernate.dao.extend.HibernateEntityExtendDao" scope="prototype">
1805 <property name="sessionFactory">
1806 <ref bean="sessionFactory" />
1807 </property>
1808 </bean>
1809
1810 <!--使用泛型DAO作为抽象基类-->
1811 <bean id="baseDao" class="com.demonstration.hibernate.basedao.BaseDao"
1812 abstract="true" depends-on="hedao,hexdao">
1813 <property name="hedao">
1814 <ref bean="hedao" />
1815 </property>
1816 <property name="hexdao">
1817 <ref bean="hexdao" />
1818 </property>
1819 </bean>
1820
1821 <!--下面这个dao没有写任何java代码完全有spring搞定 -->
1822 <!-- 配置实体类的DAO -->
1823 <bean id="demoDao" parent="baseDao">
1824 <constructor-arg>
1825 <!--根据这个生成某一个实体的dao -->
1826 <value>com.demonstration.entityclass.Demodata</value>
1827 </constructor-arg>
1828 </bean>
1829 </beans>