论坛首页 Java企业应用论坛

后台分页思路

浏览 13162 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (1) :: 隐藏帖 (14)
作者 正文
   发表时间:2011-04-11  
wuhuajun 写道
楼主的意思是全部加在到内存再分页,不然怎么会把内存吃光。。。



不是全部加到内存啊。我用的是mysql,select xxxxx from talbe where whereSql limit ?,?
难道这样会全部加到内存里分页吗?
0 请登录后投票
   发表时间:2011-04-11  
比较理想的分页方式是用几条记录就到数据库查几条
0 请登录后投票
   发表时间:2011-04-11  
huqingwei311 写道
比较理想的分页方式是用几条记录就到数据库查几条

难道我现在的方法不是吗?
0 请登录后投票
   发表时间:2011-04-11  
parwin2 写道
这方法貌似不可取,不能全部结果集全部列出,拿出该页显示的条数即可。否则对于数据比较多的时候速度慢、导致服务器崩溃,多并发的时候那可是严重的问题。

都已经拿出来分好页了,下次直接缓存取不就快了。
我觉得这里的问题不在性能上。问题是万一每页size变了咋办,也不好缓存,每次都去db拉列表,比较杯具。
0 请登录后投票
   发表时间:2011-04-11  
分页这个问题,如果你要自实现,我有段代码可以供你参考,这个是几年前参考Hibernate官方的一篇文章修改的,应该还是可以用的。
public interface Page<T> {

    /**
     * @return 是否是首页(第一页),第一页页码为1
     */
    public boolean isFirst();

    /**
     * @return 是否是最后一页
     */
    public boolean isLast();

    /**
     * @return 是否有下一页
     */
    public boolean hasNext();

    /**
     * @return 是否有上一页
     */
    public boolean hasPrevious();


    /**
     * @return 当前页的数据内容
     */
    public List<T> getThisPageElements();

    /**
     * @return 数据总的条目数量
     */
    public int getTotalNumberOfElements();

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

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

    /**
     * @return 当前页编码
     */
    public int getPageNumber();

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

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

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

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

基于Hibernate的实现:
public class HibernatePage<T> implements Page<T> {

    private List<T> elements;
    private int pageSize;
    private int pageNumber;
    private int totalElements = 0;

    /**
     * 构建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) {
        this.pageNumber = pageNumber;
        this.pageSize = pageSize;
        try {
            ScrollableResults scrollableResults = query.scroll();
            // get the total elements number
            scrollableResults.last();
            this.totalElements = scrollableResults.getRowNumber();
            if (Integer.MAX_VALUE == this.pageNumber || this.pageNumber > getLastPageNumber()) // last page
            {
                this.pageNumber = getLastPageNumber();
            }
            elements = query.setFirstResult(
                    (this.pageNumber - 1) * this.pageSize).setMaxResults(
                    this.pageSize + 1).list();
        } catch (HibernateException e) {
            throw new RuntimeException(e);
        }
    }

    public boolean isFirst() {
        return getPageNumber() == 1;
    }

    public boolean isLast() {
        return getPageNumber() >= getLastPageNumber();
    }

    public boolean hasNext() {
        return getLastPageNumber() > getPageNumber();
    }

    public boolean hasPrevious() {
        return getPageNumber() > 1;
    }

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

    /**
     * 返回List类型数据
     *
     * @return List数据源
     */
    public List<T> getThisPageElements() {
        return elements;
    }

    public int getTotalNumberOfElements() {
        return totalElements;
    }

    public int getFirstElementNumber() {
        return (getPageNumber() - 1) * getPageSize() + 1;
    }

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

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

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

    public int getPageSize() {
        return pageSize;
    }

    public int getPageNumber() {
        return pageNumber;
    }
}

基于JPA的实现:
public class JPAPage<T> implements Page<T> {

    private List<T> elements;
    private Integer pageSize;
    private Integer pageNumber;
    private Integer totalElements = 0;

    /**
     * 构建JPAPage对象,完成JPAPage的Query数据的分页处理
     *
     * @param countQuery
     *            Hibernate的查询总数的Query对象
     * @param pageNumber
     *            当前页编码
     * @param pageSize
     *            每一页显示的条目数
     * @param dataQuery
     *            Hibernate的查询结果的Query对象
     */
    public JPAPage(Query countQuery, int pageNumber, int pageSize,
            Query dataQuery) {
        // 设置
        this.pageSize = pageSize;
        this.pageNumber = pageNumber;
        // 验证
        if (this.pageNumber < 1) {
            this.pageNumber = 1;
        }
        if (Integer.MAX_VALUE == this.pageNumber || this.pageNumber > getLastPageNumber()) // last page
        {
            this.pageNumber = getLastPageNumber();
        }
        // 注入数据
        try {
            Object obj = countQuery.getSingleResult();
            if (obj != null && obj instanceof Long) {
                this.totalElements = ((Long) obj).intValue();
            } else {
                throw new NumberFormatException("[countQuery is error.]");
            }

            elements = dataQuery.setFirstResult(
                    (this.pageNumber - 1) * this.pageSize).setMaxResults(
                    this.pageSize + 1).getResultList();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public boolean isFirst() {
        return getPageNumber() == 1;
    }

    public boolean isLast() {
        return getPageNumber() >= getLastPageNumber();
    }

    public boolean hasNext() {
        return getLastPageNumber() > getPageNumber();
    }

    public boolean hasPrevious() {
        return getPageNumber() > 1;
    }

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

    /**
     * 返回List类型数据
     *
     * @return List数据源
     */
    public List<T> getThisPageElements() {
        return elements;
    }

    public int getTotalNumberOfElements() {
        return totalElements;
    }

    public int getFirstElementNumber() {
        return (getPageNumber() - 1) * getPageSize() + 1;
    }

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

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

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

    public int getPageSize() {
        return pageSize;
    }

    public int getPageNumber() {
        return pageNumber;
    }
}

同样,基于JDBC的实现或者其他什么数据结构查询的实现都很简单。使用Freemarker/Velocity分页宏编写也很容易。

这个分页虽然粗糙,但是一般的应用足够了,不过在排序方面还有待改进。
0 请登录后投票
   发表时间:2011-04-11  
想问一下, select * from table where in(ids),其中IDs为500+,这样的需求有没有好的分页方法
0 请登录后投票
   发表时间:2011-04-11  
一般分页最后都是静态页面,哪有那么多的查询。如果数据是实时变化的,那么后台在一定时间内利用freemarker等模板技术自动静态话,减少查询。
0 请登录后投票
   发表时间:2011-04-11  
看来楼主描述不清楚啊~ 都认为是一次性取出数据了~
0 请登录后投票
   发表时间:2011-04-11  
huangfoxAgain 写道
看来楼主描述不清楚啊~ 都认为是一次性取出数据了~

是啊,大家都没搞清楚,就批判了
0 请登录后投票
   发表时间:2011-04-11  
把数据的标识字段查询出来。然后再内存分页,然后在按照分页再查询具体的数据。
0 请登录后投票
论坛首页 Java企业应用版

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