论坛首页 Java企业应用论坛

应用Hibernate3的DetachedCriteria实现分页查询

浏览 154809 次
该帖已经被评为精华帖
作者 正文
   发表时间:2005-08-30  
看了robbin和downpour的文章,感觉非常棒,我就拿来试试.
个人觉得DetachedCriteria的动态查询(QBC)还是优于HQL的,所以觉得采用QBC来进行查询.但是downpour的层次性好,而且把page分页类的初始化和操作分开,将页面对象化,那么涉及到页面的时候只要传一个page对象,至于内部page是如何的可以不用管了,又更好的封装性.但是从算法而言,两位牛人的应该是一样的.
所以我想把两个结合一下,利用downpour GG的层次结构,用QBC(DetachedCriteria)查询条件...前面的原封不动,只要在DAO实现这里修改一下就行了.但是具体实现有问题,我是个初学者,对这些东西的原理还不是很清楚.
/*Created on 2005-7-15*/ 
package com.adt.dao.impl; 

import java.util.List; 

import org.flyware.util.page.Page; 

import net.sf.hibernate.HibernateException; 
import net.sf.hibernate.Query; 

import com.adt.dao.UserDAO; 

/** 
* @author Joa 
*/ 
public class UserDAOImpl extends BaseDAOHibernateImpl implements UserDAO { 

    /* (non-Javadoc); 
     * @see com.adt.dao.UserDAO#getUserByName(java.lang.String); 
     */ 
    public List getUserByName(String name); throws HibernateException { 
        String querySentence = "FROM user in class com.adt.po.User WHERE user.name=:name"; 
        Query query = getSession();.createQuery(querySentence);; 
        query.setParameter("name", name);; 
        return query.list();; 
    } 

    /* (non-Javadoc); 
     * @see com.adt.dao.UserDAO#getUserCount(); 
     */ 
    public int getUserCount(); throws HibernateException { 
        int count = 0; 
        String querySentence = "SELECT count(*); FROM user in class com.adt.po.User"; 
        Query query = getSession();.createQuery(querySentence);; 
        count = ((Integer);query.iterate();.next(););.intValue();; 
        return count; 
    } 

    /* (non-Javadoc); 
     * @see com.adt.dao.UserDAO#getUserByPage(org.flyware.util.page.Page); 
     */ 
    public List getUserByPage(Page page); throws HibernateException { 
        String querySentence = "FROM user in class com.adt.po.User"; 
        Query query = getSession();.createQuery(querySentence);; 
        query.setFirstResult(page.getBeginIndex();); 
                .setMaxResults(page.getEveryPage(););; 
        return query.list();; 
    } 

} 


下面是我写的一点,把上面的HQL转换成QBC..很明显有问题,希望懂的达人帮忙给我看看
    public List getStudentByPage(Page page); throws HibernateException { 
    	//HQL实现
        String querySentence = "FROM user in class com.adt.po.User"; 
        Query query = getSession();.createQuery(querySentence);; 
    	
        //DetachedCriteria实现
		//处理JSF参数
		studentId = FacesUtils.getRequestParameter("query:stuId");;
		studentName = FacesUtils.getRequestParameter("query:stuName");;
		studentSex = FacesUtils.getRequestParameter("query:sex");;
		studentDegree = FacesUtils.getRequestParameter("query:degree");;
		studentProvince = FacesUtils.getRequestParameter("query:province");;
		

		this.logger.debug("------------studentName----> "+ studentId);;
		this.logger.debug("------------studentName----> "+ studentName);;
		this.logger.debug("------------studentName----> "+ studentSex);;
		this.logger.debug("------------studentName----> "+ studentDegree);;
		this.logger.debug("------------studentName----> "+ studentProvince);;
		
		//设置页面
		int pageSize = 10;
		int startIndex = 0;
		
		//构造DetachedCriteria
		DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Student.class);;
		detachedCriteria.add(Restrictions.eq("stuName", studentName););;
		
		Criteria criteria = null;//这里不知道怎么写,肯定不是这样写的
		
		criteria.setFirstResult(page.getBeginIndex(););
		        .setMaxResults(page.getEveryPage(););;
		
		return criteria.list();;
    } 

		Criteria criteria = null;//这里该怎么写???在看到的资料都要涉及到session...DetachedCriteria好像没setFirstResult和setMaxResults..如何讲Criteria和DetachedCriteria联系起来,还是有其他的方法写这个???
