In Brief
Advanced Reading - Query Objects for Improved Queries
The read methods in a GLORP session are convenience methods for construction query objects1. For example the following:
employees := session readManyOf: GlorpEmployee where: [:each | each id <= 4].
is a convenience for:
query := Query readManyOf: GlorpEmployee where: [:each | each id <= 4].
employees := session execute: query.
While the convenience methods are shorter and adequate for most situations, dealing with query objects directly give you much more flexibility. The following is not currently possible with convenience methods. The queries results are ordered by name and when names are equal the results are then sorted by id. The ordering is done by the database.
query := Query readManyOf: GlorpEmployee where: [:each | each id <= 4].
query orderBy: #name.
query orderBy: #id.
employees := session execute: query.
OrderBy: also accepts blocks to indicate the order so we could use query orderBy: [:each | each name] instead of query orderBy: #name.
Query object allow us to read objects in groups. With a session we can read the first N objects that satisfy a query. The following will read the first 50 GLORP employees with a salary over 100,000. (We are assuming the salary is an instance variable of GlorpEmployee.) However there is no way using convenience methods to read the rest of the employees that satisfy the condition.
employees := session readManyOf: GlorpEmployee where: [:each |
each salary > 100000] limit: 50.
The following will read up to 100 employee objects after the first 50 and order them by name.
query := Query readManyOf: GlorpEmployee where: [:each |
each salary > 100000].
query
orderBy: #name;
limit: 100;
offset: 50.
employees := session execute: query.
When readManyOf: query returns an array of results. You can specify a different collection with the method collectionType:. The following will return a set of employee objects.
query := Query readManyOf: GlorpEmployee where: [:each | each salary > 100000].
query collectionType: Set.
employees := session execute: query.
See the class SimpleQuery for more methods one can use to refine queries. The class CompoundQuery is useful in joining multiple query objects with Boolean expressions.
Reading Parts of Objects
There are times when you only need part of an object. The following returns just the salaries (assuming salary is an instance variable of GlorpEmployee).
query := Query readManyOf: GlorpEmployee where: [:each | each salary > 100000].
query retrieve: #salary.
salaries := session execute: query.
One can retrieve more than one item. In this case for each GlorpEmployee one gets an array containing a salary and a name.
query := Query readManyOf: GlorpEmployee where: [:each | each salary > 100000].
query
retrieve: #salary;
retrieve: #name.
salariesAndNames := session execute: query.
One can also retrieve a maximum or minimum value.
query := Query readManyOf: GlorpEmployee where: [:each | each salary > 100000].
query retrieveMax: #salary.
maxSalaryInArray := session execute: query.
When we know there will be only one value returned we can specify not to wrap the one value in a collection.
query := Query readManyOf: GlorpEmployee where: [:each | each salary > 100000].
query
retrieveMax: #salary;
readsOneObject: true.
maxSalary := session execute: query.
When using retrieve: the part of the object is selected using SQL in the database, so in general will be more efficient than reading the entire object and selecting the value from the object.
Dynamic Descriptors
The examples in this tutorial treat the GlorpTutorialDescriptor class as static entity. However many of the values set in the GlorpTutorialDescriptor can be changed at runtime. A number of the GLORP test cases illustrate this.

1 See Query Object pattern pp 316-321 in Fowler [2003]

Last modified date: 01/29/2015