From ecaeee7d97d520d18a973a5429d0084fa4046bde Mon Sep 17 00:00:00 2001
From: Lukas Eder
Date: Fri, 12 Apr 2013 10:46:13 +0200
Subject: [PATCH] - Updated manual - Added feature to the manual
language, to generate redirection in HTML manuals
---
jOOQ-website/src/main/java/Transform.java | 72 ++-
jOOQ-website/src/main/resources/html-page.xsl | 6 +
.../src/main/resources/manual-3.0.xml | 473 ++++++++++--------
3 files changed, 307 insertions(+), 244 deletions(-)
diff --git a/jOOQ-website/src/main/java/Transform.java b/jOOQ-website/src/main/java/Transform.java
index a1ec1be213..aa908e35d4 100644
--- a/jOOQ-website/src/main/java/Transform.java
+++ b/jOOQ-website/src/main/java/Transform.java
@@ -41,6 +41,8 @@ import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -62,6 +64,7 @@ import org.apache.fop.apps.MimeConstants;
import org.jooq.Constants;
import org.joox.Context;
import org.joox.Each;
+import org.joox.Filter;
import org.joox.Match;
/**
@@ -184,8 +187,16 @@ public class Transform {
}
int blanks = 0, completed = 0;
- for (Match section : manual.find("section").each()) {
- Match sections = section.add(section.parents("section")).reverse();
+
+ Filter f = new Filter() {
+ @Override
+ public boolean filter(Context arg0) {
+ return Arrays.asList("section", "redirect").contains($(arg0.element()).tag());
+ }
+ };
+
+ for (Match section : manual.xpath("//section | //redirect").each()) {
+ Match sections = section.add(section.parents(f)).reverse();
String path = path(StringUtils.join(sections.ids(), "/"));
String relativePath = relative(path);
@@ -193,31 +204,48 @@ public class Transform {
File dir = new File(path);
dir.mkdirs();
- PrintStream stream = System.out;
- boolean blank = StringUtils.isBlank(section.find("content").text());
- if (blank) {
- blanks++;
- stream = System.err;
- }
- else {
- completed++;
- }
-
- stream.print("[");
- stream.print(blank ? " " : "x");
- stream.println("] Transforming section " + path);
-
File file = new File(dir, "index.php");
file.delete();
FileOutputStream out = new FileOutputStream(file);
- Source source = new DOMSource(manual.document());
- Result target = new StreamResult(out);
+ // A redirection section
+ if ("redirect".equals(section.tag())) {
+ Match redirectSection = manual.xpath("//section[@id='" + section.attr("redirect-to") + "']");
+ Match redirectSections = redirectSection.add(redirectSection.parents("section")).reverse();
- transformer.setParameter("sectionID", section.id());
- transformer.setParameter("relativePath", relativePath);
- transformer.setParameter("root", root);
- transformer.transform(source, target);
+ String redirectPath = path(StringUtils.join(redirectSections.ids(), "/"));
+
+ PrintWriter o = new PrintWriter(out);
+ o.println("");
+ o.flush();
+
+ System.out.println("[r] Redirecting section " + path + " to " + redirectPath);
+ }
+
+ // A regular section (without redirection)
+ else {
+ PrintStream stream = System.out;
+ boolean blank = StringUtils.isBlank(section.find("content").text());
+ if (blank) {
+ blanks++;
+ stream = System.err;
+ }
+ else {
+ completed++;
+ }
+
+ stream.print("[");
+ stream.print(blank ? " " : "x");
+ stream.println("] Transforming section " + path);
+
+ Source source = new DOMSource(manual.document());
+ Result target = new StreamResult(out);
+
+ transformer.setParameter("sectionID", section.id());
+ transformer.setParameter("relativePath", relativePath);
+ transformer.setParameter("root", root);
+ transformer.transform(source, target);
+ }
out.close();
}
diff --git a/jOOQ-website/src/main/resources/html-page.xsl b/jOOQ-website/src/main/resources/html-page.xsl
index 8ce6573de7..a80c86650e 100644
--- a/jOOQ-website/src/main/resources/html-page.xsl
+++ b/jOOQ-website/src/main/resources/html-page.xsl
@@ -73,7 +73,13 @@ function printContent() {
+
+
+
+
+
+
#
diff --git a/jOOQ-website/src/main/resources/manual-3.0.xml b/jOOQ-website/src/main/resources/manual-3.0.xml
index ad32b317b8..7ff259d774 100644
--- a/jOOQ-website/src/main/resources/manual-3.0.xml
+++ b/jOOQ-website/src/main/resources/manual-3.0.xml
@@ -250,17 +250,21 @@ SELECT 1 FROM DUAL]]>
+// Whenever you see "create" being used in Java code, assume that this is an instance of org.jooq.DSLContext.
+// The reason why it is called "create" is the fact, that a jOOQ QueryPart is being created from the DSL object:
+DSLContext create = DSL.using(connection, SQLDialect.ORACLE);]]>
- Term: Degree (arity)
+
+ Your naming may differ, of course. For instance, you could name the "create" instance "db", instead.
+
+
+ Degree (arity)
jOOQ records (and many other API elements) have a degree N between 1 and {max-row-degree}. The variable degree of an API element is denoted as [N], e.g. Row[N] or Record[N]. The term "degree" is preferred over arity, as "degree" is the term used in the SQL standard, whereas "arity" is used more often in mathematics and relational theory.
@@ -745,7 +749,7 @@ INFO: GENERATION FINISHED! : Total: 791.688ms, +9.143ms
- result = create.select().from(POSTS).fetch();]]>
- First get an instance of Executor so we can write a simple SELECT query. We pass an instance of the MySQL connection to Executor. Note that the executor doesn't close the connection. We'll have to do that ourselves.
+ First get an instance of DSLContext so we can write a simple SELECT query. We pass an instance of the MySQL connection to DSL. Note that the DSLContext doesn't close the connection. We'll have to do that ourselves.
We then use jOOQ's DSL to return an instance of Result. We'll be using this result in the next step.
@@ -821,7 +825,7 @@ Result result = create.select().from(POSTS).fetch();]]>
// For convenience, always static import your generated tables and
// jOOQ functions to decrease verbosity:
import static test.generated.Tables.*;
-import static org.jooq.impl.Factory.*;
+import static org.jooq.impl.DSL.*;
import java.sql.*;
@@ -844,7 +848,7 @@ public class Main {
Class.forName("com.mysql.jdbc.Driver").newInstance();
conn = DriverManager.getConnection(url, userName, password);
- Executor create = new Executor(conn, SQLDialect.MYSQL);
+ DSLContext create = DSL.using(conn, SQLDialect.MYSQL);
Result result = create.select().from(POSTS).fetch();
for (Record r : result) {
@@ -949,14 +953,14 @@ import java.sql.DriverManager //
//
import org.jooq._ //
import org.jooq.impl._ //
-import org.jooq.impl.Factory._ //
+import org.jooq.impl.DSL._ //
import org.jooq.scala.example.h2.Tables._ //
import org.jooq.scala.Conversions._ // Import implicit defs for overloaded jOOQ/SQL operators
//
object Test { //
def main(args: Array[String]): Unit = { //
val c = DriverManager.getConnection("jdbc:h2:~/test", "sa", ""); // Standard JDBC connection
- val e = new Executor(c, SQLDialect.H2); //
+ val e = DSL.using(c, SQLDialect.H2); //
val x = T_AUTHOR as "x" // SQL-esque table aliasing
//
for (r <- e // Iteration over Result. "r" is an org.jooq.Record3
@@ -1085,8 +1089,12 @@ object Test { //
-
- The Factory class
+
+
+
+
+
+ The DSL type
jOOQ exposes a lot of interfaces and hides most implementation facts from client code. The reasons for this are:
@@ -1097,34 +1105,34 @@ object Test { //
API guarantee. You only depend on the exposed interfaces, not concrete (potentially dialect-specific) implementations.
- The class is the main class from where you will create all jOOQ objects. It serves as a static factory for , (or "fields"), and many other .
+ The class is the main class from where you will create all jOOQ objects. It serves as a static factory for , (or "fields"), and many other .
- The static Factory API
+ The static DSL API
- With jOOQ 2.0, static factory methods have been introduced in order to make client code look more like SQL. Ideally, when working with jOOQ, you will simply static import all methods from the Factory class:
+ With jOOQ 2.0, static factory methods have been introduced in order to make client code look more like SQL. Ideally, when working with jOOQ, you will simply static import all methods from the DSL class:
-import static org.jooq.impl.Factory.*;
+import static org.jooq.impl.DSL.*;
- Note, that when working with Eclipse, you could also add the Factory to your favourites. This will allow to access functions even more fluently:
+ Note, that when working with Eclipse, you could also add the DSL to your favourites. This will allow to access functions even more fluently:
concat(trim(FIRST_NAME), trim(LAST_NAME));
// ... which is in fact the same as:
-Factory.concat(Factory.trim(FIRST_NAME), Factory.trim(LAST_NAME));
+DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME));
-
- Factory subclasses
+
+ DSL subclasses
- There are a couple of subclasses for the general Factory. Each SQL dialect has its own dialect-specific Factory. For instance, if you're only using the MySQL dialect, you can choose to reference the MySQLFactory instead of the standard Factory:
+ There are a couple of subclasses for the general DSL. Each SQL dialect has its own dialect-specific DSL. For instance, if you're only using the MySQL dialect, you can choose to reference the MySQLDSL instead of the standard DSL:
- The advantage of referencing a dialect-specific Factory lies in the fact that you have access to more proprietary RDMBS functionality. This may include:
+ The advantage of referencing a dialect-specific DSL lies in the fact that you have access to more proprietary RDMBS functionality. This may include:
- MySQL's encryption functions
@@ -1134,42 +1142,79 @@ Factory.concat(Factory.trim(FIRST_NAME), Factory.trim(LAST_NAME));
+
+
+
+
+
+
+
+
+
-
- The Executor class
+
+ The DSLContext class
- Executor implements , an object that configures jOOQ's behaviour when executing queries (see for more details). Unlike Factories, Executors allow for creating that are already "configured" and ready for execution.
+ DSLContext references a , an object that configures jOOQ's behaviour when executing queries (see for more details). Unlike the static DSL, the DSLContext allow for creating that are already "configured" and ready for execution.
- The Executor as a Configuration object
+ Fluent creation of a DSLContext object
+
+ The DSLContext object can be created fluently from the :
+
+
+
+
+
+ If you do not have a reference to a pre-existing Configuration object (e.g. created from ), the various overloaded DSL.using() methods will create one for you.
+
+
+ Contents of a Configuration object
- As any Configuration object, an Executor can be supplied with these objects:
+ A Configuration can be supplied with these objects:
- : The dialect of your database. This may be any of the currently supported database types (see for more details)
- : An optional runtime configuration (see for more details)
- -
+
- : An optional reference to a provider class that can provide execute listeners to jOOQ (see for more details)
+ -
Any of these:
- - : An optional JDBC Connection that will be re-used for the whole lifecycle of your Executor (see for more details). For simplicity, this is the use-case referenced from this manual, most of the time.
- - : An optional JDBC DataSource that will be re-used for the whole lifecycle of your Executor. If you prefer using DataSources over Connections, jOOQ will internally fetch new Connections from your DataSource, conveniently closing them again after query execution. This is particularly useful in J2EE or Spring contexts (see for more details)
+ - : An optional JDBC Connection that will be re-used for the whole lifecycle of your Configuration (see for more details). For simplicity, this is the use-case referenced from this manual, most of the time.
+ - : An optional JDBC DataSource that will be re-used for the whole lifecycle of your Configuration. If you prefer using DataSources over Connections, jOOQ will internally fetch new Connections from your DataSource, conveniently closing them again after query execution. This is particularly useful in J2EE or Spring contexts (see for more details)
- : A custom abstraction that is used by jOOQ to "acquire" and "release" connections. jOOQ will internally "acquire" new Connections from your ConnectionProvider, conveniently "releasing" them again after query execution. (see for more details)
- As a Configuration object, an Executor can construct , for later . An example is given here:
+ Wrapping a Configuration object, a DSLContext can construct , for later . An example is given here:
- select = create.selectOne();
-// Using the internally referenced Executor, the select statement can now be executed:
+// Using the internally referenced Configuration, the select statement can now be executed:
Result> result = select.fetch();]]>
+
+
+ Note that you do not need to keep a reference to a DSLContext. You may as well inline your local variable, and fluently execute a SQL statement as such:
+
+
+ result =
+DSL.using(connection, dialect)
+ .select()
+ .from(BOOK)
+ .where(BOOK.TITLE.like("Animal%"))
+ .fetch();]]>
@@ -1180,7 +1225,7 @@ Result> result = select.fetch();]]>
While jOOQ tries to represent the SQL standard as much as possible, many features are vendor-specific to a given database and to its "SQL dialect". jOOQ models this using the enum type.
- The SQL dialect is one of the main attributes of an . Queries created from such executors will assume dialect-specific behaviour when and .
+ The SQL dialect is one of the main attributes of a . Queries created from DSLContexts will assume dialect-specific behaviour when and .
Some parts of the jOOQ API are officially supported only by a given subset of the supported SQL dialects. For instance, the , which is supported by the Oracle and CUBRID databases, is annotated with a annotation, as such:
@@ -1233,7 +1278,7 @@ SelectSelectStep select(Field>... fields);]]>
Interact with JDBC Connections
- While you can use jOOQ for only, you can also run queries against a JDBC . Internally, jOOQ creates or objects from such a Connection, in order to execute statements. The normal operation mode is to provide an with a JDBC Connection, whose lifecycle you will control yourself. This means that jOOQ will not actively close connections, rollback or commit transactions.
+ While you can use jOOQ for only, you can also run queries against a JDBC . Internally, jOOQ creates or objects from such a Connection, in order to execute statements. The normal operation mode is to provide a with a JDBC Connection, whose lifecycle you will control yourself. This means that jOOQ will not actively close connections, rollback or commit transactions.
Note, in this case, jOOQ will internally use a , which you can reference directly if you prefer that. The DefaultConnectionProvider exposes various transaction-control methods, such as commit(), rollback(), etc.
@@ -1271,7 +1316,7 @@ SelectSelectStep select(Field>... fields);]]>
Custom data
- In advanced use cases of integrating your application with jOOQ, you may want to put custom data into your , which you can then access from your...
+ In advanced use cases of integrating your application with jOOQ, you may want to put custom data into your , which you can then access from your...
@@ -1290,7 +1335,7 @@ public class NoInsertListener extends DefaultExecuteListener {
public void start(ExecuteContext ctx) {
// This listener is active only, when your custom flag is set to true
- if (Boolean.TRUE.equals(ctx.getData("com.example.my-namespace.no-inserts"))) {
+ if (Boolean.TRUE.equals(ctx.configuration().data("com.example.my-namespace.no-inserts"))) {
// If active, fail this execution, if an INSERT statement is being executed
if (ctx.query() instanceof Insert) {
@@ -1304,23 +1349,24 @@ public class NoInsertListener extends DefaultExecuteListener {
- Now, the above listener can be added to your , but you will also need to pass the flag to the Executor, in order for the listener to work:
+ Now, the above listener can be added to your , but you will also need to pass the flag to the Configuration, in order for the listener to work:
-
- Using the getData() and setData() methods, you can store and retrieve custom data in your Executors and Configurations.
+ Using the data() methods, you can store and retrieve custom data in your Configurations.
@@ -1352,11 +1398,11 @@ catch (DataAccessException expected) {
- ExecuteListeners are hooked into your by adding them to the getExecuteListeners() property:
+ ExecuteListeners are hooked into your by returning them from a :
-
Custom Settings
- The jOOQ Executor allows for some optional configuration elements to be used by advanced users. The class is a JAXB-annotated type, that can be provided to an Executor in several ways:
+ The jOOQ Configuration allows for some optional configuration elements to be used by advanced users. The class is a JAXB-annotated type, that can be provided to a Configuration in several ways:
- - In the constructor. This will override default settings below
- - From a location specified by a JVM parameter: -Dorg.jooq.settings
+ - In the DSLContext constructor (
DSL.using()). This will override default settings below
+ - in the constructor. This will override default settings below
+ - From a location specified by a JVM parameter: -Dorg.jooq.settings
- From the classpath at /jooq-settings.xml
- From the settings defaults, as specified in http://www.jooq.org/xsd/jooq-runtime-{runtime-xsd-version}.xsd
Example
- For example, if you want to indicate to jOOQ, that it should inline all bind variables, and execute static instead of binding its variables to , you can do so by using the following Executor:
+ For example, if you want to indicate to jOOQ, that it should inline all bind variables, and execute static instead of binding its variables to , you can do so by creating the following DSLContext:
+DSLContext create = DSL.using(connection, dialect, settings);]]>
Subsequent sections of the manual contain some more in-depth explanations about these settings:
@@ -1428,7 +1475,7 @@ Executor create = new Executor(connection, dialect, settings);]]>
Mapping DEV to MY_BOOK_WORLD with jOOQ
- When a user from My Book World logs in, you want them to access the MY_BOOK_WORLD schema using classes generated from DEV. This can be achieved with the class, that you can equip your Executor's with. Take the following example:
+ When a user from My Book World logs in, you want them to access the MY_BOOK_WORLD schema using classes generated from DEV. This can be achieved with the class, that you can equip your Configuration's with. Take the following example:
Settings settings = new Settings()
@@ -1437,14 +1484,14 @@ Executor create = new Executor(connection, dialect, settings);]]>
new MappedSchema().withInput("DEV")
.withOutput("MY_BOOK_WORLD")));
-// Add the settings to the executor
-Executor create = new Executor(connection, SQLDialect.ORACLE, settings);
+// Add the settings to the DSLContext
+DSLContext create = DSL.using(connection, SQLDialect.ORACLE, settings);
-// Run queries with the "mapped" executor
+// Run queries with the "mapped" Configuration
create.selectFrom(AUTHOR).fetch();
- The query executed with an Executor equipped with the above mapping will in fact produce this SQL statement:
+ The query executed with a Configuration equipped with the above mapping will in fact produce this SQL statement:
SELECT * FROM MY_BOOK_WORLD.AUTHOR
@@ -1479,29 +1526,11 @@ create.selectFrom(AUTHOR).fetch();
Settings settings = JAXB.unmarshal(new File("jooq-runtime.xml"), Settings.class);
- This will map generated classes from DEV to MY_BOOK_WORLD, from LOG to MY_BOOK_WORLD_LOG, but leave the MASTER schema alone. Whenever you want to change your mapping configuration, you will have to create a new Executor.
+ This will map generated classes from DEV to MY_BOOK_WORLD, from LOG to MY_BOOK_WORLD_LOG, but leave the MASTER schema alone. Whenever you want to change your mapping configuration, you will have to create a new Configuration.
Using a default schema
-
- Another option to switch schema names is to use a default schema for the Executor's underlying Connection. Many RDBMS support a USE or SET SCHEMA command, which you can call like this:
-
-
-// Set the default schema
-Schema MY_BOOK_WORLD = ...
-create.use(MY_BOOK_WORLD);
-
-// Run queries with an executor having a default schema
-create.selectFrom(AUTHOR).fetch();
-
-
- Queries generated from the above Executor will produce this kind of SQL statement:
-
-
--- the schema name is omitted from all SQL constructs.
-SELECT * FROM AUTHOR
-
If you wish not to render any schema name at all, use the following Settings property for this:
@@ -1510,8 +1539,8 @@ SELECT * FROM AUTHOR
Settings settings = new Settings()
.withRenderSchema(false);
-// Add the settings to the executor
-Executor create = new Executor(connection, SQLDialect.ORACLE, settings);
+// Add the settings to the Configuration
+DSLContext create = DSL.using(connection, SQLDialect.ORACLE, settings);
// Run queries that omit rendering schema names
create.selectFrom(AUTHOR).fetch();
@@ -1530,14 +1559,14 @@ create.selectFrom(AUTHOR).fetch();
new MappedTable().withInput("AUTHOR")
.withOutput("MY_APP__AUTHOR"))));
-// Add the settings to the executor
-Executor create = new Executor(connection, SQLDialect.ORACLE, settings);
+// Add the settings to the Configuration
+DSLContext create = DSL.using(connection, SQLDialect.ORACLE, settings);
-// Run queries with the "mapped" executor
+// Run queries with the "mapped" configuration
create.selectFrom(AUTHOR).fetch();
- The query executed with an Executor equipped with the above mapping will in fact produce this SQL statement:
+ The query executed with a Configuration equipped with the above mapping will in fact produce this SQL statement:
SELECT * FROM MY_BOOK_WORLD.MY_APP__AUTHOR
@@ -1559,7 +1588,7 @@ create.selectFrom(AUTHOR).fetch();
SQL Statements
- jOOQ currently supports 6 types of SQL statements. All of these statements are constructed from an Executor instance with an optional . If supplied with a Connection or DataSource, they can be executed. Depending on the , executed queries can return results.
+ jOOQ currently supports 6 types of SQL statements. All of these statements are constructed from a DSLContext instance with an optional . If supplied with a Connection or DataSource, they can be executed. Depending on the , executed queries can return results.
@@ -1600,7 +1629,7 @@ create.select()
Many other frameworks have similar APIs with similar feature sets. Yet, what makes jOOQ special is its informal modelling a unified SQL dialect suitable for many vendor-specific dialects, and implementing that BNF notation as a hierarchy of interfaces in Java. This concept is extremely powerful, when with syntax completion. Not only can you code much faster, your SQL code will be compile-checked to a certain extent. An example of a DSL query equivalent to the previous one is given here:
- result = create.select()
.from(AUTHOR)
.join(BOOK).on(BOOK.AUTHOR_ID.equal(AUTHOR.ID))
@@ -1609,7 +1638,7 @@ Result> result = create.select()
Unlike other, simpler frameworks that use "fluent APIs" or "method chaining", jOOQ's BNF-based interface hierarchy will not allow bad query syntax. The following will not compile, for instance:
- result = create.select()
.join(BOOK).on(BOOK.AUTHOR_ID.equal(AUTHOR.ID))
// ^^^^ "join" is not possible here
@@ -1646,7 +1675,7 @@ Result> result = create.select()
Historically, jOOQ started out as an object-oriented SQL builder library like any other. This meant that all queries and their syntactic components were modeled as so-called , which delegate and to child components. This part of the API will be referred to as the model API (or non-DSL API), which is still maintained and used internally by jOOQ for incremental query building. An example of incremental query building is given here:
- query = create.selectQuery();
query.addFrom(AUTHOR);
@@ -1661,7 +1690,7 @@ Result> result = query.fetch();]]>
This query is equivalent to the one shown before using the DSL syntax. In fact, internally, the DSL API constructs precisely this SelectQuery object. Note, that you can always access the SelectQuery object to switch between DSL and model APIs:
- select = create.select().from(AUTHOR);
// Add the JOIN clause on the internal QueryObject representation
@@ -1730,7 +1759,7 @@ ORDER BY AUTHOR.LAST_NAME ASC NULLS FIRST
-Executor create = new Executor(connection, dialect);
+DSLContext create = DSL.using(connection, dialect);
create.select(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, count())
.from(AUTHOR)
@@ -1751,7 +1780,7 @@ create.select(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, count())
SELECT from single physical tables
- A very similar, but limited API is available, if you want to select from single physical tables in order to retrieve . The decision, which type of select to create is already made at the very first step, when you create the SELECT statement with the Factory or Executor:
+ A very similar, but limited API is available, if you want to select from single physical tables in order to retrieve . The decision, which type of select to create is already made at the very first step, when you create the SELECT statement with the DSL or DSLContext types:
SelectWhereStep selectFrom(Table table);]]>
@@ -1780,7 +1809,7 @@ create.select(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, count())
The SELECT clause
- The SELECT clause lets you project your own record types, referencing table fields, functions, arithmetic expressions, etc. The Factory provides several methods for expressing a SELECT clause:
+ The SELECT clause lets you project your own record types, referencing table fields, functions, arithmetic expressions, etc. The DSL type provides several methods for expressing a SELECT clause:
@@ -1840,7 +1869,7 @@ create.select().from(tableByName("BOOK"));]]>
Typesafe projections with degree up to {max-row-degree}
- Since jOOQ 3.0, and up to degree {max-row-degree} are now generically typesafe. This is reflected by an overloaded SELECT (and SELECT DISTINCT) API in both Factory and Executor. An extract from Factory:
+ Since jOOQ 3.0, and up to degree {max-row-degree} are now generically typesafe. This is reflected by an overloaded SELECT (and SELECT DISTINCT) API in both DSL and DSLContext. An extract from the DSL type:
-
+
@@ -1942,7 +1971,7 @@ new Executor(SQLDialect.POSTGRES).selectOne().getSQL();]]>
All of these JOIN methods can be called on types, or directly after the FROM clause for convenience. The following example joins AUTHOR and BOOK
- result = create.select()
@@ -2150,7 +2179,7 @@ ORDER BY 1]]>
- Some of the supported functions and pseudo-columns are these (available from the ):
+ Some of the supported functions and pseudo-columns are these (available from the ):
@@ -3529,20 +3558,20 @@ SELECT 1
SELECT 1
SELECT 1 FROM [SYS].[DUMMY]
]]>
-
+
@@ -3562,13 +3591,13 @@ new Executor(SQLDialect.SYBASE ).selectOne().getSQL();]]>
Using column expressions in jOOQ
- jOOQ allows you to freely create arbitrary column expressions using a fluent expression construction API. Many expressions can be formed as functions from , other expressions can be formed based on a pre-existing column expression. For example:
+ jOOQ allows you to freely create arbitrary column expressions using a fluent expression construction API. Many expressions can be formed as functions from , other expressions can be formed based on a pre-existing column expression. For example:
field1 = BOOK.TITLE;
-// A function created from the Factory using "prefix" notation
+// A function created from the DSL using "prefix" notation
Field field2 = trim(BOOK.TITLE);
// The same function created from a pre-existing Field using "postfix" notation
@@ -3580,7 +3609,7 @@ Field field4 = listAgg(BOOK.TITLE)
.over().partitionBy(AUTHOR.ID);]]>
- In general, it is up to you whether you want to use the "prefix" notation or the "postfix" notation to create new column expressions based on existing ones. The "SQL way" would be to use the "prefix notation", with functions created from the . The "Java way" or "object-oriented way" would be to use the "postfix" notation with functions created from objects. Both ways ultimately create the same query part, though.
+ In general, it is up to you whether you want to use the "prefix" notation or the "postfix" notation to create new column expressions based on existing ones. The "SQL way" would be to use the "prefix notation", with functions created from the . The "Java way" or "object-oriented way" would be to use the "postfix" notation with functions created from objects. Both ways ultimately create the same query part, though.
@@ -3687,8 +3716,8 @@ SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL
Field cast(Class extends Z> type);
}
-// And additional convenience methods in the Factory:
-public class Factory {
+// And additional convenience methods in the DSL:
+public class DSL {
Field cast(Object object, Field field);
Field cast(Object object, DataType type);
Field cast(Object object, Class extends T> type);
@@ -3732,7 +3761,7 @@ public class Factory {
- For more advanced datetime arithmetic, use the Factory's timestampDiff() and dateDiff() functions, as well as jOOQ's built-in SQL standard INTERVAL data type support:
+ For more advanced datetime arithmetic, use the DSL's timestampDiff() and dateDiff() functions, as well as jOOQ's built-in SQL standard INTERVAL data type support:
INTERVAL YEAR TO MONTH:
@@ -3767,7 +3796,7 @@ create.select(concat("A", "B", "C"));
There are a variety of general functions supported by jOOQ As discussed in the chapter about functions are mostly simulated in your database, in case they are not natively supported.
- This is a list of general functions supported by jOOQ's :
+ This is a list of general functions supported by jOOQ's :
COALESCE: Get the first non-null value in a list of arguments.
@@ -3777,7 +3806,7 @@ create.select(concat("A", "B", "C"));
- Please refer to the for more details.
+ Please refer to the for more details.
@@ -3789,7 +3818,7 @@ create.select(concat("A", "B", "C"));
Math can be done efficiently in the database before returning results to your Java application. In addition to the discussed previously, jOOQ also supports a variety of numeric functions. As discussed in the chapter about numeric functions (as any function type) are mostly simulated in your database, in case they are not natively supported.
- This is a list of numeric functions supported by jOOQ's :
+ This is a list of numeric functions supported by jOOQ's :
@@ -3824,7 +3853,7 @@ create.select(concat("A", "B", "C"));
- Please refer to the for more details.
+ Please refer to the for more details.
@@ -3864,7 +3893,7 @@ create.select(concat("A", "B", "C"));
String formatting can be done efficiently in the database before returning results to your Java application. As discussed in the chapter about string functions (as any function type) are mostly simulated in your database, in case they are not natively supported.
- This is a list of numeric functions supported by jOOQ's :
+ This is a list of numeric functions supported by jOOQ's :
@@ -3889,7 +3918,7 @@ create.select(concat("A", "B", "C"));
- Please refer to the for more details.
+ Please refer to the for more details.
Regular expressions, REGEXP, REGEXP_LIKE, etc.
@@ -3900,7 +3929,7 @@ create.select(concat("A", "B", "C"));
- Note that the SQL standard specifies that patterns should follow the XQuery standards. In the real world, the POSIX regular expression standard is the most used one, some use Java regular expressions, and only a few ones use Perl regular expressions. jOOQ does not make any assumptions about regular expression syntax. For cross-database compatibility, please read the relevant databaes manuals carefully, to learn about the appropriate syntax. Please refer to the for more details.
+ Note that the SQL standard specifies that patterns should follow the XQuery standards. In the real world, the POSIX regular expression standard is the most used one, some use Java regular expressions, and only a few ones use Perl regular expressions. jOOQ does not make any assumptions about regular expression syntax. For cross-database compatibility, please read the relevant databaes manuals carefully, to learn about the appropriate syntax. Please refer to the for more details.
@@ -3910,7 +3939,7 @@ create.select(concat("A", "B", "C"));
Date and time functions
- This is a list of date and time functions supported by jOOQ's :
+ This is a list of date and time functions supported by jOOQ's :
@@ -3934,7 +3963,7 @@ create.select(concat("A", "B", "C"));
System functions
- This is a list of system functions supported by jOOQ's :
+ This is a list of system functions supported by jOOQ's :
CURRENT_USER: Get current user.
@@ -3946,7 +3975,7 @@ create.select(concat("A", "B", "C"));
Aggregate functions
- Aggregate functions work just like functions, even if they have a slightly different semantics. Here are some example aggregate functions from the :
+ Aggregate functions work just like functions, even if they have a slightly different semantics. Here are some example aggregate functions from the :
Most major RDBMS support the concept of window functions. jOOQ knows of implementations in DB2, Oracle, Postgres, SQL Server, and Sybase SQL Anywhere, and supports most of their specific syntaxes. Note, that H2 and HSQLDB have implemented ROW_NUMBER() functions, without true windowing support.
- As previously discussed, any can be transformed into a window function using the over() method. See the chapter about for details. In addition to those, there are also some more window functions supported by jOOQ, as declared in the :
+ As previously discussed, any can be transformed into a window function using the over() method. See the chapter about for details. In addition to those, there are also some more window functions supported by jOOQ, as declared in the :
jOOQ's support for ROLLUP(), CUBE(), GROUPING SETS()
- jOOQ fully supports all of these functions, as well as the utility functions GROUPING() and GROUPING_ID(), used for identifying the grouping set ID of a record. The thus includes:
+ jOOQ fully supports all of these functions, as well as the utility functions GROUPING() and GROUPING_ID(), used for identifying the grouping set ID of a record. The thus includes:
Tuples or row value expressions
- According to the SQL standard, row value expressions can have a degree of more than one. This is commonly used in the , where the VALUES row value constructor allows for providing a row value expression as a source for INSERT data. Row value expressions can appear in various other places, though. They are supported by jOOQ as records / rows. jOOQ's allows for the construction of type-safe records up to the degree of {max-row-degree}. Higher-degree Rows are supported as well, but without any type-safety. Row types are modelled as follows:
+ According to the SQL standard, row value expressions can have a degree of more than one. This is commonly used in the , where the VALUES row value constructor allows for providing a row value expression as a source for INSERT data. Row value expressions can appear in various other places, though. They are supported by jOOQ as records / rows. jOOQ's allows for the construction of type-safe records up to the degree of {max-row-degree}. Higher-degree Rows are supported as well, but without any type-safety. Row types are modelled as follows:
- Row1 row(T1 t1) { ... }
public static Row2 row(T1 t1, T2 t2) { ... }
public static Row3 row(T1 t1, T2 t2, T3 t3) { ... }
@@ -4688,9 +4717,9 @@ TITLE != 'Animal Farm']]>
BOOK.TITLE.notEqual("Animal Farm")]]>
- Create conditions from the Factory
+ Create conditions from the DSL
- There are a few types of conditions, that can be created statically from the . These are:
+ There are a few types of conditions, that can be created statically from the . These are:
- , that allow you to phrase your own SQL string
@@ -4759,7 +4788,7 @@ orExists(Select>) // Combine conditions with OR. Convenience for adding
orNot(Condition) // Combine conditions with OR. Convenience for adding an inverted condition to the rhs
orNotExists(Select>) // Combine conditions with OR. Convenience for adding an inverted exists predicate to the rhs
-not() // Invert a condition (synonym for Factory.not(Condition)]]>
+not() // Invert a condition (synonym for DSL.not(Condition)]]>
@@ -5270,7 +5299,7 @@ NULL -- [ANY] AND NULL yields NULL
Slightly less intuitive, yet more powerful than the previously discussed is the EXISTS predicate, that can be used to form semi-joins or anti-joins. With jOOQ, the EXISTS predicate can be formed in various ways:
- - From the , using static methods. This is probably the most used case
+ - From the , using static methods. This is probably the most used case
- From a using
- From a using , and from other clauses
@@ -5291,7 +5320,7 @@ notExists(create.selectOne().from(BOOK)
- Note that in SQL, the projection of a subselect in an EXISTS predicate is irrelevant. To help you write queries like the above, you can use jOOQ's selectZero() or selectOne() methods
+ Note that in SQL, the projection of a subselect in an EXISTS predicate is irrelevant. To help you write queries like the above, you can use jOOQ's selectZero() or selectOne() methods
Performance of IN vs. EXISTS
@@ -5377,7 +5406,7 @@ row(Date.valueOf('2010-01-01'), new DayToSecond(2)).overlaps(Date.valueOf('2010-
- Plain SQL as a
- The Factory plain SQL API
+ The DSL plain SQL API
Plain SQL API methods are usually overloaded in three ways. Let's look at the condition query part constructor:
@@ -5394,7 +5423,7 @@ Condition condition(String sql, Object... bindings);
Condition condition(String sql, QueryPart... parts);]]>
- Please refer to the Javadoc for more details. The following is a more complete listing of plain SQL construction methods from the Factory:
+ Please refer to the Javadoc for more details. The following is a more complete listing of plain SQL construction methods from the DSL:
create.select().from(BOOK).where(BOOK.ID.equal(val(5))).and(BOOK.TITLE.equal(val("Animal Farm")));]]>
- Note the using of to explicitly create an indexed bind value. You don't have to worry about that index. When the query is , each bind value will render a question mark. When the query , each bind value will generate the appropriate bind value index.
+ Note the using of to explicitly create an indexed bind value. You don't have to worry about that index. When the query is , each bind value will render a question mark. When the query , each bind value will generate the appropriate bind value index.
Extract bind values from a query
@@ -5608,7 +5637,7 @@ Query query2 = create.select().from(AUTHOR).where(LAST_NAME.equal(param("lastNam
query2.bind("lastName", "Orwell");]]>
- In order to actually render named parameter names in generated SQL, use the method:
+ In order to actually render named parameter names in generated SQL, use the method:
@@ -5634,10 +5663,10 @@ WHERE LAST_NAME = :lastName]]>
-
- By using the and setting the to STATIC_STATEMENT. This will inline all bind values for SQL statements rendered from such an Executor.
+ By using the and setting the to STATIC_STATEMENT. This will inline all bind values for SQL statements rendered from such a Configuration.
-
- By using methods.
+ By using methods.
@@ -5657,8 +5686,8 @@ create.select()
Settings settings = new Settings()
.withStatementType(StatementType.STATIC_STATEMENT);
-// Add the settings to the executor
-Executor create = new Executor(connection, SQLDialect.ORACLE, settings);
+// Add the settings to the Configuration
+DSLContext create = DSL.using(connection, SQLDialect.ORACLE, settings);
// Run queries that omit rendering schema names
create.select()
@@ -5818,11 +5847,11 @@ public final void toSQL(RenderContext context) {
-
+
- And then, use the above factory to render pretty-printed SQL:
+ And then, use the above DSLContext to render pretty-printed SQL:
@@ -5964,7 +5993,7 @@ final Field IDx2 = new CustomField(BOOK.ID.getName(), BOOK.ID.
context.statement().setInt(context.nextIndex(), 2);
// Alternatively, you could also write:
- // context.bind(Factory.val(2));
+ // context.bind(DSL.val(2));
}
catch (SQLException e) {
throw translate(getSQL(), e);
@@ -6010,7 +6039,7 @@ create.selectFrom(BOOK).where("BOOK.ID = {0} AND TITLE = {1}", id, title);]]>Serializability
- The only transient, non-serializable element in any jOOQ object is the underlying . When you want to execute queries after de-serialisation, or when you want to store/refresh/delete , you will have to "re-attach" them to an Executor
+ The only transient, non-serializable element in any jOOQ object is the underlying . When you want to execute queries after de-serialisation, or when you want to store/refresh/delete , you may have to "re-attach" them to a Configuration
select = (Select>) in.readObject();
select.execute();
// In order to execute the above select, attach it first
-Executor create = new Executor(connection, SQLDialect.ORACLE);
+DSLContext create = DSL.using(connection, SQLDialect.ORACLE);
create.attach(select);]]>
Automatically attaching QueryParts
@@ -6398,7 +6427,7 @@ System.out.println("Title : " + book.getTitle());
System.out.println("Published in: " + book.getPublishedIn());]]>
- When you use the method, jOOQ will return the record type supplied with the argument table. Beware though, that you will no longer be able to use any clause that modifies the type of your . This includes:
+ When you use the method, jOOQ will return the record type supplied with the argument table. Beware though, that you will no longer be able to use any clause that modifies the type of your . This includes:
@@ -6546,7 +6575,7 @@ create.selectFrom(BOOK)
POJOs
- Fetching data in records is fine as long as your application is not really layered, or as long as you're still writing code in the DAO layer. But if you have a more advanced application architecture, you may not want to allow for jOOQ artefacts to leak into other layers. You may choose to write POJOs (Plain Old Java Objects) as your primary DTOs (Data Transfer Objects), without any dependencies on jOOQ's types, which may even potentially hold a reference to a , and thus a JDBC . Like Hibernate/JPA, jOOQ allows you to operate with POJOs. Unlike Hibernate/JPA, jOOQ does not "attach" those POJOs or create proxies with any magic in them.
+ Fetching data in records is fine as long as your application is not really layered, or as long as you're still writing code in the DAO layer. But if you have a more advanced application architecture, you may not want to allow for jOOQ artefacts to leak into other layers. You may choose to write POJOs (Plain Old Java Objects) as your primary DTOs (Data Transfer Objects), without any dependencies on jOOQ's types, which may even potentially hold a reference to a , and thus a JDBC . Like Hibernate/JPA, jOOQ allows you to operate with POJOs. Unlike Hibernate/JPA, jOOQ does not "attach" those POJOs or create proxies with any magic in them.
If you're using jOOQ's , you can configure it to for you, but you're not required to use those generated POJOs. You can use your own.
@@ -6699,11 +6728,11 @@ create.executeUpdate(book);]]>
If you're using jOOQ's , you can configure it to for you. Those DAOs operate on . An example of using such a DAO is given here:
- r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)
With JDBC, you have full control over your SQL statements. You can decide yourself, if you want to execute a static without bind values, or a with (or without) bind values. But you have to decide early, which way to go. And you'll have to prevent SQL injection and syntax errors manually, when inlining your bind variables.
- With jOOQ, this is easier. As a matter of fact, it is plain simple. With jOOQ, you can just set a flag in your , and all queries produced by that executor will be executed as static statements, with all bind values inlined. An example is given here:
+ With jOOQ, this is easier. As a matter of fact, it is plain simple. With jOOQ, you can just set a flag in your , and all queries produced by that configuration will be executed as static statements, with all bind values inlined. An example is given here:
@@ -7085,11 +7114,11 @@ Result> r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)
-- These statements are rendered by the two factories:
SELECT ? FROM DUAL WHERE ? = ?
SELECT 1 FROM DUAL WHERE 1 = 1]]>
-
Inlining bind values on a per-bind-value basis
- Note that you don't have to inline all your bind values at once. If you know that a bind value is not really a variable and should be inlined explicitly, you can do so by using , as documented in the manual's section about
+ Note that you don't have to inline all your bind values at once. If you know that a bind value is not really a variable and should be inlined explicitly, you can do so by using , as documented in the manual's section about
@@ -7250,7 +7279,7 @@ create.batch(create.insertInto(AUTHOR, ID, NAME).values("?", "?"))
Standalone calls to sequences
- Instead of actually phrasing a select statement, you can also use the convenience methods:
+ Instead of actually phrasing a select statement, you can also use the convenience methods:
These member functions and procedures can simply be mapped to Java methods:
-
With jOOQ, you can load this data using various parameters from the loader API. A simple load may look like this:
-Executor create = new Executor(connection, dialect);
+DSLContext create = DSL.using(connection, dialect);
// Load data into the AUTHOR table from an input stream
// holding the CSV data.
@@ -7779,7 +7808,7 @@ DELETE FROM BOOK WHERE ID = 5;]]>
Simple CRUD
- If you're using jOOQ's , it will generate implementations for every table that has a primary key. When such a record form the database, these records are "attached" to the that created them. This means that they hold an internal reference to the same database connection that was used to fetch them. This connection is used internally by any of the following methods of the UpdatableRecord:
+ If you're using jOOQ's , it will generate implementations for every table that has a primary key. When such a record form the database, these records are "attached" to the that created them. This means that they hold an internal reference to the same database connection that was used to fetch them. This connection is used internally by any of the following methods of the UpdatableRecord:
CRUD and SELECT statements
- CRUD operations can be combined with regular querying, if you select records from single database tables, as explained in the manual's section about . For this, you will need to use the selectFrom() method from the :
+ CRUD operations can be combined with regular querying, if you select records from single database tables, as explained in the manual's section about . For this, you will need to use the selectFrom() method from the :
books = author.fetchChildren(FK_BOOK_AUTHOR);]]>
The above changes to jOOQ's behaviour are transparent to the API, the only thing you need to do for it to be activated is to set the Settings flag. Here is an example illustrating optimistic locking:
-
The MODIFIED column will contain a timestamp indicating the last modification timestamp for any book in the BOOK table. If you're using jOOQ and it's , jOOQ will then generate this TIMESTAMP value for you, automatically. However, instead of running an additional statement prior to an UPDATE or DELETE statement, jOOQ adds a WHERE-clause to the UPDATE or DELETE statement, checking for TIMESTAMP's integrity. This can be best illustrated with an example:
-
Batch execution
- When inserting, updating, deleting a lot of records, you may wish to profit from JDBC batch operations, which can be performed by jOOQ. These are available through jOOQ's as shown in the following example:
+ When inserting, updating, deleting a lot of records, you may wish to profit from JDBC batch operations, which can be performed by jOOQ. These are available through jOOQ's as shown in the following example:
{
Note that you can further subtype those pre-generated DAO classes, to add more useful DAO methods to them. Using such a DAO is simple:
-
ExecuteListeners
- The lets you specify a list of instances. The ExecuteListener is essentially an event listener for Query, Routine, or ResultSet render, prepare, bind, execute, fetch steps. It is a base type for loggers, debuggers, profilers, data collectors, triggers, etc. Advanced ExecuteListeners can also provide custom implementations of Connection, PreparedStatement and ResultSet to jOOQ in apropriate methods.
+ The lets you specify a list of instances. The ExecuteListener is essentially an event listener for Query, Routine, or ResultSet render, prepare, bind, execute, fetch steps. It is a base type for loggers, debuggers, profilers, data collectors, triggers, etc. Advanced ExecuteListeners can also provide custom implementations of Connection, PreparedStatement and ResultSet to jOOQ in apropriate methods.
For convenience and better backwards-compatibility, consider extending instead of implementing this interface.
@@ -8286,7 +8315,7 @@ public class StatisticsListener extends DefaultExecuteListener {
Now, configure jOOQ's runtime to load your listener
-
@@ -8321,10 +8350,10 @@ for (ExecuteType type : ExecuteType.values()) {
The following depicts an example of a custom ExecuteListener, which pretty-prints all queries being executed by jOOQ to stdout:
-Logging
- jOOQ logs all SQL queries and fetched result sets to its internal DEBUG logger, which is implemented as an . By default, execute logging is activated in the . In order to see any DEBUG log output, put either log4j or slf4j on jOOQ's classpath along with their respective configuration. A sample log4j configuration can be seen here:
+ jOOQ logs all SQL queries and fetched result sets to its internal DEBUG logger, which is implemented as an . By default, execute logging is activated in the . In order to see any DEBUG log output, put either log4j or slf4j on jOOQ's classpath along with their respective configuration. A sample log4j configuration can be seen here:
@@ -8438,10 +8467,10 @@ Finishing : Total: 4.814ms, +3.375ms
Performance considerations
- Many users may have switched from higher-level abstractions such as Hibernate to jOOQ, because of Hibernate's hard-to-manage performance, when it comes to large database schemas and complex second-level caching strategies. jOOQ is not a lightweight database abstraction framework, and it comes with its own overhead. Please be sure to consider the following points:
+ Many users may have switched from higher-level abstractions such as Hibernate to jOOQ, because of Hibernate's difficult-to-manage performance, when it comes to large database schemas and complex second-level caching strategies. However, jOOQ itself is not a lightweight database abstraction framework, and it comes with its own overhead. Please be sure to consider the following points:
- - It takes some time to construct jOOQ queries. If you can reuse the same queries, you might cache them. Beware of thread-safety issues, though, as jOOQ's is not threadsafe, and queries are "attached" to their creating Executor
+ - It takes some time to construct jOOQ queries. If you can reuse the same queries, you might cache them. Beware of thread-safety issues, though, as jOOQ's is not necessarily threadsafe, and queries are "attached" to their creating DSLContext
- It takes some time to render SQL strings. Internally, jOOQ reuses the same for the complete query, but some rendering elements may take their time. You could, of course, cache SQL generated by jOOQ and prepare your own objects
- It takes some time to bind values to prepared statements. jOOQ does not keep any open prepared statements, internally. Use a sophisticated connection pool, that will cache prepared statements and inject them into jOOQ through the standard JDBC API
- It takes some time to fetch results. By default, jOOQ will always fetch the complete into memory. Use to prevent that, and scroll over an open underlying database cursor
@@ -9288,8 +9317,8 @@ public class Book implements java.io.Serializable
super(BOOK, Book.class);
}
- public BookDao(Executor executor) {
- super(BOOK, Book.class, executor);
+ public BookDao(Configuration configuration) {
+ super(BOOK, Book.class, configuration);
}
// Every column generates at least one fetch method
@@ -9569,17 +9598,17 @@ create.selectFrom(AUTHOR)
Using jOOQ's own mock API
- This work is greatly simplified, when using jOOQ's own mock API. The org.jooq.tools.jdbc package contains all the essential implementations for both JDBC 4.0 and 4.1, which are needed to mock JDBC for jOOQ. In order to write mock tests, provide the jOOQ with a , and implement the :
+ This work is greatly simplified, when using jOOQ's own mock API. The org.jooq.tools.jdbc package contains all the essential implementations for both JDBC 4.0 and 4.1, which are needed to mock JDBC for jOOQ. In order to write mock tests, provide the jOOQ with a , and implement the :
result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetch();]]>
@@ -9609,8 +9638,8 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
@Override
public MockResult[] execute(MockExecuteContext ctx) throws SQLException {
- // You might need an executor to create org.jooq.Result and org.jooq.Record objects
- Executor create = new Executor(SQLDialect.ORACLE);
+ // You might need a DSLContext to create org.jooq.Result and org.jooq.Record objects
+ DSLContext create = DSL.using(SQLDialect.ORACLE);
MockResult[] mock = new MockResult[1];
// The execute context contains SQL string(s), bind values, and other meta-data
@@ -9698,10 +9727,10 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
- Both modes will require that you set the in the Executor's configuration:
+ Both modes will require that you set the in the Configuration:
-
In-process mode
@@ -10135,7 +10164,7 @@ for (Record record : create().select(
- [N] in Row[N] has been raised from 8 to 22. This means that existing row value expressions with degree >= 9 are now type-safe
- - Subqueries returned from
Factory.select(...) now implement Select<Record[N]>, not Select<Record>
+ - Subqueries returned from
DSL.select(...) now implement Select<Record[N]>, not Select<Record>
IN predicates and comparison predicates taking subselects changed incompatibly
INSERT and MERGE statements now take typesafe VALUES() clauses
@@ -10162,18 +10191,18 @@ Result> result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch();]]>
- Query building vs. query execution
+ Factory was split into DSL (query building) and DSLContext (query execution)
The pre-existing Factory class has been split into two parts:
- - The Factory: This class contains only static factory methods. All QueryParts constructed from this class are "unattached", i.e. queries that are constructed through a Factory cannot be executed immediately. This is useful for subqueries.
- - The Executor: This class holds a reference to a Configuration and can construct executable ("attached") QueryParts.
+ - The DSL: This class contains only static factory methods. All QueryParts constructed from this class are "unattached", i.e. queries that are constructed through DSL cannot be executed immediately. This is useful for subqueries.
The DSL class corresponds to the static part of the jOOQ 2.x Factory type
+ - The DSLContext: This type holds a reference to a Configuration and can construct executable ("attached") QueryParts.
The DSLContext type corresponds to the non-static part of the jOOQ 2.x Factory / FactoryOperations type.
- The FactoryOperations interface has been removed entirely. An example:
+ The FactoryOperations interface has been renamed to DSLContext. An example:
Quantified comparison predicates
@@ -10217,10 +10246,10 @@ Field> field1a = Factory.rollup(...); // OK
Field> field2a = Factory.one(); // OK
// jOOQ 3.0
-GroupField field1b = Factory.rollup(...); // OK
-Field> field1c = Factory.rollup(...); // Compilation error
-GroupField field2b = Factory.one(); // OK
-Field> field2c = Factory.one(); // OK]]>
+GroupField field1b = DSL.rollup(...); // OK
+Field> field1c = DSL.rollup(...); // Compilation error
+GroupField field2b = DSL.one(); // OK
+Field> field2c = DSL.one(); // OK]]>
NULL predicate
@@ -10249,10 +10278,10 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]>
Configuration
- Executor, ExecuteContext, RenderContext, BindContext no longer extend Configuration for "convenience". From jOOQ 3.0 onwards, composition is chosen over inheritance as these objects are not really configurations. Most importantly
+ DSLContext, ExecuteContext, RenderContext, BindContext no longer extend Configuration for "convenience". From jOOQ 3.0 onwards, composition is chosen over inheritance as these objects are not really configurations. Most importantly
- Executor is only a DSL entry point for constructing "attached" QueryParts
+ DSLContext is only a DSL entry point for constructing "attached" QueryParts
ExecuteContext has a well-defined lifecycle, tied to that of a single query execution
RenderContext has a well-defined lifecycle, tied to that of a single rendering operation
BindContext has a well-defined lifecycle, tied to that of a single variable binding operation
@@ -10280,12 +10309,12 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]>
- - Connection-related JDBC wrapper utility methods (commit, rollback, etc) have been moved to the new DefaultConnectionProvider. They're no longer available from the Factory/Executor. This had been confusing to some users who called upon these methods while operating in pool DataSource mode.
+ - Connection-related JDBC wrapper utility methods (commit, rollback, etc) have been moved to the new DefaultConnectionProvider. They're no longer available from the DSLContext. This had been confusing to some users who called upon these methods while operating in pool DataSource mode.
ExecuteListeners
- ExecuteListeners can no longer be configured via Settings. Instead they have to be injected into the Configuration (e.g. the Executor). This resolves many class loader issues that were encountered before. It also helps listener implementations control their lifecycles themselves.
+ ExecuteListeners can no longer be configured via Settings. Instead they have to be injected into the Configuration. This resolves many class loader issues that were encountered before. It also helps listener implementations control their lifecycles themselves.
Data type API
@@ -10318,7 +10347,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]>
- The code generation configuration no longer accepts comma-separated regular expressions. Use the regex pipe | instead.
- The code generation configuration can no longer be loaded from .properties files. Only XML configurations are supported.
- The master data type feature is no longer supported. This feature was unlikely to behave exactly as users expected. It is better if users write their own code generators to generate master enum data types from their database tables. jOOQ's enum mapping and converter features sufficiently cover interacting with such user-defined types.
- - The Factory subtypes are no longer instanciable. As Factory now only contains static methods, subclassing is no longer useful. There are still dialect-specific Factories providing static methods for dialect-specific functions. But the code-generator no longer generates a schema-specific Factory
+ - The DSL subtypes are no longer instanciable. As DSL now only contains static methods, subclassing is no longer useful. There are still dialect-specific DSL types providing static methods for dialect-specific functions. But the code-generator no longer generates a schema-specific DSL
- The concept of a "main key" is no longer supported. The code generator produces UpdatableRecords only if the underlying table has a PRIMARY KEY. The reason for this removal is the fact that "main keys" are not reliable enough. They were chosen arbitrarily among UNIQUE KEYs.
- The UpdatableTable type has been removed. While adding significant complexity to the type hierarchy, this type adds not much value over a simple
Table.getPrimaryKey() != null check.
@@ -10349,13 +10378,13 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]>
Degree
Dialect
Domain Specific language (internal / external)
+ DSL
+ DSLContext
Execute
Execute listener
Execution lifecycle
- Executor
Export
Expression
- Factory
Fetch
Field
Function