cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Leszek Gawron <>
Subject Re: GSoC, repeater pagination in place
Date Mon, 31 Jul 2006 11:59:10 GMT
Matthias Epheser wrote:
> As Simone mentioned we are currently working together on the repeater 
> pagination. I want to explain shortly how it works what problems still 
> exist.
This is awesome!

> Pagination can now be achieved by just adding a <fd:pages initial="1" 
> size="20"/> tag to the repeater's definition. I added repeater actions 
> as well for first, previous, next and last page.
What about:
- goto a specific page action
- change page size action

> The actual pageLoad/pageSave takes place in the binding. A storage area 
> is used there to cache updated rows on page change. Once the user 
> submits, the actual saving to the JXPathContext takes place.
> To support really big lists managed by a persistency frameworks (like in 
> the application Simone mentioned) we implemented the possibility to use 
> "lazy collections". A lazy collection is simply an implementation of the 
> java.util.Collection interface that knows how to handle size()- or 
> get(i)- calls without fetching the whole data from the db.

There are two "levels" of lazy collections:

1. OnlyALittleBitLazy(tm) which fetches full collection contents on 
first collection call ( even collection.size() ); This collection is no 
use for paging - does not scale.

2. TotallyLazy(tm) which fetches all entity ids on first collection call 
and then uses separate queries to fetch EACH entity. This one seriously 
faces the famous (n+1) problem (apart from the fact that if you want
to paginate through a table of 100k entries you won't select 100k
entities but still you'll have a collection of 100k ids).

In order to display 100 entries in a particular page 100 more queries 
are needed. Performance goes down a lot.

I would like to propose something else:
public interface ValueListProvider() {
   public List getRows( SomeContextForFilteringAndSorting context, long 
offset, long rowCount );
   public long getTotalRowCount( SomeContextForFilteringAndSorting 
context );

This way you always have only two queries to run:

select * from Entity e where like '%filter%' limit 100 offset 3
select count( * ) from Entity e where like '%filter%'

and you can always wrap your lazy collection with ValueListProvider.

> Another feature we want to implement is sorting, more precisely 
> displaying sorted rows. It's not our intention to actually store the 
> data to the object in a different order but to make it possible for the 
> user to click on the column-header and get the rows displayed in 
> ascendant/descendant order. We think we need some data-providing class 
> that act as a layer between the binding storage and the repeater rows, 
> that provides sort(columnName) and getRows(from,to) or similar. We now 
> have to evaluate how this could be done in a decent way and keep the 
> door open for our lazy list here.
> Concerning this we face some "indexing problems" after a page change. 
> Row additions/deletions and sorting change the order and count of rows, 
> therefore we need a technique to obtain the right start-index when we 
> jump to a custom page. It's not guaranteed that our start-index in the 
> collection is 100 if pageSize=10 and requestedPage=10.

It may be a little bit too hot here because I cannot think of a reason 
why. Why is that?

> These are our thoughts about it:
> The previous and next actions are still able work because we could 
> remember the fist and last index of the current page and start relative 
> to them to fetch the next n rows.
> First and last page could work the same way using 0 and collection.size().

First page is of course 0
Last page could be: java.lang.Math.ceil( collectionSize / pageSize ) - 1 
) * pageSize

> So the problem is located in the goto-widget. We are thinking of a 
> couple possible solutions. Precise positioning would only be possible if 
> we use iteration and check all rows to compute the correct starting 
> point. Another solution would be to use "approximative" starting 
> indexes. That means that, facing large collections, we always take 
> pageSumber*pageSize as the starting index after the custom-page action. 
> This approach solves the (maybe resource intensive) iteration problem 
> but could provide results that are not exact. Another option would be to 
> move this problem to the not yet existing data-providing class I 
> mentioned in the sorting part.

> Do you think it's a real problem to have not exact starting indexes 
> while jumping between pages in big repeaters?

I would rather have a little bit inexact results than something that 
would kill my server if 100 users used it at the same time.

Leszek Gawron                            
IT Manager                                         MobileBox sp. z o.o.
+48 (61) 855 06 67                    
mobile: +48 (501) 720 812                       fax: +48 (61) 853 29 65

View raw message