0 请登录后投票
   发表时间:2005-08-30  
我也用了robbin的方法来做,直接QBC查询
在bean里面的action里实现分页
public String queryAction();{
		this.logger.debug("get into queryAction!!!!!!!!!");;
		
		try{

			//处理JSF参数
			studentId = FacesUtils.getRequestParameter("query:stuId");;
			studentName = FacesUtils.getRequestParameter("query:stuName");;
			studentSex = FacesUtils.getRequestParameter("query:sex");;
			studentDegree = FacesUtils.getRequestParameter("query:degree");;
			studentProvince = FacesUtils.getRequestParameter("query:province");;
			
	
			this.logger.debug("------------studentName----> "+ studentId);;
			this.logger.debug("------------studentName----> "+ studentName);;
			this.logger.debug("------------studentName----> "+ studentSex);;
			this.logger.debug("------------studentName----> "+ studentDegree);;
			this.logger.debug("------------studentName----> "+ studentProvince);;
			
			//设置页面
			int pageSize = 10;
			int startIndex = 0;
			
			//构造DetachedCriteria
			DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Student.class);;
			detachedCriteria.add(Restrictions.eq("stuName", studentName););;
			
//			//直接查询
//			PaginationSupport ps = AbstractManager.findPageByCriteria(DetachedCriteria
//					.forClass(Student.class);, PageUtil.getEveryPage(pageSize);, PageUtil.getBeginIndex(startIndex););; 
	
			PaginationSupport ps = AbstractManager.findPageByCriteria(detachedCriteria, pageSize, startIndex);; 
			

			
			ps.getItems();;     		//得到已分页好的结果集 
			ps.getIndexes();;		//得到分页索引的数组 
			ps.getTotalCount();;		//得到总结果数 
			ps.getStartIndex();;		//当前分页索引 
			ps.getNextIndex();;		//下一页索引 
			ps.getPreviousIndex();;	//上一页索引
			

			
			
			//调用service
			List listStu = this.serviceLocator.getStudentService();.getStudents(detachedCriteria);;
			//List listStu = this.serviceLocator.getStudentService();.findStudent(stuId,stuName);;
			
//			this.logger.debug("listStu.size(); = "+ listStu.size(); );;
			
			//处理返回的纪录集
			for (int i=0; i<listStu.size();; i++); {
				Student stu = (Student);listStu.get(i);;
				StudentBean studentBean = StudentBuilder.createStudentBean(stu);;
				studentBean.setServiceLocator(this.serviceLocator);;
				this.studentBeans.add(studentBean);;
				this.logger.debug("listStu==i= "+i );;
		    }	
		
		}catch (AppException ce); {
			String msg = "Could not retrieve Students " ;
			this.logger.debug(msg, ce);;
			
			throw new FacesException(msg, ce);;
		}
		return "QUERY_SUCCESS" ;
	}


			PaginationSupport ps = AbstractManager.findPageByCriteria(detachedCriteria, pageSize, startIndex);; 
这里说返回类型不对,static和non-static..应该是返回的类型不对吧...

这个有问题吗??有什么不规范和不对的地方吗????
0 请登录后投票
   发表时间:2005-09-19  

/**
 * 分页信息接口
 */
public interface Page <E>extends Serializable,Iterable
{
    /**
     * 是否是首页(第一页),第一页页码为1
     *
     * @return 首页标识
     */
    public boolean isFirstPage();;

    /**
     * 是否是最后一页
     *
     * @return 末页标识
     */
    public boolean isLastPage();;

    /**
     * 是否有下一页
     *
     * @return 下一页标识
     */
    public boolean hasNextPage();;

    /**
     * 是否有上一页
     *
     * @return 上一页标识
     */
    public boolean hasPreviousPage();;

    /**
     * 获取最后一页页码,也就是总页数
     *
     * @return 最后一页页码
     */
    public int getLastPageNumber();;

    /**
     * 当前页包含的数据,不同的情况可能返回的数据类型不一样,如List,RowSet等,请参考具体的实现
     *
     * @return 当前页数据源
     */
    public E getThisPageElements();;

