Apache MetaModel offers three different ways of defining a query for a DataContext to retrieve data. Each approach offers a set of features, making them appropriate for different situations.
1 - The Query
object
At the core of all query execution in MetaModel is the Query
object. Query
is a regular Java class containing the structural elements that make up a query. The main elements of a query is a set of clauses (SelectClause
, FromClause
and so on) which in turn each contain a set of items (SelectItem
, FromItem
etc.).
The object structure is depicted in the below class diagram. Each item will typically refer to some structure in the DataContext
's schema (a Table
, a Column
or such), or even an embedded sub-query. A query must have at least 1 SelectItem
and 1 FromItem
for it to be executable.
As such, you can instantiate Query
and populate the object yourself:
DataContext dc = ... Table table = dc.getDefaultSchema().getTableByName("person"); Column col1 = table.getColumnByName("id"); Column col2 = table.getColumnByName("name"); // Construct a query like "SELECT id, name FROM person" Query q = new Query(); q.from(table); q.select(col1, col2); // Execute the Query DataSet ds = dc.executeQuery(q);
Pros:
- Building your query this way gives you a lot of control. It allows you to effectively separate the static and dynamic parts of a query and grow awareness of any assumptions/hardcoded values etc.
- One of the main advantages of having the query as an object is that the building of the query lends itself to advanced construction logic, potentially spanning multiple components to aid in the building of a particular query. Therefore, using the Query object type is the most powerful of the three approaches to querying in MetaModel.
- Having the query available as an object also allows you to unittest / assert the structure of the queries you are creating.
Cons:
- Creating the query this way is a bit verbose, and as we shall see below, it can be made simpler in most cases.
2 - The query builder API
TODO
3 - Query parsing
Finally, Apache MetaModel allows you to simply parse a query from a string form. You can use this feature in a two-step parse-then-execute mode or in a single step to parse-and-execute.
DataContext.executeQuery(String): DataSet
DataContext.parseQuery(String): Query
The parseQuery method allows you to interrogate or even manipulate the parsed query, potentially leveraging the control and power of the Query
object approach in combination with parsing.
Note that unlike the query builder API, the sequence of query clauses in a string query is like that of SQL (select before from):
SELECT ... FROM ... [ WHERE ...] [ GROUP BY ...] [ HAVING ...] [ ORDER BY ...]
Pros:
- This approach is often the most readable way of defining a query.
- This approach allows for easy externalization of queries as strings, or of having the users type their own queries.
Cons:
- Using string literals for queries is un-safe and may introduce bugs in your code due to the non-typed and non-checked nature of the query.
- The fact that string SQL-like queries are supported may be misleading some users to think that the query is passed un-interpreted to the backing datastore. This is NOT the case.