這里想說的代碼主要是泛型DAO層的應用與分頁的寫法.
分頁,采用了hibernate的一些API來分頁,這里同時采用了兩種分頁方式,CriteriaPage分頁方式,適用于多表單時查詢后分頁用的,而第二種方式是采用Hql語句查詢后分頁的.代碼如下:
CriteriaPage.java文件:
- package?org.mmc.commons; ??
- ??
- import?java.util.ArrayList; ??
- import?java.util.List; ??
- ??
- import?org.hibernate.Criteria; ??
- import?org.hibernate.criterion.CriteriaSpecification; ??
- import?org.hibernate.criterion.Projection; ??
- import?org.hibernate.criterion.Projections; ??
- import?org.hibernate.impl.CriteriaImpl; ??
- import?org.hibernate.impl.CriteriaImpl.OrderEntry; ??
- import?org.mmc.utils.BeanUtils; ??
- ??
- /** ?
- ?*?使用Hql查詢的的分頁查詢類. ?
- ?*?支持執行Count查詢取得總記錄條數 ?
- ?*?本類參考了springside項目的分頁設計 ?
- ?*/??
- public?class?CriteriaPage?{ ??
- ??
- ????/** ?
- ?????*?得到一個PageInstance實例,. ?
- ?????*/??
- ????public?static?Page?getPageInstance(Criteria?criteria,?int?pageNo,?int?pageSize)?{ ??
- ??????? ??
- ????????????return?CriteriaPage.getPageInstanceByCount(criteria,?pageNo,?pageSize); ??
- ????} ??
- ??
- ????/** ?
- ?????*?以查詢Count的形式獲取totalCount的函數 ?
- ?????*/??
- ????protected?static?Page?getPageInstanceByCount(Criteria?criteria,?int?pageNo,?int?pageSize)?{ ??
- ????????CriteriaImpl?impl?=?(CriteriaImpl)?criteria; ??
- ??
- ????????//先把Projection和OrderBy條件取出來,清空兩者來執行Count操作 ??
- ????????Projection?projection?=?impl.getProjection(); ??
- ????????List?orderEntries; ??
- ????????try?{ ??
- ????????????orderEntries?=?(List)?BeanUtils.getPrivateProperty(impl,?"orderEntries"); ??
- ????????????BeanUtils.setPrivateProperty(impl,?"orderEntries",?new?ArrayList()); ??
- ????????} ??
- ????????catch?(Exception?e)?{ ??
- ????????????throw?new?InternalError("?Runtime?Exception?impossibility?throw?"); ??
- ????????} ??
- ??
- ????????//執行查詢 ??
- ????????int?totalCount?=?(Integer)?criteria.setProjection(Projections.rowCount()).uniqueResult(); ??
- ??
- ????????//將之前的Projection和OrderBy條件重新設回去 ??
- ????????criteria.setProjection(projection); ??
- ????????if?(projection?==?null)?{ ??
- ????????????criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY); ??
- ????????} ??
- ??
- ????????try?{ ??
- ????????????BeanUtils.setPrivateProperty(impl,?"orderEntries",?orderEntries); ??
- ????????}?catch?(Exception?e)?{ ??
- ????????????throw?new?InternalError("?Runtime?Exception?impossibility?throw?"); ??
- ????????} ??
- ??
- ????????return?getPageResult(criteria,?totalCount,?pageNo,?pageSize); ??
- ????} ??
- ???? ??
- ????/** ?
- ?????*?取得totalCount后,根據pageNo和PageSize,?執行criteria的分頁查詢,取得Page變量 ?
- ?????*/??
- ????private?static?Page?getPageResult(Criteria?criteria,?int?totalCount,?int?pageNo,?int?pageSize)?{ ??
- ????????if?(totalCount?<?1)?return?new?Page(); ??
- ??
- ????????int?startIndex?=?Page.getStartOfPage(pageNo,?pageSize); ??
- ????????List?list?=?criteria.setFirstResult(startIndex).setMaxResults(pageSize).list(); ??
- ??
- ????????return?new?Page(startIndex,?totalCount,?pageSize,?list); ??
- ????} ??
- ??
- } ??
- ??
HqlPage.java文件的代碼
Page.java文件的源代碼如下:
- package?org.mmc.commons; ??
- ??
- import?java.util.ArrayList; ??
- ??
- /** ?
- ?*?分頁對象.?包含數據及分頁信息. ?
- ?*? ?
- ?*?@author?lighter?天馬行空 ?
- ?*/??
- public?class?Page?implements?java.io.Serializable?{ ??
- ?/** ?
- ??*?當前頁第一條數據的位置,從0開始 ?
- ??*/??
- ?private?int?start; ??
- ??
- ?/** ?
- ??*?每頁的記錄數 ?
- ??*/??
- ?private?int?pageSize?=?Constants.DEFAULT_PAGE_SIZE; ??
- ??
- ?/** ?
- ??*?當前頁中存放的記錄 ?
- ??*/??
- ?private?Object?data; ??
- ??
- ?/** ?
- ??*?總記錄數 ?
- ??*/??
- ?private?int?totalCount; ??
- ??
- ?/** ?
- ??*?構造方法,只構造空頁 ?
- ??*/??
- ?public?Page()?{ ??
- ??this(0,?0,?Constants.DEFAULT_PAGE_SIZE,?new?ArrayList()); ??
- ?} ??
- ??
- ?/** ?
- ??*?默認構造方法 ?
- ??*? ?
- ??*?@param?start ?
- ??*????????????本頁數據在數據庫中的起始位置 ?
- ??*?@param?totalSize ?
- ??*????????????數據庫中總記錄條數 ?
- ??*?@param?pageSize ?
- ??*????????????本頁容量 ?
- ??*?@param?data ?
- ??*????????????本頁包含的數據 ?
- ??*/??
- ?public?Page(int?start,?int?totalSize,?int?pageSize,?Object?data)?{ ??
- ??this.pageSize?=?pageSize; ??
- ??this.start?=?start; ??
- ??this.totalCount?=?totalSize; ??
- ??this.data?=?data; ??
- ?} ??
- ??
- ?/** ?
- ??*?取數據庫中包含的總記錄數 ?
- ??*/??
- ?public?int?getTotalCount()?{ ??
- ??return?this.totalCount; ??
- ?} ??
- ??
- ?/** ?
- ??*?取總頁數 ?
- ??*/??
- ?public?int?getTotalPageCount()?{ ??
- ??if?(totalCount?%?pageSize?==?0) ??
- ???return?totalCount?/?pageSize; ??
- ??else??
- ???return?totalCount?/?pageSize?+?1; ??
- ?} ??
- ??
- ?/** ?
- ??*?取每頁數據容量 ?
- ??*/??
- ?public?int?getPageSize()?{ ??
- ??return?pageSize; ??
- ?} ??
- ??
- ?/** ?
- ??*?當前頁中的記錄 ?
- ??*/??
- ?public?Object?getResult()?{ ??
- ??return?data; ??
- ?} ??
- ??
- ?/** ?
- ??*?取當前頁碼,頁碼從1開始 ?
- ??*/??
- ?public?int?getCurrentPageNo()?{ ??
- ??return?(start?/?pageSize)?+?1; ??
- ?} ??
- ??
- ?/** ?
- ??*?是否有下一頁 ?
- ??*/??
- ?public?boolean?hasNextPage()?{ ??
- ??return?(this.getCurrentPageNo()?<?this.getTotalPageCount()?-?1); ??
- ?} ??
- ??
- ?/** ?
- ??*?是否有上一頁 ?
- ??*/??
- ?public?boolean?hasPreviousPage()?{ ??
- ??return?(this.getCurrentPageNo()?>?1); ??
- ?} ??
- ??
- ?/** ?
- ??*?獲取任一頁第一條數據的位置,每頁條數使用默認值 ?
- ??*?關鍵字設為pretected ?
- ??*/??
- ?protected?static?int?getStartOfPage(int?pageNo)?{ ??
- ??return?getStartOfPage(pageNo,?Constants.DEFAULT_PAGE_SIZE); ??
- ?} ??
- ??
- ?/** ?
- ??*?獲取任一頁第一條數據的位置,startIndex從0開始 ?
- ??*?關鍵字設為pretected ?
- ??*/??
- ?protected?static?int?getStartOfPage(int?pageNo,?int?pageSize)?{ ??
- ??return?(pageNo?-?1)?*?pageSize; ??
- ?} ??
- } ??
- ??
分頁的改造已經完成,現在重構一下DAO層的寫法,利用了spring對hibernate支持的一些的API.
DAO層:
AbstractHibernateDao.java的源代碼
- package?org.mmc.dao; ??
- ??
- import?org.apache.commons.beanutils.PropertyUtils; ??
- import?org.apache.commons.lang.StringUtils; ??
- import?org.apache.commons.logging.Log; ??
- import?org.apache.commons.logging.LogFactory; ??
- import?org.hibernate.Criteria; ??
- import?org.hibernate.criterion.MatchMode; ??
- import?org.hibernate.criterion.Order; ??
- import?org.hibernate.criterion.Projections; ??
- import?org.hibernate.criterion.Restrictions; ??
- import?org.springframework.orm.ObjectRetrievalFailureException; ??
- import?org.springframework.orm.hibernate3.support.HibernateDaoSupport; ??
- import?org.springframework.util.Assert; ??
- import?org.springframework.util.CollectionUtils; ??
- import?org.mmc.utils.GenericsUtils; ??
- ??
- import?java.io.Serializable; ??
- import?java.util.List; ??
- import?java.util.Map; ??
- import?java.util.Set; ??
- ??
- /** ?
- ?*?純Hibernate?Entity?DAO基類. ?
- ?*?通過泛型,子類無需擴展任何函數即擁有完整的CRUD操作. ?
- ?* ?
- ?*/??
- abstract?public?class?AbstractHibernateDao?extends?HibernateDaoSupport?{ ??
- ??
- ????protected?Log?logger?=?LogFactory.getLog(getClass()); ??
- ??
- ????/** ?
- ?????*?Dao所管理的Entity類型. ?
- ?????*/??
- ????protected?Class?entityClass; ??
- ??
- ????/** ?
- ?????*?取得entityClass的函數. ?
- ?????*?JDK1.4不支持泛型的子類可以拋開Class?entityClass,重新實現此函數達到相同效果。 ?
- ?????*/??
- ????protected?Class?getEntityClass()?{ ??
- ????????return?entityClass; ??
- ????} ??
- ??
- ????/** ?
- ?????*?在構造函數中將泛型T.class賦給entityClass ?
- ?????*/??
- ????public?AbstractHibernateDao()?{ ??
- ????????entityClass?=?GenericsUtils.getGenericClass(getClass()); ??
- ????} ??
- ??
- ????public?T?get(Serializable?id)?{ ??
- ????????T?o?=?(T)?getHibernateTemplate().get(getEntityClass(),?id); ??
- ????????if?(o?==?null) ??
- ????????????throw?new?ObjectRetrievalFailureException(getEntityClass(),?id); ??
- ????????return?o; ??
- ????} ??
- ??
- ????public?List?getAll()?{ ??
- ????????return?getHibernateTemplate().loadAll(getEntityClass()); ??
- ????} ??
- ??
- ????public?void?save(Object?o)?{ ??
- ????????getHibernateTemplate().saveOrUpdate(o); ??
- ????} ??
- ??
- ????public?void?removeById(Serializable?id)?{ ??
- ????????remove(get(id)); ??
- ????} ??
- ??
- ????public?void?remove(Object?o)?{ ??
- ????????getHibernateTemplate().delete(o); ??
- ????} ??
- ??
- ????public?List?find(String?hsql,?Object...?values)?{ ??
- ????????if?(values.length?==?0) ??
- ????????????return?getHibernateTemplate().find(hsql); ??
- ????????else??
- ????????????return?getHibernateTemplate().find(hsql,?values); ??
- ????} ??
- ??
- ????/** ?
- ?????*?根據屬性名和屬性值查詢對象. ?
- ?????* ?
- ?????*?@return?符合條件的唯一對象 ?
- ?????*/??
- ????public?T?findUniqueBy(String?name,?Object?value)?{ ??
- ????????Criteria?criteria?=?getSession().createCriteria(getEntityClass()); ??
- ????????criteria.add(Restrictions.eq(name,?value)); ??
- ????????return?(T)?criteria.uniqueResult(); ??
- ????} ??
- ??
- ????/** ?
- ?????*?根據屬性名和屬性值查詢對象. ?
- ?????* ?
- ?????*?@return?符合條件的對象列表 ?
- ?????*/??
- ????public?List?findBy(String?name,?Object?value)?{ ??
- ????????Assert.hasText(name); ??
- ????????Criteria?criteria?=?getSession().createCriteria(getEntityClass()); ??
- ????????criteria.add(Restrictions.eq(name,?value)); ??
- ????????return?criteria.list(); ??
- ????} ??
- ??
- ????/** ?
- ?????*?根據屬性名和屬性值以Like?AnyWhere方式查詢對象. ?
- ?????*/??
- ????public?List?findByLike(String?name,?String?value)?{ ??
- ????????Assert.hasText(name); ??
- ????????Criteria?criteria?=?getSession().createCriteria(getEntityClass()); ??
- ????????criteria.add(Restrictions.like(name,?value,?MatchMode.ANYWHERE)); ??
- ????????return?criteria.list(); ??
- ????} ??
- ??
- ????/** ?
- ?????*?根據Map中過濾條件進行查詢. ?
- ?????* ?
- ?????*?@param?filter????????過濾條件. ?
- ?????*?@param?criteriaSetup?將Map中條件轉換為criteria的call?back類 ?
- ?????*/??
- ????public?List?findBy(Map?filter,?CriteriaSetup?criteriaSetup)?{ ??
- ????????Criteria?criteria?=?getEntityCriteria(); ??
- ????????if?(!CollectionUtils.isEmpty(filter))?{ ??
- ????????????criteriaSetup.setup(criteria,?filter); ??
- ????????} ??
- ????????return?criteria.list(); ??
- ????} ??
- ??
- ????/** ?
- ?????*?函數作用同{@link?#findBy(Map,CriteriaSetup)} ?
- ?????*?如果不需要分頁,子類可直接重載此函數. ?
- ?????*/??
- ????public?List?findBy(Map?filter)?{ ??
- ????????return?findBy(filter,?getDefaultCriteriaSetup()); ??
- ????} ??
- ??
- ????protected?CriteriaSetup?getDefaultCriteriaSetup()?{ ??
- ????????return?new?CriteriaSetup()?{ ??
- ????????????public?void?setup(Criteria?criteria,?Map?filter)?{ ??
- ????????????????if?(filter?!=?null?&&?!filter.isEmpty())?{ ??
- ????????????????????Set?keys?=?filter.keySet(); ??
- ????????????????????for?(Object?key?:?keys)?{ ??
- ????????????????????????String?value?=?(String)?filter.get(key); ??
- ????????????????????????if?(StringUtils.isNotBlank(value)) ??
- ????????????????????????????criteria.add(Restrictions.eq((String)?key,?value)); ??
- ????????????????????} ??
- ????????????????} ??
- ????????????} ??
- ????????}; ??
- ????} ??
- ??
- ????/** ?
- ?????*?取得Entity的Criteria. ?
- ?????*/??
- ????protected?Criteria?getEntityCriteria()?{ ??
- ????????return?getSession().createCriteria(getEntityClass()); ??
- ????} ??
- ??
- ????/** ?
- ?????*?構造Criteria的排序條件默認函數.可供其他查詢函數調用 ?
- ?????* ?
- ?????*?@param?criteria?Criteria實例. ?
- ?????*?@param?sortMap??排序條件. ?
- ?????*?@param?entity???entity對象,用于使用反射來獲取某些屬性信息 ?
- ?????*/??
- ????protected?void?sortCriteria(Criteria?criteria,?Map?sortMap,?Object?entity)?{ ??
- ????????if?(!sortMap.isEmpty())?{ ??
- ????????????for?(Object?o?:?sortMap.keySet())?{ ??
- ????????????????String?fieldName?=?o.toString(); ??
- ????????????????String?orderType?=?sortMap.get(fieldName).toString(); ??
- ??
- ????????????????//處理嵌套屬性如category.name,modify_user.id,暫時只處理一級嵌套 ??
- ????????????????if?(fieldName.indexOf('.')?!=?-1)?{ ??
- ????????????????????String?alias?=?StringUtils.substringBefore(fieldName,?"."); ??
- ????????????????????String?aliasType?=?alias; ??
- ????????????????????try?{ ??
- ????????????????????????aliasType?=?PropertyUtils.getProperty(entity,?alias).getClass().getSimpleName(); ??
- ????????????????????}?catch?(Exception?e)?{ ??
- ????????????????????????logger.error("Get?property"?+?alias?+?"?error"); ??
- ????????????????????} ??
- ????????????????????criteria.createAlias(aliasType,?alias); ??
- ????????????????} ??
- ??
- ????????????????if?("asc".equalsIgnoreCase(orderType))?{ ??
- ????????????????????criteria.addOrder(Order.asc(fieldName)); ??
- ????????????????}?else?{ ??
- ????????????????????criteria.addOrder(Order.desc(fieldName)); ??
- ????????????????} ??
- ????????????} ??
- ????????} ??
- ????} ??
- ??
- ????/** ?
- ?????*?判斷對象某列的值在數據庫中不存在重復 ?
- ?????* ?
- ?????*?@param?names?在POJO里相對應的屬性名,列組合時以逗號分割 ?
- ?????*??????????????如"name,loginid,password" ?
- ?????*/??
- ????public?boolean?isNotUnique(Object?entity,?String?names)?{ ??
- ????????Assert.hasText(names); ??
- ????????Criteria?criteria?=?getSession().createCriteria(entity.getClass()).setProjection(Projections.rowCount()); ??
- ????????String[]?nameList?=?names.split(","); ??
- ????????try?{ ??
- ????????????for?(String?name?:?nameList)?{ ??
- ????????????????criteria.add(Restrictions.eq(name,?PropertyUtils.getProperty(entity,?name))); ??
- ????????????} ??
- ??
- ????????????String?keyName?=?getSessionFactory().getClassMetadata(entity.getClass()).getIdentifierPropertyName(); ??
- ????????????if?(keyName?!=?null)?{ ??
- ????????????????Object?id?=?PropertyUtils.getProperty(entity,?keyName); ??
- ????????????????//如果是update,排除自身 ??
- ????????????????if?(id?!=?null) ??
- ????????????????????criteria.add(Restrictions.not(Restrictions.eq(keyName,?id))); ??
- ????????????} ??
- ????????} ??
- ????????catch?(Exception?e)?{ ??
- ????????????logger.error(e.getMessage()); ??
- ????????????return?false; ??
- ????????} ??
- ????????return?((Integer)?criteria.uniqueResult())?>?0; ??
- ????} ??
- } ??