struts+hibernate分页[转贴]

Hibernate3 提供了DetachedCriteria,使得我们可以在Web层构造detachedCriteria,然后调用业务层Bean,进行动态条件查询,根据这一功能,我设计了通用的抽象Bean基类和分页类支持,代码来自于Quake Wang的javaeye-core包的相应类,然后又做了很多修改。

分页支持类:

java代码: 


package com. javaeye. common. util;

import java. util. List;

public class PaginationSupport {

        public final static int PAGESIZE = 30;

        private int pageSize = PAGESIZE;

        private List items;

        private int totalCount;

        private int [ ] indexes = new int [ 0 ];

        private int startIndex = 0;

        public PaginationSupport ( List items, int totalCount ) {
                setPageSize (PAGESIZE );
                setTotalCount (totalCount );
                setItems (items );               
                setStartIndex ( 0 );
        }

        public PaginationSupport ( List items, int totalCount, int startIndex ) {
                setPageSize (PAGESIZE );
                setTotalCount (totalCount );
                setItems (items );               
                setStartIndex (startIndex );
        }

        public PaginationSupport ( List items, int totalCount, int pageSize, int startIndex ) {
                setPageSize (pageSize );
                setTotalCount (totalCount );
                setItems (items );
                setStartIndex (startIndex );
        }

        public List getItems ( ) {
                return items;
        }

        public void setItems ( List items ) {
                this. items = items;
        }

        public int getPageSize ( ) {
                return pageSize;
        }

        public void setPageSize ( int pageSize ) {
                this. pageSize = pageSize;
        }

        public int getTotalCount ( ) {
                return totalCount;
        }

        public void setTotalCount ( int totalCount ) {
                if (totalCount > 0 ) {
                        this. totalCount = totalCount;
                        int count = totalCount / pageSize;
                        if (totalCount % pageSize > 0 )
                                count++;
                        indexes = new int [count ];
                        for ( int i = 0; i < count; i++ ) {
                                indexes [i ] = pageSize * i;
                        }
                } else {
                        this. totalCount = 0;
                }
        }

        public int [ ] getIndexes ( ) {
                return indexes;
        }

        public void setIndexes ( int [ ] indexes ) {
                this. indexes = indexes;
        }

        public int getStartIndex ( ) {
                return startIndex;
        }

        public void setStartIndex ( int startIndex ) {
                if (totalCount <= 0 )
                        this. startIndex = 0;
                else if (startIndex >= totalCount )
                        this. startIndex = indexes [indexes. length - 1 ];
                else if (startIndex < 0 )
                        this. startIndex = 0;
                else {
                        this. startIndex = indexes [startIndex / pageSize ];
                }
        }

        public int getNextIndex ( ) {
                int nextIndex = getStartIndex ( ) + pageSize;
                if (nextIndex >= totalCount )
                        return getStartIndex ( );
                else
                        return nextIndex;
        }

        public int getPreviousIndex ( ) {
                int previousIndex = getStartIndex ( ) - pageSize;
                if (previousIndex < 0 )
                        return 0;
                else
                        return previousIndex;
        }

}



抽象业务类
java代码: 


/**
* Created on 2005-7-12
*/

package com. javaeye. common. business;

import java. io. Serializable;
import java. util. List;

import org. hibernate. Criteria;
import org. hibernate. HibernateException;
import org. hibernate. Session;
import org. hibernate. criterion. DetachedCriteria;
import org. hibernate. criterion. Projections;
import org. springframework. orm. hibernate3. HibernateCallback;
import org. springframework. orm. hibernate3. support. HibernateDaoSupport;

import com. javaeye. common. util. PaginationSupport;

public abstract class AbstractManager extends HibernateDaoSupport {

        private boolean cacheQueries = false;

        private String queryCacheRegion;

        public void setCacheQueries ( boolean cacheQueries ) {
                this. cacheQueries = cacheQueries;
        }

        public void setQueryCacheRegion ( String queryCacheRegion ) {
                this. queryCacheRegion = queryCacheRegion;
        }

        public void save ( final Object entity ) {
                getHibernateTemplate ( ). save (entity );
        }

        public void persist ( final Object entity ) {
                getHibernateTemplate ( ). save (entity );
        }

