Repository: cayenne
Updated Branches:
  refs/heads/master 4517505ba -> cc025e40a


Update documentation
 - remove references to Apache Velocity
 - add some styling


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/cc025e40
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/cc025e40
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/cc025e40

Branch: refs/heads/master
Commit: cc025e40a8ea81cd290b7dcc4a669d49b8e27640
Parents: 4517505
Author: Nikita Timofeev <stari...@gmail.com>
Authored: Tue Jan 30 16:33:21 2018 +0300
Committer: Nikita Timofeev <stari...@gmail.com>
Committed: Tue Jan 30 16:33:21 2018 +0300

----------------------------------------------------------------------
 .../asciidoc/_cayenne-guide/part2/queries.adoc  | 274 ++++++++++++++-----
 1 file changed, 212 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/cc025e40/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/queries.adoc
----------------------------------------------------------------------
diff --git 
a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/queries.adoc
 
b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/queries.adoc
index 7a63595..0351940 100644
--- 
a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/queries.adoc
+++ 
b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/queries.adoc
@@ -14,28 +14,45 @@
 
 === Queries
 
-Queries are Java objects used by the application to communicate with the 
database. Cayenne knows how to translate queries into SQL statements 
appropriate for a particular database engine. Most often queries are used to 
find objects matching certain criteria, but there are other types of queries 
too. E.g. those allowing to run native SQL, call DB stored procedures, etc. 
When committing objects, Cayenne itself creates special queries to 
insert/update/delete rows in the database.
-
-There is a number of built-in queries in Cayenne, described later in this 
chapter. Most of the newer queries use fluent API and can be created and 
executed as easy-to-read one-liners. Users can define their own query types to 
abstract certain DB interactions that for whatever reason can not be adequately 
described by the built-in set.
-
-Queries can be roughly categorized as "object" and "native". Object queries 
(most notably ObjectSelect, SelectById, and EJBQLQuery) are built with 
abstractions originating in the object model (the "object" side in the 
"object-relational" divide). E.g. ObjectSelect is assembled from a Java class 
of the objects to fetch, a qualifier expression, orderings, etc. - all of this 
expressed in terms of the object model.
-
-Native queries describe a desired DB operation as SQL code (SQLSelect, 
SQLTemplate query) or a reference to a stored procedure (ProcedureQuery), etc. 
The results of native queries are usually presented as Lists of Maps, with each 
map representing a row in the DB (a term "data row" is often used to describe 
such a map). They can potentially be converted to objects, however it may take 
a considerable effort to do so. Native queries are also less (if at all) 
portable across databases than object queries.
+Queries are Java objects used by the application to communicate with the 
database.
+Cayenne knows how to translate queries into SQL statements appropriate for a 
particular database engine.
+Most often queries are used to find objects matching certain criteria, but 
there are other types of queries too.
+E.g. those allowing to run native SQL, call DB stored procedures, etc. When 
committing objects,
+Cayenne itself creates special queries to insert/update/delete rows in the 
database.
+
+There is a number of built-in queries in Cayenne, described later in this 
chapter.
+Most of the newer queries use fluent API and can be created and executed as 
easy-to-read one-liners.
+Users can define their own query types to abstract certain DB interactions
+that for whatever reason can not be adequately described by the built-in set.
+
+Queries can be roughly categorized as "object" and "native".
+Object queries (most notably `ObjectSelect`, `SelectById`, and `EJBQLQuery`)
+are built with abstractions originating in the object model (the "object" side 
in the "object-relational" divide).
+E.g. ObjectSelect is assembled from a Java class of the objects to fetch,
+a qualifier expression, orderings, etc. - all of this expressed in terms of 
the object model.
+
+Native queries describe a desired DB operation as SQL code (`SQLSelect`, 
`SQLTemplate` query)
+or a reference to a stored procedure (`ProcedureQuery`), etc.
+The results of native queries are usually presented as Lists of Maps,
+with each map representing a row in the DB (a term "data row" is often used to 
describe such a map).
+They can potentially be converted to objects, however it may take a 
considerable effort to do so.
+Native queries are also less (if at all) portable across databases than object 
queries.
 [[select]]
 ==== ObjectSelect
 
 ===== Selecting objects
 
-ObjectSelect supersedes older SelectQuery. SelectQuery is still available and 
supported.
+`ObjectSelect` supersedes older `SelectQuery`. `SelectQuery` is still 
available and supported.
 
-ObjectSelect is the most commonly used query in Cayenne applications. This may 
be the only query you will ever need. It returns a list of persistent objects 
(or data rows) of a certain type specified in the query:
+`ObjectSelect` is the most commonly used query in Cayenne applications. This 
may be the only query you will ever need.
+It returns a list of persistent objects (or data rows) of a certain type 
specified in the query:
 
 [source, java]
 ----
 List<Artist> objects = ObjectSelect.query(Artist.class).select(context);
 ----
 
-This returned all rows in the "ARTIST" table. If the logs were turned on, you 
might see the following SQL printed:
+This returned all rows in the _ARTIST_ table. If the logs were turned on, you 
might see the following SQL printed:
 
 [source]
 ----
