The introduction explained already
how to perform a query-by-example just using PriDE base functionality to
read records according to an attribute value combination (in the simplest
case: according to the primary key). This approach is the most needed one.
For the assembly of more complex query expressions, the methods ObjectAdapter.find(String)
and ObjectAdapter.query(String)
can be used. As a difference (like in all other variants of theses two functions)
find() returns only the first matching record while query()
returns all matches. Both functions get a where-clause passed the
syntactic and semantic correctness of which must be ensured by the application.
PriDE does not analyse this expression internally, except a check for null,
which will cause no where clause at all to be attached resulting in a query
for all records of a table. The following example shows a query
for all customers of IDs 1000 up to 2000:
Customer c = new Customer(); ResultIterator iter = c.query("id >= 1000 AND id <= 2000"); Customer[] result = (Customer[])iter.toArray(); |
Building the expressions completely unassisted is of course an error prone
task as this is e.g. well-known from JDO. As an alternative to self-defined
conditions, PriDE provides the class SQLExpression.
This class eases the dynamic assembly of expressions based on the most
important and popular SQL operators (siehe Interface SQLExpression.Operator).
As another advantage, there is a common central formatting of SQL expressions.
The constructor gets passed an SQLFormatter,
which usually is just the current Database object, forwarding
the formatting to its current ResourceAccessor.
The following example illustrates the usage of SQLExpression,
to define the same query as above:
Customer c = new Customer(); SQLExpression exp = new SQLExpression(DatabaseFactory.getDatabase()); exp = exp.and("id", SQLExpression.Operator.GREATEREQUAL, 1000); exp = exp.and("id", SQLExpression.Operator.LESSEQUAL, 2000); ResultIterator iter = c.query(exp.toString()); Customer[] result = (Customer[])iter.toArray(); |
Sometimes a query-by-example is generally desirable but there are some
additional constraints to be considered. For these cases, the function
getConstraint()
allows to use PriDE's dynamic SQL generation as far as possible and to
assemble only the additional constraint. The following example demonstrates
this for a query which causes the matching records to be blocked for update:
Customer c = new Customer(); c.setName("L%"); String constraint = c.constraint(new String[] { "name" }, true); ResultIterator iter = c.query(constraint + " FOR UPDATE"); Customer[] result = (Customer[])iter.toArray(); |
Of course, this approach is limited to results which can be mapped to entities. The more a query varies from this principle, the less support it gains from PriDE. In extreme cases the function Database.sqlQuery(String) must be used to self-define a query completely in all details. In worst case, the function Database.getConnection() can be used to exploit the full flexibility of ordinary JDBC programming. When using this function, it must be kept in mind that the fetched connection must be released by Database.releaseConnection(Connection) after the work is done. The ResourceAccessors ensure that repeated calls of getConnection() and releaseConnection(Connection) are very efficient and perform thread-based connection reuse.
Nevertheless, PriDE's basic query concept allows to run very different
queries even if this is not obvious on first sight. The following example
demonstrates a query for the highest ID of all Customer records,
using a modified RecordDescriptor.
// Commonly usable class for attribute maximum calculation
public class MaxDescriptor extends RecordDescriptor { private String maxfield; // The database field to get the maximum of private Integer max; // The maximum found public Integer getMax() { return max; } public void setMax(Integer max) { this.max = max; } // MaxDescriptor defines itself as the sink for query results. public MaxDescriptor(RecordDescriptor baseDescriptor, String maxfield) throws IllegalDescriptorException { super(MaxDescriptor.class, baseDescriptor.getTableName(), null, new String[][]{ {null, "getMax", "setMax"} }); this.maxfield = maxfield; } // As a difference to an ordinary record descriptor, MaxDescriptor // does not ask the database for '*' (i.e. all fields) but for the // maximum of a particular field protected String getResultFields() { return "max(" + maxfield + ")"; } public static int getMax(String field, String where, RecordDescriptor red) throws SQLException { MaxDescriptor maxdesc = new MaxDescriptor(red, field); DatabaseFactory.getDatabase().query(where, maxdesc, maxdesc, false); return (maxdesc.getMax() == null) ? -1 : maxdesc.getMax().intValue(); } } class Customer extends MappedObject { public int getMaxID() throws SQLException
{ |
The complete source code of the examples above can be found in examples/query.
Home | Introduction | Javadoc |