    /**
     * 总的数据条目数量,0表示没有数据
     *
     * @return 总数量
     */
    public int getTotalNumberOfElements();;

    /**
     * 获取当前页的首条数据的行编码
     *
     * @return 当前页的首条数据的行编码
     */
    public int getThisPageFirstElementNumber();;

    /**
     * 获取当前页的末条数据的行编码
     *
     * @return 当前页的末条数据的行编码
     */
    public int getThisPageLastElementNumber();;

    /**
     * 获取下一页编码
     *
     * @return 下一页编码
     */
    public int getNextPageNumber();;

    /**
     * 获取上一页编码
     *
     * @return 上一页编码
     */
    public int getPreviousPageNumber();;

    /**
     * 每一页显示的条目数
     *
     * @return 每一页显示的条目数
     */
    public int getPageSize();;

    /**
     * 当前页的页码
     *
     * @return 当前页的页码
     */
    public int getThisPageNumber();;

}


BasePage用于其它的page子类继承

/**
 * 高层的Page接口实现
 * 
 * @author QIU
 */
public class BasePage<E> implements Page {

	protected E elements;

	protected int pageSize;

	protected int pageNumber;

	protected int totalElements = 0;

	public BasePage(int pageNumber, int pageSize, int totalElements); {
		this.pageNumber = pageNumber;
		this.pageSize = pageSize;
		this.totalElements = totalElements;
		recomputePageNumber();;
	}

	public BasePage(int pageNumber, int pageSize); {
		this.pageNumber = pageNumber;
		this.pageSize = pageSize;
	}

	/**
	 * 重新计算当前页的号码
	 */
	protected void recomputePageNumber(); {
		if (Integer.MAX_VALUE == this.pageNumber
				|| this.pageNumber > getLastPageNumber();); { //last page
			this.pageNumber = getLastPageNumber();;
		}
	}

	public boolean isFirstPage(); {
		return getThisPageNumber(); == 1;
	}

	public boolean isLastPage(); {
		return getThisPageNumber(); >= getLastPageNumber();;
	}

	public boolean hasNextPage(); {
		return getLastPageNumber(); > getThisPageNumber();;
	}

	public boolean hasPreviousPage(); {
		return getThisPageNumber(); > 1;
	}

	public int getLastPageNumber(); {
		return totalElements % this.pageSize == 0 ? 
				totalElements/ this.pageSize 
				: totalElements / this.pageSize + 1;
	}

	public E getThisPageElements(); {
		return elements;
	}

	public int getTotalNumberOfElements(); {
		return totalElements;
	}

	public int getThisPageFirstElementNumber(); {
		return (getThisPageNumber(); - 1); * getPageSize(); + 1;
	}

	public int getThisPageLastElementNumber(); {
		int fullPage = getThisPageFirstElementNumber(); + getPageSize(); - 1;
		return getTotalNumberOfElements(); < fullPage ? getTotalNumberOfElements(); : fullPage;
	}

	public int getNextPageNumber(); {
		return getThisPageNumber(); + 1;
	}

	public int getPreviousPageNumber(); {
		return getThisPageNumber(); - 1;
	}

	public int getPageSize(); {
		return pageSize;
	}

	public int getThisPageNumber(); {
		return pageNumber;
	}
	/**
	 * 实现Iterable遍历接口
	 * @return 等价((Iterable);getThisPageElements(););.iterator();
	 * @throws UnsupportedOperationException 
	 * 		   当getThisPageElements();不是Iterable接口
	 * @See java.lang.Iterable
	 */
	public Iterator iterator(); {
		if(getThisPageElements(); instanceof Iterable); {
			return ((Iterable);getThisPageElements(););.iterator();;
		}
		else {
			throw new UnsupportedOperationException("iterator(); method is unsupported");;
		}
	}
	

}


现在我们的HibernatePage实现类,只需简单的执行一下查询就行了
/**
 * Hibernate分页信息
 * @see BasePage
 */
public class HibernatePage extends BasePage implements Page
{