        public void update ( final Object entity ) {
                getHibernateTemplate ( ). update (entity );
        }

        public void delete ( final Object entity ) {
                getHibernateTemplate ( ). delete (entity );
        }

        public Object load ( final Class entity, final Serializable id ) {
                return getHibernateTemplate ( ). load (entity, id );
        }

        public Object get ( final Class entity, final Serializable id ) {
                return getHibernateTemplate ( ). get (entity, id );
        }

        public List findAll ( final Class entity ) {
                return getHibernateTemplate ( ). find ( "from " + entity. getName ( ) );
        }

        public List findByNamedQuery ( final String namedQuery ) {
                return getHibernateTemplate ( ). findByNamedQuery (namedQuery );
        }

        public List findByNamedQuery ( final String query, final Object parameter ) {
                return getHibernateTemplate ( ). findByNamedQuery (query, parameter );
        }

        public List findByNamedQuery ( final String query, final Object [ ] parameters ) {
                return getHibernateTemplate ( ). findByNamedQuery (query, parameters );
        }

        public List find ( final String query ) {
                return getHibernateTemplate ( ). find (query );
        }

        public List find ( final String query, final Object parameter ) {
                return getHibernateTemplate ( ). find (query, parameter );
        }

        public PaginationSupport findPageByCriteria ( final DetachedCriteria detachedCriteria ) {
                return findPageByCriteria (detachedCriteria, PaginationSupport. PAGESIZE, 0 );
        }

        public PaginationSupport findPageByCriteria ( final DetachedCriteria detachedCriteria, final int startIndex ) {
                return findPageByCriteria (detachedCriteria, PaginationSupport. PAGESIZE, startIndex );
        }

        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 ( );
                                criteria. setProjection ( null );
                                List items = criteria. setFirstResult (startIndex ). setMaxResults (pageSize ). list ( );
                                PaginationSupport ps = new PaginationSupport (items, totalCount, pageSize, startIndex );
                                return ps;
                        }
                }, true );
        }

        public List findAllByCriteria ( final DetachedCriteria detachedCriteria ) {
                return ( List ) getHibernateTemplate ( ). execute ( new HibernateCallback ( ) {
                        public Object doInHibernate (Session session ) throws HibernateException {
                                Criteria criteria = detachedCriteria. getExecutableCriteria (session );
                                return criteria. list ( );
                        }
                }, true );
        }

        public int getCountByCriteria ( final DetachedCriteria detachedCriteria ) {
                Integer count = ( Integer ) getHibernateTemplate ( ). execute ( new HibernateCallback ( ) {
                        public Object doInHibernate (Session session ) throws HibernateException {
                                Criteria criteria = detachedCriteria. getExecutableCriteria (session );
                                return criteria. setProjection (Projections. rowCount ( ) ). uniqueResult ( );
                        }
                }, true );
                return count. intValue ( );
        }
}




用户在web层构造查询条件detachedCriteria,和可选的startIndex,调用业务bean的相应findByCriteria方法,返回一个PaginationSupport的实例ps。

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






连续看了两篇robbin有关DetachedCriteria的介绍,感觉真的不错,尤其是上面的示例代码,让我着实觉得该对我原来的分页查询做一下代码重构了。

我把原本我的做法也提供出来供大家讨论吧:

首先,为了实现分页查询,我封装了一个Page类:
java代码: 


/*Created on 2005-4-14*/
package org. flyware. util. page;

/**
* @author Joa
*
*/

public class Page {
   
    /** imply if the page has previous page */
    private boolean hasPrePage;
   
    /** imply if the page has next page */
    private boolean hasNextPage;
       
    /** the number of every page */
    private int everyPage;
   
    /** the total page number */
    private int totalPage;
       
    /** the number of current page */
    private int currentPage;
   
    /** the begin index of the records by the current query */
    private int beginIndex;
   
   
    /** The default constructor */
    public Page ( ) {
       
    }
   
    /** construct the page by everyPage
     * @param everyPage
     * */

    public Page ( int everyPage ) {
        this. everyPage = everyPage;
    }
   
