-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Pagination best practices
PostPosted: Tue Jun 28, 2005 1:17 am 
Regular
Regular

Joined: Fri Oct 01, 2004 2:19 am
Posts: 111
Location: Melbourne, Australia
Hibernate version: 3.0.4

What is the currently accepted best practice when it comes to pagination?

My setup includes Hibernate on a remove server handling requests for
retrieving datasets, which are larger than is practical to return to clients.
Clients therefore are specifying whatever query criteria they need and
request the resulting data set to be of a particular size ( a page) and
starting at a particular page number. This is all covered in the docs.

However, the clients are required to show the total size of the data set
matching the criteria. How can I do this without running the original
query again, using a count(*) projection? Is there an interface I can use
to achieve this? I saw the Projections.rowCount() projection but as best
as I can ascertain, this would still require me to run the query again.

_________________
Cheers,

Bonny

please don't forget to rate :)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 28, 2005 11:40 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
So .... how would you do it in SQL?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 28, 2005 4:28 pm 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
I am not sure it is a good idea to generate dynamic queries this way, but it must work with "native SQL":

"SELECT COUNT(*) FROM ( SELECT ... )" or "WITH SELECT ... " a.k.a "inline view"


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 28, 2005 9:25 pm 
Regular
Regular

Joined: Fri Oct 01, 2004 2:19 am
Posts: 111
Location: Melbourne, Australia
Gavin,

gavin wrote:
So .... how would you do it in SQL?



I'm not suggesting the approach described (using the rowCount projection)
is not the right way to do this. I just wanted to understand the implication
and make sure I use the correct tools.

Also, this applies to Criteria queries, but how can one achieve this
using a predefined query stored as part of the Hibernate mapping docs?
Should I create a dynamic query as baliukas suggests above?

_________________
Cheers,

Bonny

please don't forget to rate :)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2005 12:30 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
There is no way to tune dynamic queries constructed from user query criteria (this stuff can be very slow to execute) and it is not secure (SQL injection), not all of databases support inline views too. I use lucene for this stuff and it works great if stale data is tolerated.
It is out of topic, but it must be usefull to think about related problems before to use dynamic queries.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 30, 2005 1:47 am 
Regular
Regular

Joined: Fri Oct 01, 2004 2:19 am
Posts: 111
Location: Melbourne, Australia
baliukas wrote:
There is no way to tune dynamic queries constructed from user query criteria (this stuff can be very slow to execute) and it is not secure (SQL injection), not all of databases support inline views too. I use lucene for this stuff and it works great if stale data is tolerated.
It is out of topic, but it must be usefull to think about related problems before to use dynamic queries.


I was a bit unclear as to how to achieve this. What I meant was that
instead of having two queries in the mapping document like so:
Code:
<query name="..."> <![CDATA[ select attr  from someType where
   cond1 = :param1 and cond2=:param2 ]]></query>

<query name="..."> <![CDATA[ select count(*) from ( select attr  from
someType where   cond1 = :param1 and cond2=:param2) ]]>


I would have only the original query and then create a secondary query
like so:
Code:
Query q = sess.getNamedQuery(...);
Query countQ = sess.createQuery( "select count(*) from (" + q.getQueryString() + ")");


Or are you suggesting that even this usage is expensive? Otherwise I will
have to ensure that I have two versions of each query I am specifying
ahead of time and ensure that they are both in sync. This is error prone
and could create hard to find errors.

_________________
Cheers,

Bonny

please don't forget to rate :)


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 30, 2005 1:42 pm 
Beginner
Beginner

Joined: Thu Mar 31, 2005 5:59 pm
Posts: 34
Actually I think this is very similar to the problem I'm having right now.

I'll describe what I'm doing and maybe I'm just being stupid here, but ya'll can tell me anyways.

So, currently, I'm constructing a query and I only want 100 rows back.

I construct my query (FROM foo.bar as bar where bar.valueone = "somevalue" ...) as a String and then issue the following commands:

Code:
//create a query, set max results, and get the associated results
Query q = session.createQuery(query);
q.setMaxResults(maxObjects);           
returnVal = q.list();