    /**
     * 构建HibernatePage对象,完成Hibernate的Query数据的分页处理
     *
     * @param query      Hibernate的Query对象
     * @param pageNumber 当前页编码,从1开始,如果传的值为Integer.MAX_VALUE表示获取最后一页。
     *                   如果你不知道最后一页编码,传Integer.MAX_VALUE即可。如果当前页超过总页数,也表示最后一页。
     *                   这两种情况将重新更改当前页的页码,为最后一页编码。
     * @param pageSize   每一页显示的条目数
     */
    public HibernatePage(Query query, int pageNumber, int pageSize);
    {
        super(pageNumber,pageSize);;
        try
        {
            ScrollableResults scrollableResults = query.scroll();;
            //get the total elements number
            scrollableResults.last();;
            this.totalElements = scrollableResults.getRowNumber();;
            recomputePageNumber();;
            elements = query.setFirstResult((this.pageNumber - 1); * this.pageSize);.setMaxResults(this.pageSize + 1);.list();;
        } catch (HibernateException e);
        {
            throw new RuntimeException(e);;
        }
    }
    
    /**
     * 构建HibernatePage对象,完成Hibernate的Query数据的分页处理
     *
     * @param selectQuery      	Hibernate的查询Query对象
     * @param countQuery		Hibernate的查询总数据行数的Query对象
     * @param pageNumber 当前页编码,从1开始,如果传的值为Integer.MAX_VALUE表示获取最后一页。
     *                   如果你不知道最后一页编码,传Integer.MAX_VALUE即可。如果当前页超过总页数,也表示最后一页。
     *                   这两种情况将重新更改当前页的页码,为最后一页编码。
     * @param pageSize   每一页显示的条目数
     */
    public HibernatePage(Query selectQuery, Query countQuery,int pageNumber, int pageSize);
    {
    	super(pageNumber,pageSize);;
        try
        {
            //得到总记录数
            this.totalElements = ((Integer);countQuery.uniqueResult(););.intValue();;
            recomputePageNumber();;
            elements = selectQuery
            	.setFirstResult((this.pageNumber - 1); * this.pageSize);
            	.setMaxResults(this.pageSize + 1);
            	.list();;
            
        } catch (HibernateException e);
        {
            throw new RuntimeException(e);;
        }
    }
}


EJB3.0的Page接口实现EJBPage
/**
 * EJB分页信息
 * @author QIU
 * @see BasePage
 */
public class EJBPage extends BasePage {
	
	public EJBPage(Query selectQuery,Query countQuery,int pageNumber,int pageSize); {
		
		super(pageNumber,pageSize);;
		this.totalElements = (Integer);countQuery.getSingleResult();;
		recomputePageNumber();;
		this.elements = selectQuery
			.setFirstResult((this.pageNumber - 1); * this.pageSize);
			.setMaxResults(this.pageSize + 1);
			.getResultList();;
	}
	
}
0 请登录后投票
   发表时间:2005-09-19  
JDBCPage

/**
* Jdbc分页信息,需要Jdk 1.5的支持
* @see Page
* @see BasePage
*/
public class JdbcPage extends BasePage //implements Page
{
//    private CachedRowSet elements;
//    private int pageSize;
//    private int pageNumber;
//    private int totalElements = 0;

    /**
     * 构建JdbcPage对象,完成JDBC的ResultSet分页处理
     *
     * @param rs         ResultSet对象,ResultSet必须是可滚动的数据集,可以通过以下的Statement执行查询。
     *                   Statement stmt = conn.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
     * @param pageNumber 当前页编码,从1开始,如果传的值为Integer.MAX_VALUE表示获取最后一页。
     *                   如果你不知道最后一页编码,传Integer.MAX_VALUE即可。如果当前页超过总页数,也表示最后一页。
     *                   这两种情况将重新更改当前页的页码,为最后一页编码。
     * @param pageSize   每一页显示的条目数
     */
    public JdbcPage(ResultSet rs, int pageNumber, int pageSize)
    {
    super(pageNumber,pageSize);
        try
        {
            //get the total elements number
            rs.last();
            totalElements = rs.getRow();
//            if (this.pageNumber == Integer.MAX_VALUE || this.pageNumber > getLastPageNumber())
//            {
//                this.pageNumber = getLastPageNumber();
//            }
            recomputePageNumber();
            CachedRowSet elements = new CachedRowSetImpl();
            elements.setMaxRows(this.pageSize);
            elements.setPageSize(this.pageSize);
            elements.populate(rs, (this.pageNumber - 1) * this.pageSize);
            this.elements = elements;
           
        } catch (SQLException e)
        {
            throw new RuntimeException(e);
        }
    }
   