    /** The whole constructor */
    public Page ( boolean hasPrePage, boolean hasNextPage, 
                    int everyPage, int totalPage,
                    int currentPage, int beginIndex ) {
        this. hasPrePage = hasPrePage;
        this. hasNextPage = hasNextPage;
        this. everyPage = everyPage;
        this. totalPage = totalPage;
        this. currentPage = currentPage;
        this. beginIndex = beginIndex;
    }

    /**
     * @return
     * Returns the beginIndex.
     */

    public int getBeginIndex ( ) {
        return beginIndex;
    }
   
    /**
     * @param beginIndex
     * The beginIndex to set.
     */

    public void setBeginIndex ( int beginIndex ) {
        this. beginIndex = beginIndex;
    }
   
    /**
     * @return
     * Returns the currentPage.
     */

    public int getCurrentPage ( ) {
        return currentPage;
    }
   
    /**
     * @param currentPage
     * The currentPage to set.
     */

    public void setCurrentPage ( int currentPage ) {
        this. currentPage = currentPage;
    }
   
    /**
     * @return
     * Returns the everyPage.
     */

    public int getEveryPage ( ) {
        return everyPage;
    }
   
    /**
     * @param everyPage
     * The everyPage to set.
     */

    public void setEveryPage ( int everyPage ) {
        this. everyPage = everyPage;
    }
   
    /**
     * @return
     * Returns the hasNextPage.
     */

    public boolean getHasNextPage ( ) {
        return hasNextPage;
    }
   
    /**
     * @param hasNextPage
     * The hasNextPage to set.
     */

    public void setHasNextPage ( boolean hasNextPage ) {
        this. hasNextPage = hasNextPage;
    }
   
    /**
     * @return
     * Returns the hasPrePage.
     */

    public boolean getHasPrePage ( ) {
        return hasPrePage;
    }
   
    /**
     * @param hasPrePage
     * The hasPrePage to set.
     */

    public void setHasPrePage ( boolean hasPrePage ) {
        this. hasPrePage = hasPrePage;
    }
   
    /**
     * @return Returns the totalPage.
     *
     */

    public int getTotalPage ( ) {
        return totalPage;
    }
   
    /**
     * @param totalPage
     * The totalPage to set.
     */

    public void setTotalPage ( int totalPage ) {
        this. totalPage = totalPage;
    }
   
}



上面的这个Page类对象只是一个完整的Page描述,接下来我写了一个PageUtil,负责对Page对象进行构造:
java代码: 


/*Created on 2005-4-14*/
package org. flyware. util. page;

import org. apache. commons. logging. Log;
import org. apache. commons. logging. LogFactory;

/**
* @author Joa
*
*/

public class PageUtil {
   
    private static final Log logger = LogFactory. getLog (PageUtil. class );
   
    /**
     * Use the origin page to create a new page
     * @param page
     * @param totalRecords
     * @return
     */

    public static Page createPage (Page page, int totalRecords ) {
        return createPage (page. getEveryPage ( ), page. getCurrentPage ( ), totalRecords );
    }
   
    /** 
     * the basic page utils not including exception handler
     * @param everyPage
     * @param currentPage
     * @param totalRecords
     * @return page
     */

    public static Page createPage ( int everyPage, int currentPage, int totalRecords ) {
        everyPage = getEveryPage (everyPage );
        currentPage = getCurrentPage (currentPage );
        int beginIndex = getBeginIndex (everyPage, currentPage );
        int totalPage = getTotalPage (everyPage, totalRecords );
        boolean hasNextPage = hasNextPage (currentPage, totalPage );
        boolean hasPrePage = hasPrePage (currentPage );
       
        return new Page (hasPrePage, hasNextPage, 
                                everyPage, totalPage,
                                currentPage, beginIndex );
    }
   
    private static int getEveryPage ( int everyPage ) {
        return everyPage == 0 ? 10 : everyPage;
    }
   
    private static int getCurrentPage ( int currentPage ) {
        return currentPage == 0 ? 1 : currentPage;
    }
   
    private static int getBeginIndex ( int everyPage, int currentPage ) {
        return (currentPage - 1 ) * everyPage;
    }
       
    private static int getTotalPage ( int everyPage, int totalRecords ) {
        int totalPage = 0;
               
        if (totalRecords % everyPage == 0 )
            totalPage = totalRecords / everyPage;
        else
            totalPage = totalRecords / everyPage + 1 ;
               
        return totalPage;
    }
   
