JDOQL: What is the equivalent of SQL's count(*) in the JDO world?

Displaying large datasets

There are often times when you need to display data in a table format and the size of the potential dataset is extremely large and so ends up being represented across many pages and displayed with the usual "previous/next" buttons.

Most UI frameworks need to know upfront what is the total count of items you will be displaying so they know how many pages there are and can display some text above the table that says something like:

Items 31-40 of 397

Avoiding a big database, memory and CPU hit

What you don't want to do is force your JDO ORM (or an ORM using any Java persistence standard e.g. JPA) from instantiating ALL of the objects just so that your UI knows the total count of items to be displayed.

To do this you need to perform some kind of 'count' query. In JDO this is done by setting the result set to 'count' but count needs a parameter.

e.g.

PersistenceManager pm = getPm();

Query q = pm.newQuery(MyClass.class);

        // Set up any filtering here ...
        q.setFilter("value > 300");


q.setResult("count(batch)");

where batch is an attribute of MyClass, the extent of which, you are querying. Now that's all well and good but what if you don't want to perform the 'count' on any specific field.

I just want a total record/object count

In raw SQL you would do something like:

        select count(*) from mytable;

but that '*' is an SQL concept only. However, there is an equivalent in JDOQL and given it is OO based you can guess what the equivalent is in JDOQL - 'this'.

So the following will make sure you get the exact count that you are looking for:

q.setResult("count(this)");

If you were to perform a Collection retrieval with the exact same filter then the above count will always match the number of objects in the returned Collection. However, if you use count(attributeName) this may not always be the case based on uniqueness of the attribute's value etc.,

Conclusion


Until we came across the count(this) construct we were having issues with our counts returning more objects than a query with the exact same filter that returned a collection of the objects. I hope this helps anyone else out there who has this issue.

Extra performance hint

Some JDBC drivers which will always retrieve all records to perform a 'count' operation even if you have specified only a count(this) dataset in JDOQL above.

That is not desirable on large datasets!
 
To overcome this issue with we can, if using the DataNucleus JDO implementation, use its extension that tells it to inform the driver NOT to pull all records to perform a count: 

q.addExtension("datanucleus.query.resultSizeMethod", "count");


Enjoy!

Comments

Popular posts from this blog

Java package name structure and organization - best practice and conventions

Classic software engineering mistakes: To Greenfield or Refactor Legacy code?

How to reset MySQL 8 root password on CentOS 7 and 8