Announcement Announcement Module
Collapse
No announcement yet.
How do I implement pagination in Hibernate efficiently? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How do I implement pagination in Hibernate efficiently?

    Hi,
    What is the best way to implement pagination of query results using Hibernate?

    I tried using the proxy parameter in the hibernate xml class definition files but proxies only work with load and invoke queries and getHibernateTemplate does not implement the invoke commands (only find), so what do I do? Can I use the same session as getHibernateTemplate and call the invoke command directly?



    Thanks in advance.

  • #2
    Most examples I've seen use Hibernate's Query or Criteria APIs for pagination.

    Comment


    • #3
      Check the hibernate forum. Pagination is a hot topic over there. Another idea is to get the book: 'Hibernate in Action'. Great book!

      Comment


      • #4
        I found this blog entry very informative. With some coding (take a look at HibernateTemplate), I am sure you could very easily implement Spring / Hibernate pagination helper methods

        Comment


        • #5
          Using criteria the code looks like this:

          Criteria criteria=session.createCriteria(Item.class);
          criteria.addOrder(Order.asc("name"));
          criteria.setFirstResult(100);
          criteria.setMaxResults(50);
          List pageResults=criteria.list();

          Basically you just need to establish an order of the query results. (remember to ensure a distinct result set) and set the index of the first result and the number of maximum results. In the above sample you will receive the third page (each consisting of 50 items) sorted by names.

          Use the HibernateCallback interface for instance and use the HibnerateTemplate.execute(callback) method.

          Comment


          • #6
            Originally posted by irbouho
            I found this blog entry very informative.
            Perhaps a couple methods for pagination should be added to HibernateTemplate along with a Page helper class (as per the blog entry). It could probably be reworked to return Lists instead of the Page object, but I do like the additional functionality you could provide from such a Page. The addition to the api would be somthing along the lines of:

            Code:
            Page getPage(Query query, int pageSize, int pageNum) //this could also return a List
            List getAllPages(Query query, int pageSize) //returns a List of all the pages
            Thoughts?
            Ryan

            Comment


            • #7
              Hi,
              I found the Criteria class along with the HibernateCallback and Page wrapper (from blog entry) adequate for my needs.
              Thanks for the help!

              Should the Page wrapper class have a function
              int getNumPages(Query query, int pageSize)?

              Comment


              • #8
                Correct me if I'm wrong, but if you have the following code, wouldn't you lose the transactionality applied via Interceptor since the query is actually executed outside of the target class?

                Code:
                Page findStuffAsPage(int pageSize, int pageNum){
                   return new Page(getHibernateTemplate().createQuery(getSession(), "from Cat c"), pageSize, pageNum);
                }
                Page Class from http://blog.hibernate.org/cgi-bin/bl.../14#pagination
                Code:
                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;
                   }
                
                }


                R

                Comment


                • #9
                  Correct me if I'm wrong, but if you have the following code, wouldn't you lose the transactionality applied via Interceptor since the query is actually executed outside of the target class?
                  Depends on. As long as the transaction is spanning over the whole findStuffAsPage method, everything will be fine.
                  For example:

                  findStuffAsPage is advised and a declarative transaction is attached, the following fluff is likely to happen:

                  <Transaction.begin>
                  call createQuery
                  create new Page
                  return page
                  <Transaction.end>

                  The question remains, when the query is executed. As long as the query is executed during the creation of the Page object (!Bad style!), it will work fine. So I would prefer a factory method on that anyway.

                  But I do not get what the really enhancement is the Page class will provide. You know setting first result and result count isn't a big deal anyway. Maybe adding an over all count + incooperate a table support would do it. But I don't know.... .

                  Comment


                  • #10
                    Just a small addition
                    Page class implementation looks quiet simple, it should work fine as long as the whole call to findStuffAsPage is spanned in a Transaction. But you still need to pay attention to lazy intialization.

                    Comment


                    • #11
                      I think that ScrollableResults is better for paging .
                      ScrollableResults in hibernate 2.1.6 is good

                      regards

                      Comment


                      • #12
                        I think that ScrollableResults is better for paging .
                        ScrollableResults in hibernate 2.1.6 is good
                        Scrollable results may have some drawbacks since the connection has to remain open. There is no single fetch of database datas. It's more like have an opened connection. So the scrolling and stuff has to happen inside a transaction anyways.

                        If you know the page to show, I wouldn't go for scrollable results then. But maybe I am missing an important information here.

                        Comment


                        • #13
                          I think that ScrollableResults is better for paging .
                          There are a couple reasons I use paging. The first is to make it easier for the user to view a large set of data. Ideally, this wouldn't happen often (you'd be able to limit what the user needs to see more effectively), but in practice much harder to accomplish. In this case, ScrollableResults would work, pending the open connection issue Martin raised. The second reason is when you want to limit the amount of data being retrieved and transfered of the network. In my case, I have an application where the user's will be accessing it via low bandwidth connections and it is preferrable for only records x through y be retrieved. Unless I'm mistaken, in the second case, I'm not going to be able to accomplish that with a ScrollableResult

                          But I do not get what the really enhancement is the Page class will provide. You know setting first result and result count isn't a big deal anyway. Maybe adding an over all count + incooperate a table support would do it. But I don't know.... .
                          Sure it's easy to implement, but why rewrite the code over and over if you're going to be doing paging often? Other benefits I see is reusing the logic to determine the current page's location (pages ahead/behind) and a bit better readability when dealing with all the pages of a query (list of pages instead of list of lists).

                          R

                          Comment


                          • #14
                            You can use ScrollableResults with or without open connection - if connection is closed You simple reopen again, like this :

                            String queryString = ...;
                            int rowStart = 0;
                            int maxRows = 100;
                            databaseList = new ArrayList(); // cannot make new list always,, example
                            Session session = null;
                            try {
                            session = SessionFactoryUtils.getSession(dao.getSessionFacto ry(),
                            true);
                            Query q = session.createQuery(queryString);
                            ScrollableResults scr = q.scroll();
                            scr.first();
                            scr.scroll(rowStart);
                            int i = 0;
                            while (maxRows > i++) {
                            databaseList.add(scr.get(0));
                            if (!scr.next())
                            break;
                            }
                            } catch (DataAccessResourceFailureException e) {
                            logMessage(e);
                            } catch (HibernateException e) {
                            logMessage(e);
                            } catch (IllegalStateException e) {
                            logMessage(e);
                            } finally {
                            SessionFactoryUtils.closeSessionIfNecessary(sessio n, dao
                            .getSessionFactory());
                            }
                            return databaseList;

                            ScrollableResult is simple result - do same thing, only return rows which you want

                            regards

                            Comment


                            • #15
                              ... continuing

                              Hi all!!
                              almost 2 years old thread, but it is exacly what i am need to impliment now ...

                              Is there something new in Spring/Hibernate that can help? :o thks!!

                              Comment

                              Working...
                              X