    private static boolean hasPrePage ( int currentPage ) {
        return currentPage == 1 ? false : true;
    }
   
    private static boolean hasNextPage ( int currentPage, int totalPage ) {
        return currentPage == totalPage || totalPage == 0 ? false : true;
    }
   

}



上面的这两个对象与具体的业务逻辑无关,可以独立和抽象。

面对一个具体的业务逻辑:分页查询出User,每页10个结果。具体做法如下:
1. 编写一个通用的结果存储类Result,这个类包含一个Page对象的信息,和一个结果集List:
java代码: 


/*Created on 2005-6-13*/
package com. adt. bo;

import java. util. List;

import org. flyware. util. page. Page;

/**
* @author Joa
*/

public class Result {

    private Page page;

    private List content;

    /**
     * The default constructor
     */

    public Result ( ) {
        super ( );
    }

    /**
     * The constructor using fields
     *
     * @param page
     * @param content
     */

    public Result (Page page, List content ) {
        this. page = page;
        this. content = content;
    }

    /**
     * @return Returns the content.
     */

    public List getContent ( ) {
        return content;
    }

    /**
     * @return Returns the page.
     */

    public Page getPage ( ) {
        return page;
    }

    /**
     * @param content
     *            The content to set.
     */

    public void setContent ( List content ) {
        this. content = content;
    }

    /**
     * @param page
     *            The page to set.
     */

    public void setPage (Page page ) {
        this. page = page;
    }
}



2. 编写业务逻辑接口,并实现它(UserManager, UserManagerImpl)
java代码: 


/*Created on 2005-7-15*/
package com. adt. service;

import net. sf. hibernate. HibernateException;

import org. flyware. util. page. Page;

import com. adt. bo. Result;

/**
* @author Joa
*/

public interface UserManager {
   
    public Result listUser (Page page ) throws HibernateException;

}



java代码: 


/*Created on 2005-7-15*/
package com. adt. service. impl;

import java. util. List;

import net. sf. hibernate. HibernateException;

import org. flyware. util. page. Page;
import org. flyware. util. page. PageUtil;

import com. adt. bo. Result;
import com. adt. dao. UserDAO;
import com. adt. exception. ObjectNotFoundException;
import com. adt. service. UserManager;

/**
* @author Joa
*/

public class UserManagerImpl implements UserManager {
   
    private UserDAO userDAO;

    /**
     * @param userDAO The userDAO to set.
     */

    public void setUserDAO (UserDAO userDAO ) {
        this. userDAO = userDAO;
    }
   
    /* (non-Javadoc)
     * @see com.adt.service.UserManager#listUser(org.flyware.util.page.Page)
     */

    public Result listUser (Page page ) throws HibernateException, ObjectNotFoundException {
        int totalRecords = userDAO. getUserCount ( );
        if (totalRecords == 0 )
            throw new ObjectNotFoundException ("userNotExist" );
        page = PageUtil. createPage (page, totalRecords );
        List users = userDAO. getUserByPage (page );
        return new Result (page, users );
    }

}



其中,UserManagerImpl中调用userDAO的方法实现对User的分页查询,接下来编写UserDAO的代码:
3. UserDAO 和 UserDAOImpl:
java代码: 


/*Created on 2005-7-15*/
package com. adt. dao;

import java. util. List;

import org. flyware. util. page. Page;

import net. sf. hibernate. HibernateException;

/**
* @author Joa
*/

public interface UserDAO extends BaseDAO {
   
    public List getUserByName ( String name ) throws HibernateException;
   
    public int getUserCount ( ) throws HibernateException;
   
    public List getUserByPage (Page page ) throws HibernateException;

}



java代码: 


/*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 ( );
    }

}



至此,一个完整的分页程序完成。前台的只需要调用userManager.listUser(page)即可得到一个Page对象和结果集对象的综合体,而传入的参数page对象则可以由前台传入,如果用webwork,甚至可以直接在配置文件中指定。

下面给出一个webwork调用示例:
java代码: 


/*Created on 2005-6-17*/
package com. adt. action. user;

import java. util. List;

import org. apache. commons. logging. Log;
import org. apache. commons. logging. LogFactory;
import org. flyware. util. page. Page;