@@ -43,7 +60,11 @@ INFO: SELECT t0.DATE_OF_BIRTH, t0.NAME, t0.ID FROM ARTIST t0
 INFO: === returned 5 row. - took 5 ms.
 ----
 
-This SQL was generated by Cayenne from the ObjectSelect above. ObjectSelect 
can have a qualifier to select only the data matching specific criteria. 
Qualifier is simply an Expression (Expressions where discussed in the previous 
chapter), appended to the query using "where" method. If you only want artists 
whose name begins with 'Pablo', you might use the following qualifier 
expression:
+This SQL was generated by Cayenne from the `ObjectSelect` above.
+`ObjectSelect` can have a qualifier to select only the data matching specific 
criteria.
+Qualifier is simply an Expression (Expressions where discussed in the previous 
chapter),
+appended to the query using "where" method. If you only want artists whose 
name begins with 'Pablo',
+you might use the following qualifier expression:
 
 [source, java]
 ----
@@ -61,7 +82,7 @@ INFO: SELECT t0.DATE_OF_BIRTH, t0.NAME, t0.ID FROM ARTIST t0 
WHERE t0.NAME LIKE
 INFO: === returned 1 row. - took 6 ms.
 ----
 
-ObjectSelect allows to assemble qualifier from parts, using "and" and "or" 
method to chain then together:
+`ObjectSelect` allows to assemble qualifier from parts, using "and" and "or" 
method to chain then together:
 
 [source, java]
 ----
@@ -71,7 +92,7 @@ List<Artist> objects = ObjectSelect.query(Artist.class)
     .select(context);
 ----
 
-To order the results of ObjectSelect, one or more orderings can be applied:
+To order the results of `ObjectSelect`, one or more orderings can be applied:
 
 [source, java]
 ----
@@ -81,7 +102,10 @@ List<Artist> objects = ObjectSelect.query(Artist.class)
     .select(context);
 ----
 
-There's a number of other useful methods in ObjectSelect that define what to 
select and how to optimize database interaction (prefetching, caching, fetch 
offset and limit, pagination, etc.). Some of them are discussed in separate 
chapters on caching and performance optimization. Others are fairly 
self-explanatory. Please check the API docs for the full extent of the 
ObjectSelect features.
+There's a number of other useful methods in `ObjectSelect` that define what to 
select
+and how to optimize database interaction (prefetching, caching, fetch offset 
and limit, pagination, etc.).
+Some of them are discussed in separate chapters on caching and performance 
optimization.
+Others are fairly self-explanatory. Please check the API docs for the full 
extent of the `ObjectSelect` features.
 
 ===== Selecting individual columns
 
@@ -104,7 +128,8 @@ List<Object[]> nameAndDate = ObjectSelect
 
 ===== Selecting using aggregate functions
 
-ObjectSelect query supports usage of aggregate functions. Most common variant 
of aggregation is selecting count of records, this can be done really easy:
+ObjectSelect query supports usage of aggregate functions.
+Most common variant of aggregation is selecting count of records, this can be 
done really easy:
 
 [source, java]
 ----
@@ -146,7 +171,9 @@ ORDER BY COUNT(t1.PAINTING_ID) DESC, t0.ARTIST_NAME
 [[ejbql]]
 ==== EJBQLQuery
 
-EJBQLQuery was created as a part of an experiment in adopting some of Java 
Persistence API (JPA) approaches in Cayenne. It is a parameterized object query 
that is created from query String. A String used to build EJBQLQuery must 
conform to JPQL (JPA query language):
+EJBQLQuery was created as a part of an experiment in adopting some of Java 
Persistence API (JPA) approaches in Cayenne.
+It is a parameterized object query that is created from query String.
+A String used to build `EJBQLQuery` must conform to JPQL (JPA query language):
 
 
 [source, java]
@@ -154,11 +181,14 @@ EJBQLQuery was created as a part of an experiment in 
adopting some of Java Persi
 EJBQLQuery query = new EJBQLQuery("select a FROM Artist a");
 ----
 
-JPQL details can be found in any JPA manual. Here we'll mention only how this 
fits into Cayenne and what are the differences between EJBQL and other Cayenne 
queries.
+JPQL details can be found in any JPA manual. Here we'll mention only how this 
fits into Cayenne
+and what are the differences between EJBQL and other Cayenne queries.
 
-Although most frequently EJBQLQuery is used as an alternative to SelectQuery, 
there are also DELETE and UPDATE varieties available.
+Although most frequently `EJBQLQuery` is used as an alternative to 
`SelectQuery`,
+there are also DELETE and UPDATE varieties available.
 
-NOTE: As of this version of Cayenne, DELETE and UPDATE do not change the state 
of objects in the ObjectContext. They are run directly against the database 
instead.
+NOTE: As of this version of Cayenne, DELETE and UPDATE do not change the state 
of objects in the `ObjectContext`.
+They are run directly against the database instead.
 
 
 [source, java]
@@ -180,7 +210,11 @@ context.performGenericQuery(update);
 ----
 
 