    /**
     * 构建JdbcPage对象,完成JDBC的ResultSet分页处理
     *
     * @param rs         ResultSet对象,ResultSet必须是可滚动的数据集,可以通过以下的Statement执行查询。
     *                   Statement stmt = conn.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
     * @param pageNumber 当前页编码,从1开始,如果传的值为Integer.MAX_VALUE表示获取最后一页。
     *                   如果你不知道最后一页编码,传Integer.MAX_VALUE即可。如果当前页超过总页数,也表示最后一页。
     *                   这两种情况将重新更改当前页的页码,为最后一页编码。
     * @param pageSize   每一页显示的条目数
     */
    public JdbcPage(ResultSet rs,BusinessObjectCreator creator, int pageNumber, int pageSize)
    {
    super(pageNumber,pageSize);
        try
        {
            //get the total elements number
            rs.last();
            totalElements = rs.getRow();
            recomputePageNumber();
           
            this.elements = populateIntoList(rs,creator,pageNumber,pageSize);
           
        } catch (SQLException e){
            throw new RuntimeException(e);
        }
    }
   
private static List populateIntoList(ResultSet rs, BusinessObjectCreator factory, int pageNumber, int pageSize) throws SQLException {
List result = new ArrayList();
//移动到页码的第一条记录,忽略第一页
if(pageNumber>1){
      rs.absolute(((pageNumber-1)*pageSize));
}
for(int i=0;i<pageSize;i++){
      if(rs.next()){
        result.add(factory.getBusinessObject(rs));
      } else{
        if(i==0){ //没有记录的情况
        return null;
        }
        break;
      }
   }
return result;
}
}


BusinessObjectCreator接口
/**
 * 业务对象创建接口,用于JDBCPage创建对象方法回调
 * @author QIU
 *
 */
public interface BusinessObjectCreator {
	public Object getBusinessObject(ResultSet rs);;
}
0 请登录后投票
   发表时间:2005-09-20  
/**
 * Hibernate使用Criteria分页信息
 * @author QIU
 *
 */
public class CriteriaPage extends BasePage{

	public CriteriaPage(Criteria criteria,int pageNumber, int pageSize); {
		super(pageNumber,pageSize);;
		//得到总记录数
		ScrollableResults scrollableResults = criteria.scroll();;
		scrollableResults.last();;
		this.totalElements = scrollableResults.getRowNumber();;
		
		recomputePageNumber();;
		elements = criteria
			.setFirstResult((this.pageNumber - 1); * this.pageSize);
			.setMaxResults(this.pageSize + 1);.list();;
	}

}


重贴JdbcPage

/**
 * Jdbc分页信息,需要Jdk 1.5的支持
 * @see Page
 * @see BasePage
 */
public class JdbcPage extends BasePage //implements Page
{
//    private CachedRowSet elements;
//    private int pageSize;
//    private int pageNumber;
//    private int totalElements = 0;

    /**
     * 构建JdbcPage对象,完成JDBC的ResultSet分页处理
     *
     * @param rs         ResultSet对象,ResultSet必须是可滚动的数据集,可以通过以下的Statement执行查询。
     *                   Statement stmt = conn.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);;
     * @param pageNumber 当前页编码,从1开始,如果传的值为Integer.MAX_VALUE表示获取最后一页。
     *                   如果你不知道最后一页编码,传Integer.MAX_VALUE即可。如果当前页超过总页数,也表示最后一页。
     *                   这两种情况将重新更改当前页的页码,为最后一页编码。
     * @param pageSize   每一页显示的条目数
     */
    public JdbcPage(ResultSet rs, int pageNumber, int pageSize);
    {
    	super(pageNumber,pageSize);;
        try
        {
            //get the total elements number
            rs.last();;
            totalElements = rs.getRow();;
//            if (this.pageNumber == Integer.MAX_VALUE || this.pageNumber > getLastPageNumber(););
//            {
//                this.pageNumber = getLastPageNumber();;
//            }
            recomputePageNumber();;
            CachedRowSet elements = new CachedRowSetImpl();;
            elements.setMaxRows(this.pageSize);;
            elements.setPageSize(this.pageSize);;
            elements.populate(rs, (this.pageNumber - 1); * this.pageSize);;
            this.elements = elements;
            
        } catch (SQLException e);
        {
            throw new RuntimeException(e);;
        }
    }
    