import com. adt. bo. Result;
import com. adt. service. UserService;
import com. opensymphony. xwork. Action;

/**
* @author Joa
*/

public class ListUser implements Action {

    private static final Log logger = LogFactory. getLog (ListUser. class );

    private UserService userService;

    private Page page;

    private List users;

    /*
     * (non-Javadoc)
     *
     * @see com.opensymphony.xwork.Action#execute()
     */

    public String execute ( ) throws Exception {
        Result result = userService. listUser (page );
        page = result. getPage ( );
        users = result. getContent ( );
        return SUCCESS;
    }

    /**
     * @return Returns the page.
     */

    public Page getPage ( ) {
        return page;
    }

    /**
     * @return Returns the users.
     */

    public List getUsers ( ) {
        return users;
    }

    /**
     * @param page
     *            The page to set.
     */

    public void setPage (Page page ) {
        this. page = page;
    }

    /**
     * @param users
     *            The users to set.
     */

    public void setUsers ( List users ) {
        this. users = users;
    }

    /**
     * @param userService
     *            The userService to set.
     */

    public void setUserService (UserService userService ) {
        this. userService = userService;
    }
}



上面的代码似乎看不出什么地方设置了page的相关初值,事实上,可以通过配置文件来进行配置,例如,我想每页显示10条记录,那么只需要:
java代码: 


<?xml version=" 1. 0"?>
<!DOCTYPE xwork PUBLIC "- //OpenSymphony Group//XWork 1.0//EN" "http://www.opensymphony.com/xwork/xwork-1.0.dtd">

<xwork>
       
        < package name="user" extends="webwork-interceptors">
               
                <!-- The default interceptor stack name -->
        <default-interceptor-ref name="myDefaultWebStack"/>
               
                <action name="listUser" class="com. adt. action. user. ListUser">
                        <param name="page. everyPage"> 10</param>
                        <result name="success">/user/user_list. jsp</result>
                </action>
               
        </ package>

</xwork>




这样就可以通过配置文件和OGNL的共同作用来对page对象设置初值了。并可以通过随意修改配置文件来修改每页需要显示的记录数。

注:上面的<param>的配置,还需要webwork和Spring整合的配合。




我写的一个用于分页的类,用了泛型了,hoho

java代码: 


package com. intokr. util;

import java. util. List;

/**
* 用于分页的类<br>
* 可以用于传递查询的结果也可以用于传送查询的参数<br>
*
* @version 0.01
* @author cheng
*/

public class Paginator<E> {
        private int count = 0; // 总记录数
        private int p = 1; // 页编号
        private int num = 20; // 每页的记录数
        private List<E> results = null; // 结果

        /**
        * 结果总数
        */

        public int getCount ( ) {
                return count;
        }

        public void setCount ( int count ) {
                this. count = count;
        }

        /**
        * 本结果所在的页码,从1开始
        *
        * @return Returns the pageNo.
        */

        public int getP ( ) {
                return p;
        }

        /**
        * if(p<=0) p=1
        *
        * @param p
        */

        public void setP ( int p ) {
                if (p <= 0 )
                        p = 1;
                this. p = p;
        }

        /**
        * 每页记录数量
        */

        public int getNum ( ) {
                return num;
        }

        /**
        * if(num<1) num=1
        */

        public void setNum ( int num ) {
                if (num < 1 )
                        num = 1;
                this. num = num;
        }

        /**
        * 获得总页数
        */

        public int getPageNum ( ) {
                return (count - 1 ) / num + 1;
        }

        /**
        * 获得本页的开始编号,为 (p-1)*num+1
        */

        public int getStart ( ) {
                return (p - 1 ) * num + 1;
        }

        /**
        * @return Returns the results.
        */

        public List<E> getResults ( ) {
                return results;
        }

        public void setResults ( List<E> results ) {
                this. results = results;
        }

        public String toString ( ) {
                StringBuilder buff = new StringBuilder ( );
                buff. append (" {" );
                buff. append ("count:" ). append (count );
                buff. append (",p:" ). append (p );
                buff. append (",nump:" ). append (num );
                buff. append (",results:" ). append (results );
                buff. append (" }" );
                return buff. toString ( );
        }

}

 

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值