论坛首页 Java企业应用论坛

查询的分页问题,考虑性能

浏览 42650 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-12-28  
用Hibernate进行查询,如果返回数据量很大的话,我们一般要用iterator()方法,而且再调用这个方法之前,要先有个Query对象,然后给Query设置first,maxResults,我们页面上的分页导航栏是需要本次查询的总记录数总页面数,但是现在我们只知道本页面的记录数,我们有什么好办法拿到总的记录数吗?最好不要再增加数据库的查询操作了,因为目前已经有pagesize+1次查询了。
   发表时间:2004-12-28  
sorry,没太看明白你的意思,但有一点我不是很明白,为什么一定要用iterator,请看robbin的文章http://www.hibernate.org.cn/41.html,不过希望下面的小方法能对你有所帮助。
public class Page {
   
   private List results;
   private int pageSize;
   private int page;
   
   public Page(Query query, int page, int pageSize); {
       
       this.page = page;
       this.pageSize = pageSize;
       results = query.setFirstResult(page * pageSize);
           .setMaxResults(pageSize+1);
           .list();;
   
   }
   
   public boolean isNextPage(); {
       return results.size(); > pageSize;
   }
   
   public boolean isPreviousPage(); {
       return page > 0;
   }
   
   public List getList(); {
       return isNextPage(); ?
           results.subList(0, pageSize-1); :
           results;
   }

}

public Page getPosts(int page); {
    return new Page( 
        session.createQuery("from Posts p order by p.date desc");
        page,
        40
    );;
}

扩展一下我想应该可以满足大多数的需要,想要屏蔽list提供一个统一的接口可以list.iterator()一下。
0 请登录后投票
   发表时间:2004-12-28  
不知道楼主是怎么做的,不过用iterator绝对不会有pagesize+1次查询那么多。从你的描述看,似乎是一页一页查数据,同时希望得到记录总数。那么可以分两次查询,第一次得到某一页的数据,用Query即可。另一次用:((Integer)session.iterator(querySentence).next()).intValue(),这样做的时候,Hibernate不会一次把所有的记录读取出来,而是会取出所有的主键,然后返回一个int值表示主键的数量,这样可以获得比较高的效率。
0 请登录后投票
   发表时间:2004-12-28  
用iterator没啥意思,加上query cache好了
0 请登录后投票
   发表时间:2004-12-29  
downpour 写道
另一次用:((Integer)session.iterator(querySentence).next()).intValue(),这样做的时候,Hibernate不会一次把所有的记录读取出来,而是会取出所有的主键,然后返回一个int值表示主键的数量,这样可以获得比较高的效率。


我查询返回的是对象,所以session.iterator(queryString).next()返回的也是一个对象,不能转换为Integer,还是不能拿到总记录数。除非我把queryString里包括一个count(*),可这样觉得不好。
0 请登录后投票
   发表时间:2004-12-29  
chinakite 写道
sorry,没太看明白你的意思,但有一点我不是很明白,为什么一定要用iterator,请看robbin的文章http://www.hibernate.org.cn/41.html,不过希望下面的小方法能对你有所帮助。
扩展一下我想应该可以满足大多数的需要,想要屏蔽list提供一个统一的接口可以list.iterator()一下。


我想要的是在不改变sql语句下,在没有很大的集合对象返回的情况下,拿到总的记录数,最好不要在增加查询操作。
0 请登录后投票
   发表时间:2004-12-29  
请你看看hibernate文档再来提问题好吗?你不在querySentence里面包含select count(*)你怎么得到记录总数啊?文档里面不止一次提到你所说的不返回结果集得到记录总数就是用我给你的那个方法。不至于我连文档页码都找给你吧。
0 请登录后投票
   发表时间:2004-12-30  
downpour 写道
不知道楼主是怎么做的,不过用iterator绝对不会有pagesize+1次查询那么多。从你的描述看,似乎是一页一页查数据,同时希望得到记录总数。那么可以分两次查询,第一次得到某一页的数据,用Query即可。另一次用:((Integer)session.iterator(querySentence).next()).intValue(),这样做的时候,Hibernate不会一次把所有的记录读取出来,而是会取出所有的主键,然后返回一个int值表示主键的数量,这样可以获得比较高的效率。

由于我是把查询语句放在map文件中的。
	<query name="findByUser_Checkin">
	<!--
            <method-param>java.lang.String</method-param>
            <method-param>java.lang.String</method-param>
      -->
		<![CDATA[
SELECT u FROM Checkin AS u WHERE u.Userid=:userid AND u.Sid = :sid
]]>
	</query>

其中用到了HQL语句。比如我的调用方法:
	public List findByUnitAndRole(String unitcode,int degree); throws HibernateException {
		Session s = null;
		try {
			s = getSession();;
			Query q = s.getNamedQuery("findByUnitAndRole");;
			q.setString("unitcode", unitcode);;			
			q.setInteger("degree", degree);;
			return q.list();;
		} finally {
			closeSession();;
		}
	}

那当然我可以设置我的配置文件,打印出sql语句。但是这样的话,一是我就在程序中硬写了SQL语句。二是我还设置了参数:unitcode,degree.。那么我要用这个方法::((Integer)session.iterator(querySentence).next()).intValue(),我从那里得到querySentence?谢谢您们的回答!
0 请登录后投票
   发表时间:2004-12-30  
用count()也不错啊只是增加了一次查询!不会有太大影响吧,
0 请登录后投票
   发表时间:2005-01-05  
downpour 写道
请你看看hibernate文档再来提问题好吗?你不在querySentence里面包含select count(*)你怎么得到记录总数啊?文档里面不止一次提到你所说的不返回结果集得到记录总数就是用我给你的那个方法。不至于我连文档页码都找给你吧。

不好意思,好几天没来,其实我的意思是这样的,我要做的是查询结果集合并返回,我不想多写2条sql语句,其中一条单单返回一个count(*),记录总数只是为了分页导航,我想算出一共有多少页。有时候查询语句是很复杂的,很多条件,我不想在里面加一个count(*),因为count(*)是一个分组函数,不能和业务对象一起返回。
另外在sql不用count(*)也可以用jdbc得到总数,例如这样。ResultSet
rs ; rs.last(); int rownum = rs.getRow();
0 请登录后投票
论坛首页 Java企业应用版

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