    /**
     * 构建JdbcPage对象,完成JDBC的ResultSet分页处理
     *
     * @param rs         ResultSet对象,ResultSet必须是可滚动的数据集,可以通过以下的Statement执行查询。
     *                   Statement stmt = conn.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);;
     * @param pageNumber 当前页编码,从1开始,如果传的值为Integer.MAX_VALUE表示获取最后一页。
     *                   如果你不知道最后一页编码,传Integer.MAX_VALUE即可。如果当前页超过总页数,也表示最后一页。
     *                   这两种情况将重新更改当前页的页码,为最后一页编码。
     * @param pageSize   每一页显示的条目数
     */
    public JdbcPage(ResultSet rs,BusinessObjectCreator creator, int pageNumber, int pageSize);
    {
    	super(pageNumber,pageSize);;
        try
        {
            //get the total elements number
            rs.last();;
            totalElements = rs.getRow();;
            recomputePageNumber();;
            
            this.elements = populateIntoList(rs,creator,pageNumber,pageSize);;
            
        } catch (SQLException e);{
            throw new RuntimeException(e);;
        }
    }
    
	private static List populateIntoList(ResultSet rs, BusinessObjectCreator factory, int pageNumber, int pageSize); throws SQLException {
		List result = new ArrayList();;
		//移动到页码的第一条记录,忽略第一页
		if(pageNumber>1);{
		      rs.absolute(((pageNumber-1);*pageSize););;
		}
		for(int i=0;i<pageSize;i++);{
		      if(rs.next(););{
		        result.add(factory.getBusinessObject(rs););;
		      } else{
		        if(i==0);{ //没有记录的情况
		        	return null;
		        }
		        break;
		      }
		   }
		return result;
	}
}


/**
 * 业务对象创建接口,用于JDBCPage创建对象方法回调
 * @author QIU
 *
 */
public interface BusinessObjectCreator {
	public Object getBusinessObject(ResultSet rs);;
}


其它的Page接口实现,我们只需简单的继承BasePage,轻松的就可以增加对Page的实现.Page接口详细可以查看Hibernate官网上的描述
0 请登录后投票
   发表时间:2005-09-21  

ScrollableResults scrollableResults = query.scroll();
//get the total elements number
scrollableResults.last();
this.totalElementsCount = scrollableResults.getRowNumber() + 1;
我使用oracle9i + oracle10 jdbc driver, 在数据量大的情况下,会有outofmemery exception的
0 请登录后投票
   发表时间:2005-10-18  
今天试了一下robbin的分页方法,发现一个问题

方法代码:
 public PaginationSupport findPageByCriteria(final DetachedCriteria detachedCriteria, final int pageSize, 
                        final int startIndex); { 
                return (PaginationSupport); getHibernateTemplate();.execute(new HibernateCallback(); { 
                        public Object doInHibernate(Session session); throws HibernateException { 
                                Criteria criteria = detachedCriteria.getExecutableCriteria(session);; 
                                int totalCount = ((Integer); criteria.setProjection(Projections.rowCount(););.uniqueResult(););.intValue();; 
                                [b]criteria.setProjection(null);;[/b]
                                List items = criteria.setFirstResult(startIndex);.setMaxResults(pageSize);.list();; 
                                PaginationSupport ps = new PaginationSupport(items, totalCount, pageSize, startIndex);; 
                                return ps; 
                        } 
                }, true);; 
        }


调用代码:
DetachedCriteria dc=DetachedCriteria .forClass(Cat.class);;
dc.createAlias("mate","mt");
   .add(Property.forName("mt.name");.like("miaomiao",MatchMode.ANYWHERE););;
PaginationSupport ps = findPageByCriteria(dc,20,0);;
List list = ps.getItems();;
[b]Object[] objects = Object[] list.get(0);;[/b]


发现返回的List里面放的不是我本来想要的Cat, 而是Object[].
0 请登录后投票
   发表时间:2005-10-18  
经过测试,看来问题出在 criteria.setProjection(null); 上。
0 请登录后投票
   发表时间:2005-12-23  