-In most cases SelectQuery is preferred to EJBQLQuery, as it is API-based, and 
provides you with better compile-time checks. However sometimes you may want a 
completely scriptable object query. This is when you might prefer EJBQL. A more 
practical reason for picking EJBQL over SelectQuery though is that the former 
offers some extra selecting capabilities, namely aggregate functions and 
subqueries:
+In most cases SelectQuery is preferred to `EJBQLQuery`, as it is API-based,
+and provides you with better compile-time checks. However sometimes you may 
want a completely scriptable object query.
+This is when you might prefer EJBQL.
+A more practical reason for picking `EJBQL` over `SelectQuery`
+though is that the former offers some extra selecting capabilities, namely 
aggregate functions and subqueries:
 
 [source, java]
 ----
@@ -193,7 +227,9 @@ for(Object[] artistWithCount : result) {
 ----
 
 
-This also demonstrates a previously unseen type of select result - a List of 
Object[] elements, where each entry in an Object[] is either a DataObject or a 
scalar, depending on the query SELECT clause. A result can also be a list of 
scalars:
+This also demonstrates a previously unseen type of select result - a List of 
`Object[]` elements,
+where each entry in an Object[] is either a `DataObject` or a scalar, 
depending on the query SELECT clause.
+A result can also be a list of scalars:
 
 [source, java]
 ----
@@ -201,14 +237,18 @@ EJBQLQuery query = new EJBQLQuery("select a.name FROM 
Artist a");
 List<String> names = context.performQuery(query);
 ----
 
-EJBQLQuery supports an "IN" clause with three different usage-patterns. The 
following example would require three individual positional parameters (named 
parameters could also have been used) to be supplied.
+EJBQLQuery supports an "IN" clause with three different usage-patterns.
+The following example would require three individual positional parameters
+(named parameters could also have been used) to be supplied.
 
 [source, java]
 ----
 select p from Painting p where p.paintingTitle in (?1,?2,?3)
 ----
 
-The following example requires a single positional parameter to be supplied. 
The parameter can be any concrete implementation of the java.util.Collection 
interface such as java.util.List or java.util.Set.
+The following example requires a single positional parameter to be supplied.
+The parameter can be any concrete implementation of the `java.util.Collection` 
interface
+such as `java.util.List` or `java.util.Set`.
 
 [source, java]
 ----
@@ -222,17 +262,25 @@ The following example is functionally identical to the 
one prior.
 select p from Painting p where p.paintingTitle in (?1)
 ----
 
-It is xref:evaluete[possible to convert] an xref:expressions[Expression] 
object used with a xref:select[SelectQuery] to EJBQL. Use the 
Expression#appendAsEJBQL methods for this purpose.
+It is xref:evaluete[possible to convert] an xref:expressions[Expression] 
object used with a xref:select[SelectQuery] to EJBQL.
+Use the Expression#appendAsEJBQL methods for this purpose.
 
-While Cayenne Expressions discussed previously can be thought of as identical 
to JPQL WHERE clause, and indeed they are very close, there are a few noteable 
differences:
+While Cayenne Expressions discussed previously can be thought of as identical 
to JPQL WHERE clause,
+and indeed they are very close, there are a few noteable differences:
 
-- Null handling: SelectQuery would translate the expressions matching NULL 
values to the corresponding "X IS NULL" or "X IS NOT NULL" SQL syntax. 
EJBQLQuery on the other hand requires explicit "IS NULL" (or "IS NOT NULL") 
syntax to be used, otherwise the generated SQL will look like "X = NULL" (or "X 
<> NULL"), which will evaluate differently.
+- Null handling: SelectQuery would translate the expressions matching NULL 
values to the corresponding "X IS NULL"
+or "X IS NOT NULL" SQL syntax. EJBQLQuery on the other hand requires explicit 
"IS NULL" (or "IS NOT NULL")
+syntax to be used, otherwise the generated SQL will look like "X = NULL" (or 
"X <> NULL"),
+which will evaluate differently.
 
-- Expression Parameters: SelectQuery uses "$" to denote named parameters (e.g. 
"$myParam"), while EJBQL uses ":" (e.g. ":myParam"). Also EJBQL supports 
positional parameters denoted by the question mark: "?3".
+- Expression Parameters: SelectQuery uses "$" to denote named parameters (e.g. 
"$myParam"),
+while EJBQL uses ":" (e.g. ":myParam").
+Also EJBQL supports positional parameters denoted by the question mark: "?3".
 
 ===== SelectById
 
-This query allows to search objects by their ID. It's introduced in Cayenne 
4.0 and uses new "fluent" API same as `ObjectSelect` query.
+This query allows to search objects by their ID.
+It's introduced in Cayenne 4.0 and uses new "fluent" API same as 
`ObjectSelect` query.
 
 Here is example of how to use it:
 
@@ -246,7 +294,10 @@ Artist artistWithId1 = SelectById.query(Artist.class, 1)
 
 ===== SQLSelect and SQLExec
 
-`SQLSelect` and `SQLExec` are essentially a "fluent" versions of older 
`SQLTemplate` query. `SQLSelect` can be used (as name suggests) to select 
custom data in form of entities, separate columns or collection of `DataRow`. 
`SQLExec` is designed to just execute any raw SQL code (e.g. updates, deletes, 
DDLs, etc.) This queries support all directives described in 
xref:sqltemplate[SQLTemplate] section.
+`SQLSelect` and `SQLExec` are essentially a "fluent" versions of older 
`SQLTemplate` query.
+`SQLSelect` can be used (as name suggests) to select custom data in form of 
entities,
+separate columns or collection of `DataRow`. `SQLExec` is designed to just 
execute any raw SQL code
+(e.g. updates, deletes, DDLs, etc.) This queries support all directives 
described in <<SQLTemplate>> section.
 
 Here is example of how to use SQLSelect:
 
@@ -274,7 +325,10 @@ int inserted = SQLExec
 
 ===== MappedSelect and MappedExec
 
-`MappedSelect` and `MappedExec` is a queries that are just a reference to 
another queries stored in the DataMap. The actual stored query can be 
SelectQuery, SQLTemplate, EJBQLQuery, etc. Difference between `MappedSelect` 
and `MappedExec` is (as reflected in their names) whether underlying query 
intended to select data or just to perform some generic SQL code.
+`MappedSelect` and `MappedExec` is a queries that are just a reference to 
another queries stored in the DataMap.
+The actual stored query can be SelectQuery, SQLTemplate, EJBQLQuery, etc.
+Difference between `MappedSelect` and `MappedExec` is (as reflected in their 
names) whether underlying query
+intended to select data or just to perform some generic SQL code.
 
 NOTE: These queries are "fluent" versions of deprecated `NamedQuery` class.
 
@@ -299,7 +353,12 @@ System.out.println("Rows updated: " + 
result.firstUpdateCount());
 
 ==== ProcedureCall
 
-Stored procedures are mapped as separate objects in CayenneModeler. 
`ProcedureCall` provides a way to execute them with a certain set of 
parameters. This query is a "fluent" version of older `ProcedureQuery`. Just 
like with `SQLTemplate`, the outcome of a procedure can be anything - a single 
result set, multiple result sets, some data modification (returned as an update 
count), or a combination of these. So use root class to get a single result 
set, and use only procedure name for anything else:
+Stored procedures are mapped as separate objects in CayenneModeler.
+`ProcedureCall` provides a way to execute them with a certain set of 
parameters.
+This query is a "fluent" version of older `ProcedureQuery`. Just like with 
`SQLTemplate`,
+the outcome of a procedure can be anything - a single result set, multiple 
result sets,
+some data modification (returned as an update count), or a combination of 
these.
+So use root class to get a single result set, and use only procedure name for 
anything else:
 
 
 [source, java]
@@ -321,7 +380,9 @@ ProcedureResult result = ProcedureCall.query("my_procedure")
     .call();
 ----
 
-A stored procedure can return data back to the application as result sets or 
via OUT parameters. To simplify the processing of the query output, 
QueryResponse treats OUT parameters as if it was a separate result set. For 
stored procedures declaref any OUT or INOUT parameters, `ProcedureResult` have 
convenient utility method to get them:
+A stored procedure can return data back to the application as result sets or 
via OUT parameters.
+To simplify the processing of the query output, QueryResponse treats OUT 
parameters as if it was a separate result set.
+For stored procedures declaref any OUT or INOUT parameters, `ProcedureResult` 
have convenient utility method to get them:
 
 [source, java]
 ----
@@ -332,13 +393,20 @@ ProcedureResult result = 
ProcedureCall.query("my_procedure")
 Object out = result.getOutParam("out_param");
 ----
 
-There maybe a situation when a stored procedure handles its own transactions, 
but an application is configured to use Cayenne-managed transactions. This is 
obviously conflicting and undesirable behavior. In this case ProcedureQueries 
should be executed explicitly wrapped in an "external" Transaction. This is one 
of the few cases when a user should worry about transactions at all. See 
Transactions section for more details.
+There maybe a situation when a stored procedure handles its own transactions,
+but an application is configured to use Cayenne-managed transactions.
+This is obviously conflicting and undesirable behavior.
+In this case ProcedureQueries should be executed explicitly wrapped in an 
"external" Transaction.
+This is one of the few cases when a user should worry about transactions at 
all.
+See Transactions section for more details.
 
 ==== Custom Queries
 
-If a user needs some extra functionality not addressed by the existing set of 
Cayenne queries, he can write his own. The only requirement is to implement 
`org.apache.cayenne.query.Query` interface. The easiest way to go about it is 
to subclass some of the base queries in Cayenne.
+If a user needs some extra functionality not addressed by the existing set of 
Cayenne queries, he can write his own.
+The only requirement is to implement `org.apache.cayenne.query.Query` 
interface.
+The easiest way to go about it is to subclass some of the base queries in 
Cayenne.
 
-E.g. to do something directly in the JDBC layer, you might subclass 
AbstractQuery:
+E.g. to do something directly in the JDBC layer, you might subclass 
`AbstractQuery`:
 
 [source, java]
 ----
@@ -358,7 +426,7 @@ public class MyQuery extends AbstractQuery {
 }
 ----
 
-To delegate the actual query execution to a standard Cayenne query, you may 
subclass IndirectQuery:
+To delegate the actual query execution to a standard Cayenne query, you may 
subclass `IndirectQuery`:
 
 
 [source, java]
@@ -378,11 +446,16 @@ public class MyDelegatingQuery extends IndirectQuery {
 }
 ----
 
-In fact many internal Cayenne queries are IndirectQueries, delegating to 
SelectQuery or SQLTemplate after some preprocessing.
+In fact many internal Cayenne queries are `IndirectQueries`, delegating to 
`SelectQuery` or `SQLTemplate`
+ after some preprocessing.
 
 [[sqltemplate]]
 ==== SQLTemplate
-SQLTemplate is a query that allows to run native SQL from a Cayenne 
application. It comes handy when the standard ORM concepts are not sufficient 
for a given query or an update. SQL is too powerful and allows to manipulate 
data in ways that are not easily described as a graph of related entities. 
Cayenne acknowledges this fact and provides this facility to execute SQL, 
mapping the result to objects when possible. Here are examples of selecting and 
non-selecting SQLTemplates:
+SQLTemplate is a query that allows to run native SQL from a Cayenne 
application.
+It comes handy when the standard ORM concepts are not sufficient for a given 
query or an update.
+SQL is too powerful and allows to manipulate data in ways that are not easily 
described as a graph of related entities.
+Cayenne acknowledges this fact and provides this facility to execute SQL, 
mapping the result to objects when possible.
+Here are examples of selecting and non-selecting SQLTemplates:
 
 
 [source, java]
@@ -397,13 +470,28 @@ SQLTemplate update = new SQLTemplate(Artist.class, 
"delete from ARTIST");
 QueryResponse response = context.performGenericQuery(update);
 ----
 
-Cayenne doesn't make any attempt to make sense of the SQL semantics, so it 
doesn't know whether a given query is performing a select or update, etc. It is 
the the user's decision to run a given query as a selecting or "generic".
+Cayenne doesn't make any attempt to make sense of the SQL semantics,
+so it doesn't know whether a given query is performing a select or update, etc.
+It is the the user's decision to run a given query as a selecting or "generic".
 
-NOTE: Any data modifications done to DB as a result of SQLTemplate execution 
do not change the state of objects in the ObjectContext. So some objects in the 
context may become stale as a result.
+NOTE: Any data modifications done to DB as a result of `SQLTemplate` execution 
do not change the state
+of objects in the ObjectContext. So some objects in the context may become 
stale as a result.
 
-Another point to note is that the first argument to the SQLTemplate 
constructor - the Java class - has the same meaning as in SelectQuery only when 
the result can be converted to objects (e.g. when this is a selecting query and 
it is selecting all columns from one table). In this case it denotes the "root" 
entity of this query result. If the query does not denote a single entity 
result, this argument is only used for query routing, i.e. determining which 
database it should be run against. You are free to use any persistent class or 
even a DataMap instance in such situation. It will work as long as the passed 
"root" maps to the same database as the current query.
+Another point to note is that the first argument to the `SQLTemplate` 
constructor - the Java class -
+has the same meaning as in SelectQuery only when the result can be converted 
to objects
+(e.g. when this is a selecting query and it is selecting all columns from one 
table).
+In this case it denotes the "root" entity of this query result. If the query 
does not denote a single entity result,
+this argument is only used for query routing, i.e. determining which database 
it should be run against.
+You are free to use any persistent class or even a DataMap instance in such 
situation.
+It will work as long as the passed "root" maps to the same database as the 
current query.
 
-To achieve interoperability between mutliple RDBMS a user can specify multiple 
SQL statements for the same SQLTemplate, each corresponding to a native SQL 
dialect. A key used to look up the right dialect during execution is a fully 
qualified class name of the corresponding DbAdapter. If no DB-specific 
statement is present for a given DB, a default generic statement is used. E.g. 
in all the examples above a default statement will be used regardless of the 
runtime database. So in most cases you won't need to explicitly "translate" 
your SQL to all possible dialects. Here is how this works in practice:
+To achieve interoperability between multiple RDBMS a user can specify multiple 
SQL statements
+for the same `SQLTemplate`, each corresponding to a native SQL dialect.
+A key used to look up the right dialect during execution is a fully qualified 
class name of the corresponding `DbAdapter`.
+If no DB-specific statement is present for a given DB, a default generic 
statement is used.
+E.g. in all the examples above a default statement will be used regardless of 
the runtime database.
+So in most cases you won't need to explicitly "translate" your SQL to all 
possible dialects.
+Here is how this works in practice:
 
 [source, java]
 ----
@@ -416,11 +504,17 @@ String pgSQL = "SELECT ARTIST_ID, RTRIM(NAME), 
DATE_OF_BIRTH FROM ARTIST";
 query.setTemplate(PostgresAdapter.class.getName(), pgSQL);
 ----
 
-===== Scripting SQLTemplate with Velocity
+===== Scripting SQLTemplate with templates
 
-The most interesting aspect of SQLTemplate (and the reason why it is called a 
"template") is that a SQL string is treated by Cayenne as an Apache Velocity 
template. Before sending it to DB as a PreparedStatement, the String is 
evaluated in the Velocity context, that does variable substitutions, and 
performs special callbacks in response to various directives, thus controlling 
query interaction with the JDBC layer.
+The most interesting aspect of SQLTemplate (and the reason why it is called a 
"template")
+is that a SQL string is treated by Cayenne as a template. Before sending it to 
DB as a PreparedStatement,
+the String is evaluated, that does variable substitutions, and performs 
special callbacks
+in response to various directives, thus controlling query interaction with the 
JDBC layer.
 
-Check Velocity docs for the syntax details. Here we'll just mention the two 
main scripting elements - "variables" (that look like `$var`) and "directives" 
(that look like `#directive(p1 p2 p3)`). All built-in Velocity directives are 
supported. Additionally Cayenne defines a number of its own directives to bind 
parameters to PreparedStatements and to control the structure of the ResultSet. 
These directives are described in the following sections.
+Here we'll describe the two main scripting elements - "variables" (that look 
like `$var`)
+and "directives" (that look like `#directive(p1 p2 p3)`).
+Cayenne defines a number of directives to bind parameters to 
`PreparedStatement`
+and to control the structure of the `ResultSet`. These directives are 
described in the following sections.
 
 
 ===== Variable Substitution
@@ -436,9 +530,15 @@ query.setParameters(Collections.singletonMap("tableName", 
"mydb.PAINTING"));
 // this will generate SQL like this: "delete from mydb.PAINTING"
 ----
 
-The example above demonstrates the point made earlier in this chapter - even 
if we don't know upfront which table the query will run against, we can still 
use a fixed "root" in constructor (`Artist.class` in this case) , as we are not 
planning on converting the result to objects.
+The example above demonstrates the point made earlier in this chapter -
+even if we don't know upfront which table the query will run against,
+we can still use a fixed "root" in constructor (`Artist.class` in this case),
+as we are not planning on converting the result to objects.
 
-Variable substitution within the text uses `"object.toString()"` method to 
replace the variable value. Keep in mind that this may not be appropriate in 
all situations. E.g. passing a date object in a WHERE clause expression may be 
converted to a String not understood by the target RDBMS SQL parser. In such 
cases variable should be wrapped in `#bind` directive as described below.
+Variable substitution within the text uses `object.toString()` method to 
replace the variable value.
+Keep in mind that this may not be appropriate in all situations.
+E.g. passing a date object in a WHERE clause expression may be converted to a 
String not understood by the target RDBMS SQL parser.
+In such cases variable should be wrapped in `#bind` directive as described 
below.
 
 [[directives]]
 ===== Directives
@@ -447,7 +547,10 @@ These are the Cayenne directives used to customize 
SQLTemplate parsing and integ
 
 ====== #bind
 
-Creates a PreparedStatement positional parameter in place of the directive, 
binding the value to it before statement execution. `#bind` is allowed in 
places where a "?" would be allowed in a PreparedStatement. And in such places 
it almost always makes sense to pass objects to the template via this or other 
forms of #bind instead of inserting them inline.
+Creates a PreparedStatement positional parameter in place of the directive, 
binding the value to it before statement execution.
+`#bind` is allowed in places where a "?" would be allowed in a 
PreparedStatement.
+And in such places it almost always makes sense to pass objects to the 
template via this
+or other forms of `#bind` instead of inserting them inline.
 
 Semantics:
 
@@ -460,7 +563,9 @@ Semantics:
 
 Arguments:
 
-- `value` - can either be a char constant or a variable that is resolved from 
the query parameters. Note that the variable can be a collection, that will be 
automatically expanded into a list of individual value bindings. This is useful 
for instance to build IN conditions.
+- `value` - can either be a char constant or a variable that is resolved from 
the query parameters.
+Note that the variable can be a collection, that will be automatically 
expanded into a list of individual value bindings.
+This is useful for instance to build IN conditions.
 
 - `jdbcType` - is a JDBC data type of the parameter as defined in 
`java.sql.Types`.
 
@@ -486,7 +591,12 @@ update ARTIST set NAME = #bind($name) where ID = #bind($id)
 
 ====== #bindEqual
 
-Same as #bind, but also includes the "=" sign in front of the value binding. 
Look at the example below - we took the #bind example and replaced `"ID = 
#bind(..)"` with `"ID #bindEqual(..)"`. While it looks like a clumsy shortcut 
to eliminate the equal sign, the actual reason why this is useful is that it 
allows the value to be null. If the value is not null, `"= ?"` is generated, 
but if it is, the resulting chunk of the SQL would look like `"IS NULL"` and 
will be compilant with what the DB expects.
+Same as #bind, but also includes the "=" sign in front of the value binding.
+Look at the example below - we took the #bind example and replaced `"ID = 
#bind(..)"` with `"ID #bindEqual(..)"`.
+While it looks like a clumsy shortcut to eliminate the equal sign,
+the actual reason why this is useful is that it allows the value to be null.
+If the value is not null, `"= ?"` is generated, but if it is, the resulting 
chunk of the SQL would look like `"IS NULL"`
+and will be compilant with what the DB expects.
 
 Semantics:
 
@@ -554,7 +664,11 @@ update ARTIST set NAME = #bind($name) where ID 
#bindEqual($id)
 
 ====== #bindObjectEqual
 
-It can be tricky to use a Persistent object or an ObjectId in a binding, 
especially for tables with compound primary keys. This directive helps to 
handle such binding. It maps columns in the query to the names of Persistent 
object ID columns, extracts ID values from the object, and generates SQL like 
"COL1 = ? AND COL2 = ? ..." , binding positional parameters to ID values. It 
can also correctly handle null object. Also notice how we are specifying a 
Velocity array for multi-column PK.
+It can be tricky to use a Persistent object or an ObjectId in a binding,
+especially for tables with compound primary keys. This directive helps to 
handle such binding.
+It maps columns in the query to the names of Persistent object ID columns, 
extracts ID values from the object,
+and generates SQL like "COL1 = ? AND COL2 = ? ..." , binding positional 
parameters to ID values.
+It can also correctly handle null object. Also notice how we are specifying an 
array for multi-column PK.
 
 Semantics:
 
@@ -624,7 +738,9 @@ select.setParameters(Collections.singletonMap("a", a));
 
 ====== #result
 
-Renders a column in SELECT clause of a query and maps it to a key in the 
result DataRow. Also ensures the value read is of the correct type. This allows 
to create a DataRow (and ultimately - a persistent object) from an arbitrary 
ResultSet.
+Renders a column in SELECT clause of a query and maps it to a key in the 
result DataRow.
+Also ensures the value read is of the correct type. This allows to create a 
DataRow (and ultimately - a persistent object)
+from an arbitrary ResultSet.
 
 Semantics:
 
@@ -640,11 +756,16 @@ Arguments:
 
 - `column` - the name of the column to render in SQL SELECT clause.
 
-- `javaType` - a fully-qualified Java class name for a given result column. 
For simplicity most common Java types used in JDBC can be specified without a 
package. These include all numeric types, primitives, String, SQL dates, 
BigDecimal and BigInteger. So `"#result('A' 'String')"`, `"#result('B' 
'java.lang.String')"` and `"#result('C' 'int')"` are all valid
+- `javaType` - a fully-qualified Java class name for a given result column.
+For simplicity most common Java types used in JDBC can be specified without a 
package.
+These include all numeric types, primitives, String, SQL dates, BigDecimal and 
BigInteger.
+So `"#result('A' 'String')"`, `"#result('B' 'java.lang.String')"` and 
`"#result('C' 'int')"` are all valid
 
 - `alias` - specifies both the SQL alias of the column and the value key in 
the DataRow. If omitted, "column" value is used.
 
-- `dataRowKey` - needed if SQL 'alias' is not appropriate as a DataRow key on 
the Cayenne side. One common case when this happens is when a DataRow retrieved 
from a query is mapped using joint prefetch keys (see below). In this case 
DataRow must use database path expressions for joint column keys, and their 
format is incompatible with most databases alias format.
+- `dataRowKey` - needed if SQL 'alias' is not appropriate as a DataRow key on 
the Cayenne side.
+One common case when this happens is when a DataRow retrieved from a query is 
mapped using joint prefetch keys (see below).
+In this case DataRow must use database path expressions for joint column keys, 
and their format is incompatible with most databases alias format.
 
 Usage:
 
@@ -669,7 +790,9 @@ NOTE: For advanced features you may look at the <<Apache 
Velocity extension>>
 
 ====== Mapping SQLTemplate Results
 
-Here we'll discuss how to convert the data selected via SQLTemplate to some 
useable format, compatible with other query results. It can either be very 
simple or very complex, depending on the structure of the SQL, JDBC driver 
nature and the desired result structure. This section presents various tips and 
tricks dealing with result mapping.
+Here we'll discuss how to convert the data selected via SQLTemplate to some 
useable format, compatible with other query results.
+It can either be very simple or very complex, depending on the structure of 
the SQL,
+JDBC driver nature and the desired result structure. This section presents 
various tips and tricks dealing with result mapping.
 
 By default SQLTemplate is expected to return a List of Persistent objects of 
its root type. This is the simple case:
 
@@ -681,7 +804,9 @@ SQLTemplate query = new SQLTemplate(Artist.class, "SELECT * 
FROM ARTIST");
 List<Artist> artists = context.performQuery(query);
 ----
 
-Just like SelectQuery, SQLTemplate can fetch DataRows. In fact DataRows option 
is very useful with SQLTemplate, as the result type most often than not does 
not represent a Cayenne entity, but instead may be some aggregated report or 
any other data whose object structure is opaque to Cayenne:
+Just like SelectQuery, SQLTemplate can fetch DataRows. In fact DataRows option 
is very useful with SQLTemplate,
+as the result type most often than not does not represent a Cayenne entity,
+but instead may be some aggregated report or any other data whose object 
structure is opaque to Cayenne:
 
 [source, Java]
 ----
@@ -696,9 +821,16 @@ query.setFetchingDataRows(true);
 List<DataRow> rows = context.performQuery(query);
 ----
 
-In the example above, even though the query root is Artist. the result is a 
list of artist names with painting counts (as mentioned before in such case 
"root" is only used to find the DB to fetch against, but has no bearning on the 
result). The DataRows here are the most appropriate and desired result type.
+In the example above, even though the query root is Artist.
+The result is a list of artist names with painting counts (as mentioned before 
in such case "root"
+is only used to find the DB to fetch against, but has no bearning on the 
result).
+The DataRows here are the most appropriate and desired result type.
 
-In a more advanced case you may decide to fetch a list of scalars or a list of 
Object[] with each array entry being either an entity or a scalar. You probably 
won't be doing this too often and it requires quite a lot of work to setup, but 
if you want your SQLTemplate to return results similar to EJBQLQuery, it is 
doable using SQLResult as described below:
+In a more advanced case you may decide to fetch a list of scalars or a list of 
`Object[]`
+with each array entry being either an entity or a scalar.
+You probably won't be doing this too often and it requires quite a lot of work 
to setup,
+but if you want your `SQLTemplate` to return results similar to `EJBQLQuery`,
+it is doable using `SQLResult` as described below:
 
 [source, Java]
 ----
@@ -734,7 +866,11 @@ query.setResult(resultDescriptor);
 List<Object[]> data = context.performQuery(query);
 ----
 
-Another trick related to mapping result sets is making Cayenne recognize 
prefetched entities in the result set. This emulates "joint" prefetching of 
SelectQuery, and is achieved by special column naming. Columns belonging to the 
"root" entity of the query should use unqualified names corresponding to the 
root DbEntity columns. For each related entity column names must be prefixed 
with relationship name and a dot (e.g. "toArtist.ID"). Column naming can be 
controlled with "#result" directive:
+Another trick related to mapping result sets is making Cayenne recognize 
prefetched entities in the result set.
+This emulates "joint" prefetching of `SelectQuery`, and is achieved by special 
column naming.
+Columns belonging to the "root" entity of the query should use unqualified 
names corresponding to the root `DbEntity` columns.
+For each related entity column names must be prefixed with relationship name 
and a dot (e.g. "toArtist.ID").
+Column naming can be controlled with `#result` directive:
 
 [source, Java]
 ----
@@ -754,9 +890,20 @@ q.addPrefetch(Artist.PAINTINGS_PROPERTY)
 List<Artist> objects = context.performQuery(query);
 ----
 
-And the final tip deals with capitalization of the DataRow keys. Queries like 
`"SELECT * FROM..."` and even `"SELECT COLUMN1, COLUMN2, ... FROM ..."` can 
sometimes result in Cayenne exceptions on attempts to convert fetched DataRows 
to objects. Essentially any query that is not using a `#result` directive to 
describe the result set is prone to this problem, as different databases may 
produce different capitalization of the java.sql.ResultSet columns.
+And the final tip deals with capitalization of the DataRow keys. Queries like 
`"SELECT * FROM..."`
+and even `"SELECT COLUMN1, COLUMN2, ... FROM ..."` can sometimes result in 
Cayenne exceptions
+on attempts to convert fetched DataRows to objects.
+Essentially any query that is not using a `#result` directive to describe the 
result set is prone to this problem,
+as different databases may produce different capitalization of the 
`java.sql.ResultSet` columns.
 
-The most universal way to address this issue is to describe each column 
explicitly in the SQLTemplate via `#result`, e.g.: `"SELECT #result('column1'), 
#result('column2'), .."`. However this quickly becomes impractical for tables 
with lots of columns. For such cases Cayenne provides a shortcut based on the 
fact that an ORM mapping usually follows some naming convention for the column 
names. Simply put, for case-insensitive databases developers normally use 
either all lowercase or all uppercase column names. Here is the API that takes 
advantage of that user knowledge and forces Cayenne to follow a given naming 
convention for the DataRow keys (this is also available as a dropdown in the 
Modeler):
+The most universal way to address this issue is to describe each column 
explicitly in the SQLTemplate via `#result`,
+e.g.: `"SELECT #result('column1'), #result('column2'), .."`.
+However this quickly becomes impractical for tables with lots of columns.
+For such cases Cayenne provides a shortcut based on the fact that an ORM 
mapping usually follows some naming convention
+for the column names. Simply put, for case-insensitive databases developers
+normally use either all lowercase or all uppercase column names.
+Here is the API that takes advantage of that user knowledge and forces Cayenne 
to follow
+a given naming convention for the DataRow keys (this is also available as a 
dropdown in the Modeler):
 
 [source, Java]
 ----
@@ -774,7 +921,10 @@ query.setColumnNamesCapitalization(CapsStrategy.UPPER);
 List objects = context.performQuery(query);
 ----
 
-None of this affects the generated SQL, but the resulting DataRows are using 
correct capitalization. Note that you probably shouldn't bother with this 
unless you are getting CayenneRuntimeExceptions when fetching with SQLTemplate.
+None of this affects the generated SQL, but the resulting DataRows are using 
correct capitalization.
+
+NOTE: You probably shouldn't bother with this unless you are getting
+`CayenneRuntimeExceptions` when fetching with `SQLTemplate`.
 
 
 

Reply via email to