以前从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>