有没有解决方案啊?
0 请登录后投票
   发表时间:2005-12-23  
goldapple 写道
有没有解决方案啊?


package com.skyon.cams.util;

import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

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.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.impl.CriteriaImpl.OrderEntry;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.util.Assert;

import com.skyon.framework.core.SkyonException;
import com.skyon.framework.dao.PaginationSupport;

/**
 * 一些常用的 Hibernate 方法, 注意, 一些方法可能只适用于 Hibernate3.0.5 !!!
 * @see org.springframework.orm.hibernate3.HibernateTemplate
 * @since 2005-9-13
 * @author 王政
 * @version $Id: HibernateUtils.java,v 1.4 2005/09/19 01:00:28 wangzheng Exp $
 */
public abstract class HibernateUtils {
	
	private static Log logger = LogFactory.getLog(HibernateUtils.class);;
	
	public static final String CRITERIA_ASSERT_ERROR_MESSAGE = " 's type is not " + CriteriaImpl.class + ", please make sure you are using Hibernate3.0.5!!! ";
	
    /**
     * 将 Criteria 加上分页条件并输出结果
     * @param criteria the criteria
     * @param offset the offset
     * @param maxPageItems the maxPageItems
     * @return the result list
     */
    public static List getPageResult(Criteria criteria, int offset, int maxPageItems); throws HibernateException {
        criteria.setFirstResult(offset);;
        criteria.setMaxResults(maxPageItems);;
        return criteria.list();; 
    }
    