Now what I additionally have to provide to the user is a number representing the total number of objects that match the query (as in, if I hadn't set maxResults, what would I get back?).

To improve network transfer, it would be nice if I could just get the count back (possibly I would be retrieving a million items across the network instead of just 100).

Should I just give up and retrieve everything and crop afterwards?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 30, 2005 3:02 pm 
Beginner
Beginner

Joined: Thu Mar 31, 2005 5:59 pm
Posts: 34
Nevermind, I figured it out. I had to close the session and open a new one (for some reason if I didn't do that, it tried to update the table like I had changed the values, even though I hadn't changed the values?).

Here's my code in case anyone else is a dunce like me:

Code:
Query r = session.createQuery("select count(*) "  + query);
System.out.println(r.uniqueResult());


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 01, 2005 1:43 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
Code:
Query q = sess.getNamedQuery(...);
Query countQ = sess.createQuery( "select count(*) from (" + q.getQueryString() + ")");

There is nothing wrong in this query, I just misunderstand use case.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 04, 2005 12:40 am 
Beginner
Beginner

Joined: Tue Jun 21, 2005 8:38 am
Posts: 37
It would be so much nicer if the query string can be similarily retrieved from a Criteria object, so that one can:
Code:
Query countQ = sess.createQuery( "select count(*) from (" + criteria.getQueryString() + ")");


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 05, 2005 11:57 pm 
Beginner
Beginner

Joined: Wed May 25, 2005 7:49 pm
Posts: 25
hanson.char wrote:
It would be so much nicer if the query string can be similarily retrieved from a Criteria object, so that one can:
Code:
Query countQ = sess.createQuery( "select count(*) from (" + criteria.getQueryString() + ")");


If you are using Criteria queries, you can just use a Projection, as in
Code:
criteria.setProjection(Projections.count("field"));


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 06, 2005 3:07 am 
Beginner
Beginner

Joined: Tue Jun 21, 2005 8:38 am
Posts: 37
lfbaker wrote:
If you are using Criteria queries, you can just use a Projection, as in
Code:
criteria.setProjection(Projections.count("field"));


Cool! Or simply,
Code:
criteria.setProjection(Projections.rowCount());

Very nice :)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 06, 2005 4:21 am 
Beginner
Beginner

Joined: Tue Jun 21, 2005 8:38 am
Posts: 37
hanson.char wrote:
lfbaker wrote:
If you are using Criteria queries, you can just use a Projection, as in
Code:
criteria.setProjection(Projections.count("field"));


Cool! Or simply,
Code:
criteria.setProjection(Projections.rowCount());

Very nice :)


Sadly it seems the Criteria object failed on complicated object reference. For example, the following HQL works if I use Query constructed from:

Code:
FROM Transaction t WHERE t.instruction.customerProductAgreement.compositeKey.customerId = :p0

Note the alias somehow must be specified in this case to make it work. (The alias is not necessary if it is a simple property reference.) However, it doesn't work

1) if the alias is taken out (using Query); or
2) if I use Criteria object, regardless of whether I specify an alias or not when I create the Critiera from the session.

It always failed with an error saying it cannot resolve the property "instruction.customerProductAgreement.compositeKey.customerId". I am using Hibernate 3.0.5.

Is this a known bug, or am I mistaken ?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 06, 2005 10:33 am 
Beginner
Beginner

Joined: Wed May 25, 2005 7:49 pm
Posts: 25
hanson.char wrote:
It always failed with an error saying it cannot resolve the property "instruction.customerProductAgreement.compositeKey.customerId". I am using Hibernate 3.0.5.

Is this a known bug, or am I mistaken ?

I think if it is a property, that syntax will work. If it is an association to another mapped class, you need to use criteria chaining, as in
Code:
criteria.createCriteria("instruction").createCriteria("customerProductAgreement");

Try that and see if it works.

-Lee


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 07, 2005 12:38 am 
Beginner
Beginner

Joined: Tue Jun 21, 2005 8:38 am
Posts: 37
lfbaker wrote:
hanson.char wrote:
It always failed with an error saying it cannot resolve the property "instruction.customerProductAgreement.compositeKey.customerId". I am using Hibernate 3.0.5.

Is this a known bug, or am I mistaken ?

I think if it is a property, that syntax will work. If it is an association to another mapped class, you need to use criteria chaining, as in
Code:
criteria.createCriteria("instruction").createCriteria("customerProductAgreement");

Try that and see if it works.

-Lee


Not consistent with the hql fragment used in Query, but the criteria chaining does work. Thanks!


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 16 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.