`
lighter
  • 浏览: 500934 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

研究一下springside的核心部分源代码

阅读更多
 这两天,有一些时间,研究一下springside的源代码,结果感觉不错,于是对自己做过一些代码做了一些优化与重构.
分页的代码如下:
(说明:这里的代码是我参考了springside的源代码后作了一些比较小的改动,这里没有给出完整的例子,只是讨论一下核心的代码)
这里想说的代码主要是泛型DAO层的应用与分页的写法.

分页,采用了hibernate的一些API来分页,这里同时采用了两种分页方式,CriteriaPage分页方式,适用于多表单时查询后分页用的,而第二种方式是采用Hql语句查询后分页的.代码如下:

CriteriaPage.java文件:
  1. package org.mmc.commons;   
  2.   
  3. import java.util.ArrayList;   
  4. import java.util.List;   
  5.   
  6. import org.hibernate.Criteria;   
  7. import org.hibernate.criterion.CriteriaSpecification;   
  8. import org.hibernate.criterion.Projection;   
  9. import org.hibernate.criterion.Projections;   
  10. import org.hibernate.impl.CriteriaImpl;   
  11. import org.hibernate.impl.CriteriaImpl.OrderEntry;   
  12. import org.mmc.utils.BeanUtils;   
  13.   
  14. /**  
  15.  * 使用Hql查询的的分页查询类.  
  16.  * 支持执行Count查询取得总记录条数  
  17.  * 本类参考了springside项目的分页设计  
  18.  */  
  19. public class CriteriaPage {   
  20.   
  21.     /**  
  22.      * 得到一个PageInstance实例,.  
  23.      */  
  24.     public static Page getPageInstance(Criteria criteria, int pageNo, int pageSize) {   
  25.           
  26.             return CriteriaPage.getPageInstanceByCount(criteria, pageNo, pageSize);   
  27.     }   
  28.   
  29.     /**  
  30.      * 以查询Count的形式获取totalCount的函数  
  31.      */  
  32.     protected static Page getPageInstanceByCount(Criteria criteria, int pageNo, int pageSize) {   
  33.         CriteriaImpl impl = (CriteriaImpl) criteria;   
  34.   
  35.         //先把Projection和OrderBy条件取出来,清空两者来执行Count操作   
  36.         Projection projection = impl.getProjection();   
  37.         List orderEntries;   
  38.         try {   
  39.             orderEntries = (List) BeanUtils.getPrivateProperty(impl, "orderEntries");   
  40.             BeanUtils.setPrivateProperty(impl, "orderEntries"new ArrayList());   
  41.         }   
  42.         catch (Exception e) {   
  43.             throw new InternalError(" Runtime Exception impossibility throw ");   
  44.         }   
  45.   
  46.         //执行查询   
  47.         int totalCount = (Integer) criteria.setProjection(Projections.rowCount()).uniqueResult();   
  48.   
  49.         //将之前的Projection和OrderBy条件重新设回去   
  50.         criteria.setProjection(projection);   
  51.         if (projection == null) {   
  52.             criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);   
  53.         }   
  54.   
  55.         try {   
  56.             BeanUtils.setPrivateProperty(impl, "orderEntries", orderEntries);   
  57.         } catch (Exception e) {   
  58.             throw new InternalError(" Runtime Exception impossibility throw ");   
  59.         }   
  60.   
  61.         return getPageResult(criteria, totalCount, pageNo, pageSize);   
  62.     }   
  63.        
  64.     /**  
  65.      * 取得totalCount后,根据pageNo和PageSize, 执行criteria的分页查询,取得Page变量  
  66.      */  
  67.     private static Page getPageResult(Criteria criteria, int totalCount, int pageNo, int pageSize) {   
  68.         if (totalCount < 1return new Page();   
  69.   
  70.         int startIndex = Page.getStartOfPage(pageNo, pageSize);   
  71.         List list = criteria.setFirstResult(startIndex).setMaxResults(pageSize).list();   
  72.   
  73.         return new Page(startIndex, totalCount, pageSize, list);   
  74.     }   
  75.   
  76. }   
  77.   


HqlPage.java文件的代码


Page.java文件的源代码如下:
  1. package org.mmc.commons;   
  2.   
  3. import java.util.ArrayList;   
  4.   
  5. /**  
  6.  * 分页对象. 包含数据及分页信息.  
  7.  *   
  8.  * @author lighter 天马行空  
  9.  */  
  10. public class Page implements java.io.Serializable {   
  11.  /**  
  12.   * 当前页第一条数据的位置,从0开始  
  13.   */  
  14.  private int start;   
  15.   
  16.  /**  
  17.   * 每页的记录数  
  18.   */  
  19.  private int pageSize = Constants.DEFAULT_PAGE_SIZE;   
  20.   
  21.  /**  
  22.   * 当前页中存放的记录  
  23.   */  
  24.  private Object data;   
  25.   
  26.  /**  
  27.   * 总记录数  
  28.   */  
  29.  private int totalCount;   
  30.   
  31.  /**  
  32.   * 构造方法,只构造空页  
  33.   */  
  34.  public Page() {   
  35.   this(00, Constants.DEFAULT_PAGE_SIZE, new ArrayList());   
  36.  }   
  37.   
  38.  /**  
  39.   * 默认构造方法  
  40.   *   
  41.   * @param start  
  42.   *            本页数据在数据库中的起始位置  
  43.   * @param totalSize  
  44.   *            数据库中总记录条数  
  45.   * @param pageSize  
  46.   *            本页容量  
  47.   * @param data  
  48.   *            本页包含的数据  
  49.   */  
  50.  public Page(int start, int totalSize, int pageSize, Object data) {   
  51.   this.pageSize = pageSize;   
  52.   this.start = start;   
  53.   this.totalCount = totalSize;   
  54.   this.data = data;   
  55.  }   
  56.   
  57.  /**  
  58.   * 取数据库中包含的总记录数  
  59.   */  
  60.  public int getTotalCount() {   
  61.   return this.totalCount;   
  62.  }   
  63.   
  64.  /**  
  65.   * 取总页数  
  66.   */  
  67.  public int getTotalPageCount() {   
  68.   if (totalCount % pageSize == 0)   
  69.    return totalCount / pageSize;   
  70.   else  
  71.    return totalCount / pageSize + 1;   
  72.  }   
  73.   
  74.  /**  
  75.   * 取每页数据容量  
  76.   */  
  77.  public int getPageSize() {   
  78.   return pageSize;   
  79.  }   
  80.   
  81.  /**  
  82.   * 当前页中的记录  
  83.   */  
  84.  public Object getResult() {   
  85.   return data;   
  86.  }   
  87.   
  88.  /**  
  89.   * 取当前页码,页码从1开始  
  90.   */  
  91.  public int getCurrentPageNo() {   
  92.   return (start / pageSize) + 1;   
  93.  }   
  94.   
  95.  /**  
  96.   * 是否有下一页  
  97.   */  
  98.  public boolean hasNextPage() {   
  99.   return (this.getCurrentPageNo() < this.getTotalPageCount() - 1);   
  100.  }   
  101.   
  102.  /**  
  103.   * 是否有上一页  
  104.   */  
  105.  public boolean hasPreviousPage() {   
  106.   return (this.getCurrentPageNo() > 1);   
  107.  }   
  108.   
  109.  /**  
  110.   * 获取任一页第一条数据的位置,每页条数使用默认值  
  111.   * 关键字设为pretected  
  112.   */  
  113.  protected static int getStartOfPage(int pageNo) {   
  114.   return getStartOfPage(pageNo, Constants.DEFAULT_PAGE_SIZE);   
  115.  }   
  116.   
  117.  /**  
  118.   * 获取任一页第一条数据的位置,startIndex从0开始  
  119.   * 关键字设为pretected  
  120.   */  
  121.  protected static int getStartOfPage(int pageNo, int pageSize) {   
  122.   return (pageNo - 1) * pageSize;   
  123.  }   
  124. }   
  125.   


分页的改造已经完成,现在重构一下DAO层的写法,利用了spring对hibernate支持的一些的API.
DAO层:
AbstractHibernateDao.java的源代码
  1. package org.mmc.dao;   
  2.   
  3. import org.apache.commons.beanutils.PropertyUtils;   
  4. import org.apache.commons.lang.StringUtils;   
  5. import org.apache.commons.logging.Log;   
  6. import org.apache.commons.logging.LogFactory;   
  7. import org.hibernate.Criteria;   
  8. import org.hibernate.criterion.MatchMode;   
  9. import org.hibernate.criterion.Order;   
  10. import org.hibernate.criterion.Projections;   
  11. import org.hibernate.criterion.Restrictions;   
  12. import org.springframework.orm.ObjectRetrievalFailureException;   
  13. import org.springframework.orm.hibernate3.support.HibernateDaoSupport;   
  14. import org.springframework.util.Assert;   
  15. import org.springframework.util.CollectionUtils;   
  16. import org.mmc.utils.GenericsUtils;   
  17.   
  18. import java.io.Serializable;   
  19. import java.util.List;   
  20. import java.util.Map;   
  21. import java.util.Set;   
  22.   
  23. /**  
  24.  * 纯Hibernate Entity DAO基类.  
  25.  * 通过泛型,子类无需扩展任何函数即拥有完整的CRUD操作.  
  26.  *  
  27.  */  
  28. abstract public class AbstractHibernateDao extends HibernateDaoSupport {   
  29.   
  30.     protected Log logger = LogFactory.getLog(getClass());   
  31.   
  32.     /**  
  33.      * Dao所管理的Entity类型.  
  34.      */  
  35.     protected Class entityClass;   
  36.   
  37.     /**  
  38.      * 取得entityClass的函数.  
  39.      * JDK1.4不支持泛型的子类可以抛开Class entityClass,重新实现此函数达到相同效果。  
  40.      */  
  41.     protected Class getEntityClass() {   
  42.         return entityClass;   
  43.     }   
  44.   
  45.     /**  
  46.      * 在构造函数中将泛型T.class赋给entityClass  
  47.      */  
  48.     public AbstractHibernateDao() {   
  49.         entityClass = GenericsUtils.getGenericClass(getClass());   
  50.     }   
  51.   
  52.     public T get(Serializable id) {   
  53.         T o = (T) getHibernateTemplate().get(getEntityClass(), id);   
  54.         if (o == null)   
  55.             throw new ObjectRetrievalFailureException(getEntityClass(), id);   
  56.         return o;   
  57.     }   
  58.   
  59.     public List getAll() {   
  60.         return getHibernateTemplate().loadAll(getEntityClass());   
  61.     }   
  62.   
  63.     public void save(Object o) {   
  64.         getHibernateTemplate().saveOrUpdate(o);   
  65.     }   
  66.   
  67.     public void removeById(Serializable id) {   
  68.         remove(get(id));   
  69.     }   
  70.   
  71.     public void remove(Object o) {   
  72.         getHibernateTemplate().delete(o);   
  73.     }   
  74.   
  75.     public List find(String hsql, Object... values) {   
  76.         if (values.length == 0)   
  77.             return getHibernateTemplate().find(hsql);   
  78.         else  
  79.             return getHibernateTemplate().find(hsql, values);   
  80.     }   
  81.   
  82.     /**  
  83.      * 根据属性名和属性值查询对象.  
  84.      *  
  85.      * @return 符合条件的唯一对象  
  86.      */  
  87.     public T findUniqueBy(String name, Object value) {   
  88.         Criteria criteria = getSession().createCriteria(getEntityClass());   
  89.         criteria.add(Restrictions.eq(name, value));   
  90.         return (T) criteria.uniqueResult();   
  91.     }   
  92.   
  93.     /**  
  94.      * 根据属性名和属性值查询对象.  
  95.      *  
  96.      * @return 符合条件的对象列表  
  97.      */  
  98.     public List findBy(String name, Object value) {   
  99.         Assert.hasText(name);   
  100.         Criteria criteria = getSession().createCriteria(getEntityClass());   
  101.         criteria.add(Restrictions.eq(name, value));   
  102.         return criteria.list();   
  103.     }   
  104.   
  105.     /**  
  106.      * 根据属性名和属性值以Like AnyWhere方式查询对象.  
  107.      */  
  108.     public List findByLike(String name, String value) {   
  109.         Assert.hasText(name);   
  110.         Criteria criteria = getSession().createCriteria(getEntityClass());   
  111.         criteria.add(Restrictions.like(name, value, MatchMode.ANYWHERE));   
  112.         return criteria.list();   
  113.     }   
  114.   
  115.     /**  
  116.      * 根据Map中过滤条件进行查询.  
  117.      *  
  118.      * @param filter        过滤条件.  
  119.      * @param criteriaSetup 将Map中条件转换为criteria的call back类  
  120.      */  
  121.     public List findBy(Map filter, CriteriaSetup criteriaSetup) {   
  122.         Criteria criteria = getEntityCriteria();   
  123.         if (!CollectionUtils.isEmpty(filter)) {   
  124.             criteriaSetup.setup(criteria, filter);   
  125.         }   
  126.         return criteria.list();   
  127.     }   
  128.   
  129.     /**  
  130.      * 函数作用同{@link #findBy(Map,CriteriaSetup)}  
  131.      * 如果不需要分页,子类可直接重载此函数.  
  132.      */  
  133.     public List findBy(Map filter) {   
  134.         return findBy(filter, getDefaultCriteriaSetup());   
  135.     }   
  136.   
  137.     protected CriteriaSetup getDefaultCriteriaSetup() {   
  138.         return new CriteriaSetup() {   
  139.             public void setup(Criteria criteria, Map filter) {   
  140.                 if (filter != null && !filter.isEmpty()) {   
  141.                     Set keys = filter.keySet();   
  142.                     for (Object key : keys) {   
  143.                         String value = (String) filter.get(key);   
  144.                         if (StringUtils.isNotBlank(value))   
  145.                             criteria.add(Restrictions.eq((String) key, value));   
  146.                     }   
  147.                 }   
  148.             }   
  149.         };   
  150.     }   
  151.   
  152.     /**  
  153.      * 取得Entity的Criteria.  
  154.      */  
  155.     protected Criteria getEntityCriteria() {   
  156.         return getSession().createCriteria(getEntityClass());   
  157.     }   
  158.   
  159.     /**  
  160.      * 构造Criteria的排序条件默认函数.可供其他查询函数调用  
  161.      *  
  162.      * @param criteria Criteria实例.  
  163.      * @param sortMap  排序条件.  
  164.      * @param entity   entity对象,用于使用反射来获取某些属性信息  
  165.      */  
  166.     protected void sortCriteria(Criteria criteria, Map sortMap, Object entity) {   
  167.         if (!sortMap.isEmpty()) {   
  168.             for (Object o : sortMap.keySet()) {   
  169.                 String fieldName = o.toString();   
  170.                 String orderType = sortMap.get(fieldName).toString();   
  171.   
  172.                 //处理嵌套属性如category.name,modify_user.id,暂时只处理一级嵌套   
  173.                 if (fieldName.indexOf('.') != -1) {   
  174.                     String alias = StringUtils.substringBefore(fieldName, ".");   
  175.                     String aliasType = alias;   
  176.                     try {   
  177.                         aliasType = PropertyUtils.getProperty(entity, alias).getClass().getSimpleName();   
  178.                     } catch (Exception e) {   
  179.                         logger.error("Get property" + alias + " error");   
  180.                     }   
  181.                     criteria.createAlias(aliasType, alias);   
  182.                 }   
  183.   
  184.                 if ("asc".equalsIgnoreCase(orderType)) {   
  185.                     criteria.addOrder(Order.asc(fieldName));   
  186.                 } else {   
  187.                     criteria.addOrder(Order.desc(fieldName));   
  188.                 }   
  189.             }   
  190.         }   
  191.     }   
  192.   
  193.     /**  
  194.      * 判断对象某列的值在数据库中不存在重复  
  195.      *  
  196.      * @param names 在POJO里相对应的属性名,列组合时以逗号分割  
  197.  
  198.      *              如"name,loginid,password"  
  199.      */  
  200.     public boolean isNotUnique(Object entity, String names) {   
  201.         Assert.hasText(names);   
  202.         Criteria criteria = getSession().createCriteria(entity.getClass()).setProjection(Projections.rowCount());   
  203.         String[] nameList = names.split(",");   
  204.         try {   
  205.             for (String name : nameList) {   
  206.                 criteria.add(Restrictions.eq(name, PropertyUtils.getProperty(entity, name)));   
  207.             }   
  208.   
  209.             String keyName = getSessionFactory().getClassMetadata(entity.getClass()).getIdentifierPropertyName();   
  210.             if (keyName != null) {   
  211.                 Object id = PropertyUtils.getProperty(entity, keyName);   
  212.                 //如果是update,排除自身   
  213.                 if (id != null)   
  214.                     criteria.add(Restrictions.not(Restrictions.eq(keyName, id)));   
  215.             }   
  216.         }   
  217.         catch (Exception e) {   
  218.             logger.error(e.getMessage());   
  219.             return false;   
  220.         }   
  221.         return ((Integer) criteria.uniqueResult()) > 0;   
  222.     }   
  223. }   
  224.   
上面只是简单的说了一下的springside项目源代码的一些优雅的地方,如果有需要的要求的话,我会贴出完整的一个简单例子的demo的,包括分页的与泛型DAO的应用.
分享到:
评论
5 楼 xugq035 2009-08-17  
请问一下如果通过hql查询,如果语句中包含distinct怎么办?
String countQueryString = " select count (*) " + removeSelect(removeOrders(hql));
这样查询出来的总数好像不正确
4 楼 fudehai001 2009-02-21  
贴出完整的一个简单例子的demo  --盼望中,辛苦了
3 楼 huobao89 2008-10-10  
想问一下 如果 用 startIndex做,在页面用pager-taglib 做分页,怎么传参数给
export="pageOffset,pageNumber" 
谢谢
2 楼 junzhonxiaozi 2007-04-05  
谢谢分享,我正需要这方面的例子学习学习
可以贴出让大家分享么!
邮箱(交流学习):junzhonxiaozi@126.com
1 楼 j2292003 2006-12-26  
如果page分页的Criteria 含有group by 等,你是如何解决的?
先把Projection和OrderBy条件取出来,清空两者来执行Count操作 ,这意味着取出Projection时,取出了group by等条件,这样执行的结果不一样,本人也遇到了这个问题,暂时没有想到好的解决方法,判交流:j2292003@hotmail.com

相关推荐

    springside3+ext源代码

    总的来说,"springside3+ext源代码"是一个集成了多种主流Java技术的实战项目,适合希望深入研究Spring生态、EXTJS以及MVC架构的开发者进行学习和借鉴。通过这个项目,开发者不仅可以提升技术水平,还能了解到实际...

    Springside-core-4.1.0/Springside-core-4.1.0

    SpringSide-core是SpringSide项目的核心部分,包含了项目的基础构建模块和核心功能。4.1.0版本是SpringSide的一个重要里程碑,它带来了诸多改进和优化。 二、SpringSide-core-4.1.0关键组件 1. **依赖管理**:...

    springside

    在SpringSide的压缩包文件中,"springside"可能是一个示例项目的根目录,包含了项目的所有源代码、配置文件和资源。通过分析这个目录,我们可以学习到SpringSide如何组织项目结构,以及如何配置和使用Spring的各个...

    springside开发全面讲解

    1. **模块化设计**:springside采用模块化设计,将项目划分为多个独立的模块,如核心模块、安全模块、AOP模块等,使得代码结构清晰,易于维护和扩展。 2. **依赖管理**:springside使用Maven进行依赖管理,通过预...

    springside-3.2.2源码

    1. `core`:核心模块,包含 SpringSide 的基础工具类和配置管理,如日志、国际化、属性文件处理等。 2. `modules`:模块化设计,包括示例模块、数据库访问模块、Web 模块等,便于开发者根据需求选择使用。 3. `tools...

    SpringSide4 参考手册

    这些部分讲述了如何进行动态组合查询条件、使用Hibernate二级缓存、以及如何配置数据源和事务管理。 为了提升性能,文档介绍了各种缓存技术,包括Ehcache、Guava Cache以及分布式缓存的实现。还提到了如何在Ehcache...

    springside3.0.1.zip

    通过对SpringSide 3.0.1源代码的深入研究,不仅可以加深对Spring框架的理解,还能了解到现代Java企业级开发的各种最佳实践和工具使用。这是一次难得的学习和提升技术的机会,对于任何想要成为专业Java开发者的人来说...

    springside示例quickstart的eclipse工程

    这个工程包含了一系列配置文件、源代码和资源,帮助用户理解Spring框架的核心概念和工作方式。 在Eclipse工程中,我们通常会看到以下关键组成部分: 1. **pom.xml**:这是Maven项目的配置文件,定义了项目依赖、...

    springside-core.rar

    4.1.0.GA版本是该项目的一个稳定发布,包含了对SpringSide核心功能的优化和改进,确保了代码的稳定性和性能。 首先,"springside-core-4.1.0.GA"是核心模块的主JAR文件,其中封装了SpringSide的核心类和接口。这个...

    springside3.0.zip

    《SpringSide 3.0:Java企业开发的高效框架指南》 SpringSide 3.0 是一个基于Spring框架的开源项目,旨在为Java...理解并掌握SpringSide 3.0 的核心知识点,对于提升Java企业级应用的开发效率和质量具有重要意义。

    springside3.3.4 使用方法

    - 构建过程会自动下载所需的依赖库、编译Java源代码、执行单元测试并打包成WAR文件。 2. **部署项目**: - 将构建好的WAR文件部署到Web服务器上(例如Tomcat或Jetty)。 - 启动Web服务器,并访问部署的应用程序...

    springside.jar

    本文将深入探讨springside.jar的核心功能,以及如何在实际项目中有效利用它。 一、springside.jar简介 springside.jar是基于Spring框架的一个轻量级工具库,旨在简化企业级Java开发。它由springside-project组织...

    springside3.3完整版

    本版本,即“springside3.3”,是专为MyEclipse集成环境设计的,包含了完整的功能代码,方便开发者在MyEclipse中进行开发和调试。同时,它还附带了数据.sql文件,意味着我们可以直接导入数据库,快速搭建项目环境。 ...

    有springside4.2.3-GA.jar 包

    1. **Core**:这是SpringSide的核心模块,包含了一些通用的工具类和配置,如日志管理、代码生成器、属性文件管理等,为项目提供了基础服务。 2. **Demo**:示例模块,提供了各种应用场景的实例,帮助开发者快速理解...

    springside-3.3.4-src

    通过深入研究 SpringSide 3.3.4 的源代码,开发者不仅能掌握 Spring 框架的使用,还能学习到如何构建高效、可维护的企业级应用。同时,对于想要提升自身 Java 开发技能的程序员来说,SpringSide 是一个不可多得的...

    springside-core-4.2.2.GA相关jar包

    4. **代码规范和最佳实践**:SpringSide强调代码质量,提供了统一的编码风格和最佳实践,这有助于保持团队间的代码一致性,并提高代码可读性和维护性。 5. **项目模板**:SpringSide通常包含一系列预定义的项目模板...

    springside-4.0.0.GA.zip

    通过深入研究SpringSide 4.0.0.GA,开发者可以学习到如何有效地整合Spring Framework和其他相关技术,提升自己的JavaEE开发技能。无论是对于新手还是资深开发者,SpringSide都是一个不可多得的学习和参考资料库,它...

    springside3源码及jar

    《深入解析springside3:源码与jar剖析》 springside3是一个基于Spring框架的轻量级Java开发工具集,它旨在简化企业级应用的开发过程...对于想要深入了解Java企业级开发的程序员来说,研究springside3无疑是一条捷径。

    springside3文档资料收录

    SpringSide3不仅包含了Spring框架的核心概念,还涵盖了Spring在实际开发中的各种应用场景,帮助开发者深入理解并熟练运用Spring进行软件开发。 一、Spring框架概述 Spring是一个开源的企业级应用框架,它以依赖注入...

Global site tag (gtag.js) - Google Analytics