	/**
	 * 根据 DetachedCriteria 得 到 分页结果, 运行期间会根据 criteria  自动运算总行数, 注意如果 criteria 中 set 了 Projection, 则返回结果 List 中为 Projection 指定类型
	 * @param hibernateTemplate	 the hibernateTemplate
	 * @param criteria the criteria
	 * @param firstResult the first result row number 
	 * @param maxResults the max result 
	 * @return the pagination support
	 * @throws org.springframework.dao.DataAccessException in case of Hibernate errors 
	 */
	public static PaginationSupport findByCriteria(HibernateTemplate hibernateTemplate, final DetachedCriteria criteria, final int firstResult, final int maxResults); 
		throws DataAccessException {
		
		return (PaginationSupport); hibernateTemplate.execute(new HibernateCallback(); {
			public Object doInHibernate(Session session); throws HibernateException, SQLException {
				Criteria executableCriteria = criteria.getExecutableCriteria(session);;
				
				// Get the orginal orderEntries
				OrderEntry[] orderEntries = HibernateUtils.getOrders(executableCriteria);;
				// Remove the orders
				executableCriteria = HibernateUtils.removeOrders(executableCriteria);;				
				// get the original projection
				Projection projection = HibernateUtils.getProjection(executableCriteria);;
				
                int totalCount = ((Integer); executableCriteria.setProjection(Projections.rowCount(););.uniqueResult(););.intValue();;
                
                executableCriteria.setProjection(projection);;
                if (projection == null); {
                	// Set the ResultTransformer to get the same object structure with hql
                	executableCriteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);;
                }              
                // Add the orginal orderEntries
                executableCriteria = HibernateUtils.addOrders(executableCriteria, orderEntries);;
                
                // Now, the Projection and the orderEntries have been resumed
                List items = HibernateUtils.getPageResult(executableCriteria, firstResult, maxResults);;						
				return new PaginationSupport(items, totalCount, firstResult, maxResults);;
			}
		}, true);;
	}
	
	/**
	 * 根据 hql 得 到 总行数
	 * @param hibernateTemplate
	 * @param queryString hql
	 * @param isNamedQuery 是否是 named query
	 * @param paramNames 如果是 named query, 为 named query 中的参数名称, 否则无意义
	 * @param paramValues 参数值
	 * @return 满足条件的总行数
	 * @throws IllegalArgumentException if queryString is blank
	 * @throws org.springframework.dao.DataAccessException in case of Hibernate errors 
	 */
	public static int getTotalCount(HibernateTemplate hibernateTemplate, String queryString, boolean isNamedQuery, String[] paramNames, Object[] paramValues); 
		throws IllegalArgumentException, DataAccessException {
		if (StringUtils.isBlank(queryString);); {
    		throw new IllegalArgumentException(" queryString can't be blank ");;
    	}
    	    	
		String countQueryString = " select count (*); " + JdbcUtils.removeSelect(JdbcUtils.removeOrders(queryString););;
		
		List countList;
		
		if (isNamedQuery); {
			countList = hibernateTemplate.findByNamedParam(countQueryString, paramNames, paramValues);;			
		} else {
			countList = hibernateTemplate.find(countQueryString, paramValues);;		
		}
		
		return ((Integer); countList.get(0););.intValue();;
	}
    
	
    /**
     * 从 criteria 中取得 {@link Projection}, 接口中没有公开此方法, 因此从 {@link CriteriaImpl} 中取得
     * @see CriteriaImpl#getProjection();
     * @param criteria the criteria
     * @return the Projection
     */
    public static Projection getProjection(Criteria criteria); {
    	assertType(criteria);;
    	CriteriaImpl impl = (CriteriaImpl); criteria;
    	return impl.getProjection();;
    }
    
    
	private static void assertType(Criteria criteria); {
		Assert.notNull(criteria, " criteria is required. ");;
		String message = criteria + CRITERIA_ASSERT_ERROR_MESSAGE;
		if (! CriteriaImpl.class.isInstance(criteria);); {
    		if (logger.isDebugEnabled();); {
    			logger.debug(message);;
    		}
    		throw new SkyonException(message);;
    	}
	}
    
	/**
	 * 得到 criteria 中的 OrderEntry[]
	 * @param criteria the criteria
	 * @return the OrderEntry[]
	 */
    public static OrderEntry[] getOrders(Criteria criteria); {
    	assertType(criteria);;
		CriteriaImpl impl = (CriteriaImpl); criteria;
		Field field = getOrderEntriesField(criteria);;
		try {
			return (OrderEntry[]); ((List); field.get(impl););.toArray(new OrderEntry[0]);;
		} catch (Exception e); {
    		logAndThrowException(criteria, e);;
    		throw new InternalError(" Runtime Exception impossibility can't throw ");;
		} 
    }
    
    
	/**
	 * 移除 criteria 中的 OrderEntry[]
	 * @param criteria the criteria
	 * @return the criteria after removed OrderEntry[]
	 */
    public static Criteria removeOrders(Criteria criteria); {
    	assertType(criteria);;
    	CriteriaImpl impl = (CriteriaImpl); criteria;
    	
    	try {
        	Field field = getOrderEntriesField(criteria);;
        	field.set(impl, new ArrayList(););;
        	return impl;
    	} catch (Exception e); {
    		logAndThrowException(criteria, e);;
    		throw new InternalError(" Runtime Exception impossibility can't throw ");;
    	}	
    }

    /**
     * 为 criteria 增加 OrderEntry[]
     * @param criteria the criteria
     * @param orderEntries the OrderEntry[]
     * @return the criteria after add OrderEntry[]
     */
    public static Criteria addOrders(Criteria criteria, OrderEntry[] orderEntries); {
    	assertType(criteria);;
    	CriteriaImpl impl = (CriteriaImpl); criteria;
    	try {
        	Field field = getOrderEntriesField(criteria);;
        	for (int i = 0; i < orderEntries.length; i++); {
        		List innerOrderEntries = (List); field.get(criteria);;
        		innerOrderEntries.add(orderEntries[i]);;
        	}
        	return impl;
    	} catch (Exception e); {
    		logAndThrowException(criteria, e);;
    		throw new InternalError(" Runtime Exception impossibility can't throw ");;
    	}
    }

	private static void logAndThrowException(Criteria criteria, Exception e); {
		String message = criteria + CRITERIA_ASSERT_ERROR_MESSAGE;
		if (logger.isDebugEnabled();); {
			logger.debug(message, e);;
		}
		throw new SkyonException(message, e);;
	}
    
	private static Field getOrderEntriesField(Criteria criteria); {
		Assert.notNull(criteria, " criteria is requried. " );;
		try {
			Field field = CriteriaImpl.class.getDeclaredField("orderEntries");;
			field.setAccessible(true);;
			return field;
		} catch (Exception e); {
			logAndThrowException(criteria, e);;
    		throw new InternalError();;
		}
	}
}

0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics