[#1657] Reorganise the manual (144 / 176)

This commit is contained in:
Lukas Eder 2012-08-25 14:30:22 +02:00
parent 8659323f1b
commit 311f3e2652

View File

@ -4457,30 +4457,101 @@ create.fetch("SELECT * FROM BOOK WHERE ID = 5 AND TITLE = 'Animal Farm'");]]></j
</ul>
<p>
Both of these methods are contained in jOOQ's internal API's <reference class="org.jooq.QueryPartInternal"/>, which is internally implemented by every QueryPart. QueryPart internals are best illustrated with an example.
Both of these methods are contained in jOOQ's internal API's <reference class="org.jooq.QueryPartInternal"/>, which is internally implemented by every QueryPart.
</p>
<h3>Example: CompareCondition</h3>
<p>
A simple example can be provided by checking out jOOQ's internal representation of a (simplified) <reference id="comparison-predicate" title="CompareCondition"/>. It is used for any <reference class="org.jooq.Condition"/> comparing two fields as for example the T_AUTHOR.ID = T_BOOK.AUTHOR_ID condition here:
</p>
<p>
The following sections explain some more details about <reference id="sql-rendering" title="SQL rendering"/> and <reference id="variable-binding" title="variable binding"/>, as well as other implementation details about QueryParts in general.
</p>
</content>
<sections>
<section id="sql-rendering">
<title>SQL rendering</title>
<content>
<h3>QueryParts and how they render SQL statements</h3>
<p>
Every <reference class="org.jooq.QueryPart"/> must implement the <reference class="org.jooq.QueryPartInternal" anchor="#toSQL(org.jooq.RenderContext)" title="toSQL(RenderContext)"/> method to render its SQL string to a <reference class="org.jooq.RenderContext"/>. This RenderContext has two purposes:
</p>
<ul>
<li>It provides some information about the "state" of SQL rendering.</li>
<li>It provides a common API for constructing SQL strings on the context's internal <reference class="java.lang.StringBuilder"/></li>
</ul>
<p>
An overview of the <reference class="org.jooq.RenderContext"/> API is given here:
</p>
<java><![CDATA[// These methods are useful for generating unique aliases within a RenderContext (and thus within a Query)
String peekAlias();
String nextAlias();
// These methods return rendered SQL
String render();
String render(QueryPart part);
// These methods allow for fluent appending of SQL to the RenderContext's internal StringBuilder
RenderContext keyword(String keyword);
RenderContext literal(String literal);
RenderContext sql(String sql);
RenderContext sql(char sql);
RenderContext sql(int sql);
RenderContext sql(QueryPart part);
// These methods allow for controlling formatting of SQL, if the relevant Setting is active
RenderContext formatNewLine();
RenderContext formatSeparator();
RenderContext formatIndentStart();
RenderContext formatIndentStart(int indent);
RenderContext formatIndentLockStart();
RenderContext formatIndentEnd();
RenderContext formatIndentEnd(int indent);
RenderContext formatIndentLockEnd();
// These methods control the RenderContext's internal state
boolean inline();
RenderContext inline(boolean inline);
boolean qualify();
RenderContext qualify(boolean qualify);
boolean namedParams();
RenderContext namedParams(boolean renderNamedParams);
CastMode castMode();
RenderContext castMode(CastMode mode);
Boolean cast();
RenderContext castModeSome(SQLDialect... dialects);]]></java>
<p>
The following additional methods are inherited from a common <reference class="org.jooq.Context"/>, which is shared among <reference class="org.jooq.RenderContext"/> and <reference class="org.jooq.BindContext"/>:
</p>
<java><![CDATA[// These methods indicate whether fields or tables are being declared (MY_TABLE AS MY_ALIAS) or referenced (MY_ALIAS)
boolean declareFields();
Context declareFields(boolean declareFields);
boolean declareTables();
Context declareTables(boolean declareTables);
// These methods indicate whether a top-level query is being rendered, or a subquery
boolean subquery();
Context subquery(boolean subquery);
// These methods provide the bind value indices within the scope of the whole Context (and thus of the whole Query)
int nextIndex();
int peekIndex();]]></java>
<h3>An example of rendering SQL</h3>
<p>
A simple example can be provided by checking out jOOQ's internal representation of a (simplified) <reference id="comparison-predicate" title="CompareCondition"/>. It is used for any <reference class="org.jooq.Condition"/> comparing two fields as for example the T_AUTHOR.ID = T_BOOK.AUTHOR_ID condition here:
</p>
<sql>-- [...]
FROM T_AUTHOR
JOIN T_BOOK ON T_AUTHOR.ID = T_BOOK.AUTHOR_ID
-- [...]</sql>
<p>
This is how jOOQ implements such a condition:
</p>
<p>
This is how jOOQ renders such a condition:
</p>
<java><![CDATA[@Override
public final void bind(BindContext context) throws DataAccessException {
// The CompareCondition itself does not bind any variables.
// But the two fields involved in the condition might do so...
context.bind(field1).bind(field2);
}
@Override
public final void toSQL(RenderContext context) {
// The CompareCondition delegates rendering of the Fields to the Fields
// themselves and connects them using the Condition's comparator operator:
@ -4511,38 +4582,194 @@ public final void toSQL(RenderContext context) {
.sql(" ")
.sql(field2);
}
}
]]></java>
}]]></java>
<p>
The following sections explain some more details about <reference id="sql-rendering" title="SQL rendering"/> and <reference id="variable-binding" title="variable binding"/>, as well as other implementation details about QueryParts in general.
</p>
</content>
<sections>
<section id="sql-rendering">
<title>SQL rendering</title>
<content></content>
<p>
See the manual's sections about <reference id="custom-queryparts" title="custom QueryParts"/> and <reference id="plain-sql-queryparts" title="plain SQL QueryParts"/> to learn about how to write your own query parts in order to extend jOOQ.
</p>
</content>
</section>
<section id="variable-binding">
<title>Variable binding</title>
<content></content>
<content>
<h3>QueryParts and how they bind values to SQL statements</h3>
<p>
Every <reference class="org.jooq.QueryPart"/> must implement the <reference class="org.jooq.QueryPartInternal" anchor="#bind(org.jooq.BindContext)" title="bind(BindContext)"/> method. This BindContext has two purposes:
</p>
<ul>
<li>It provides some information about the "state" of the variable binding in process.</li>
<li>It provides a common API for binding values to the context's internal <reference class="java.sql.PreparedStatement"/></li>
</ul>
<p>
An overview of the <reference class="org.jooq.RenderContext"/> API is given here:
</p>
<java><![CDATA[// This method provides access to the PreparedStatement to which bind values are bound
PreparedStatement statement();
// These methods provide convenience to delegate variable binding
BindContext bind(QueryPart part) throws DataAccessException;
BindContext bind(Collection<? extends QueryPart> parts) throws DataAccessException;
BindContext bind(QueryPart[] parts) throws DataAccessException;
// These methods perform the actual variable binding
BindContext bindValue(Object value, Class<?> type) throws DataAccessException;
BindContext bindValues(Object... values) throws DataAccessException;]]></java>
<p>
Some additional methods are inherited from a common <reference class="org.jooq.Context"/>, which is shared among <reference class="org.jooq.RenderContext"/> and <reference class="org.jooq.BindContext"/>. Details are documented in the previous chapter about <reference id="sql-rendering" title="SQL rendering"/>
</p>
<h3>An example of binding values to SQL</h3>
<p>
A simple example can be provided by checking out jOOQ's internal representation of a (simplified) <reference id="comparison-predicate" title="CompareCondition"/>. It is used for any <reference class="org.jooq.Condition"/> comparing two fields as for example the T_AUTHOR.ID = T_BOOK.AUTHOR_ID condition here:
</p>
<sql>-- [...]
WHERE T_AUTHOR.ID = ?
-- [...]</sql>
<p>
This is how jOOQ binds values on such a condition:
</p>
<java><![CDATA[@Override
public final void bind(BindContext context) throws DataAccessException {
// The CompareCondition itself does not bind any variables.
// But the two fields involved in the condition might do so...
context.bind(field1).bind(field2);
}]]></java>
<p>
See the manual's sections about <reference id="custom-queryparts" title="custom QueryParts"/> and <reference id="plain-sql-queryparts" title="plain SQL QueryParts"/> to learn about how to write your own query parts in order to extend jOOQ.
</p>
</content>
</section>
<section id="custom-queryparts">
<title>Custom QueryParts</title>
<content></content>
<title>Extend jOOQ with custom types</title>
<content>
<h3>Write your own QueryPart implementations</h3>
<p>
If a SQL clause is too complex to express with jOOQ, you can extend either one of the following types for use directly in a jOOQ query:
</p>
<java><![CDATA[public abstract class CustomField<T> extends AbstractField<T> {}
public abstract class CustomCondition extends AbstractCondition {}
public abstract class CustomTable<R extends TableRecord<R>> extends TableImpl<R> {}
public abstract class CustomRecord<R extends TableRecord<R>> extends TableRecordImpl<R> {}]]></java>
<p>
These classes are declared public and covered by jOOQ's integration tests. When you extend these classes, you will have to provide your own implementations for the <reference id="queryparts" title="QueryParts'"/> <reference id="sql-rendering" title="toSQL()"/> and <reference id="variable-binding" title="bind()"/> methods, as discussed before:
</p>
<java><![CDATA[// This method must produce valid SQL. If your QueryPart contains other QueryParts, you may delegate SQL code generation to them
// in the correct order, passing the render context.
//
// If context.inline() is true, you must inline all bind variables
// If context.inline() is false, you must generate ? for your bind variables
public void toSQL(RenderContext context);
// This method must bind all bind variables to a PreparedStatement. If your QueryPart contains other QueryParts, you may delegate
// variable binding to them in the correct order, passing the bind context.
//
// Every QueryPart must ensure, that it starts binding its variables at context.nextIndex().
public void bind(BindContext context) throws DataAccessException;]]></java>
<p>
The above contract may be a bit tricky to understand at first. The best thing is to check out jOOQ source code and have a look at a couple of QueryParts, to see how it's done. Here's an example <reference class="org.jooq.impl.CustomField"/> showing how to create a field multiplying another field by 2
</p>
<java><![CDATA[// Create an anonymous CustomField, initialised with BOOK.ID arguments
final Field<Integer> IDx2 = new CustomField<Integer>(BOOK.ID.getName(), BOOK.ID.getDataType()) {
@Override
public void toSQL(RenderContext context) {
// In inline mode, render the multiplication directly
if (context.inline()) {
context.sql(BOOK.ID).sql(" * 2");
}
// In non-inline mode, render a bind value
else {
context.sql(BOOK.ID).sql(" * ?");
}
}
@Override
public void bind(BindContext context) {
try {
// Manually bind the value 2
context.statement().setInt(context.nextIndex(), 2);
// Alternatively, you could also write:
// context.bind(Factory.val(2));
}
catch (SQLException e) {
throw translate(getSQL(), e);
}
}
};
// Use the above field in a SQL statement:
create.select(IDx2).from(BOOK);]]></java>
</content>
</section>
<section id="plain-sql-queryparts">
<title>Plain SQL QueryParts</title>
<content></content>
<content>
<h3>Plain SQL as a simpler alternative to custom QueryParts</h3>
<p>
If you don't need the integration of rather complex QueryParts into jOOQ, then you might be safer using simple <reference id="plain-sql" title="Plain SQL"/> functionality, where you can provide jOOQ with a simple String representation of your embedded SQL. Plain SQL methods in jOOQ's API come in two flavours.
</p>
<ul>
<li><strong>method(String, Object...)</strong>: This is a method that accepts a SQL string and a list of bind values that are to be bound to the variables contained in the SQL string</li>
<li><strong>method(String, QueryPart...)</strong>: This is a method that accepts a SQL string and a list of QueryParts that are "injected" at the position of their respective placeholders in the SQL string</li>
</ul>
<p>
The above distinction is best explained using an example:
</p>
<java><![CDATA[// Plain SQL using bind values. The value 5 is bound to the first variable, "Animal Farm" to the second variable:
create.selectFrom(BOOK).where("BOOK.ID = ? AND TITLE = ?", 5, "Animal Farm");
// Plain SQL using placeholders (counting from zero). The QueryPart "id" is substituted for the placeholder {0}, the QueryPart "title" for {1}
Field<Integer> id = val(5);
Field<String> title = val("Animal Farm");
create.selectFrom(BOOK).where("BOOK.ID = {0} AND TITLE = {1}", id, title);]]></java>
<p>
The above technique allows for creating rather complex SQL clauses that are currently not supported by jOOQ, without extending any of the <reference id="custom-queryparts" title="custom QueryParts"/> as indicated in the previous chapter.
</p>
</content>
</section>
<section id="serializability">
<title>Serializability</title>
<content></content>
<content>
<h3>Attaching QueryParts</h3>
<p>
The only transient, non-serializable element in any jOOQ object is the <reference id="factory" title="Factory's"/> underlying <reference class="java.sql.Connection"/>. When you want to execute queries after de-serialisation, or when you want to store/refresh/delete <reference id="crud-with-updatablerecords" title="Updatable Records"/>, you will have to "re-attach" them to a Factory
</p>
<java><![CDATA[// Deserialise a SELECT statement
ObjectInputStream in = new ObjectInputStream(...);
Select<?> select = (Select<?>) in.readObject();
// This will throw a DetachedException:
select.execute();
// In order to execute the above select, attach it first
Factory create = new Factory(connection, SQLDialect.ORACLE);
create.attach(select);]]></java>
<h3>Automatically attaching QueryParts</h3>
<p>
Another way of attaching QueryParts automatically, or rather providing them with a new <reference class="java.sql.Connection"/> at will, is to hook into the <reference id="execute-listeners" title="Execute Listener support"/>. More details about this can be found in the manual's chapter about <reference id="execute-listeners" title="ExecuteListeners"/>
</p>
</content>
</section>
</sections>
</section>