[#1657] Reorganise the manual (144 / 176)
This commit is contained in:
parent
8659323f1b
commit
311f3e2652
@ -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>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user