diff --git a/jOOQ-manual/src/main/resources/org/jooq/web/manual-2.5.xml b/jOOQ-manual/src/main/resources/org/jooq/web/manual-2.5.xml index 74f5ac4f78..a7dfe14a66 100644 --- a/jOOQ-manual/src/main/resources/org/jooq/web/manual-2.5.xml +++ b/jOOQ-manual/src/main/resources/org/jooq/web/manual-2.5.xml @@ -86,14 +86,14 @@

jOOQ has come to fill this gap.

- +

jOOQ is different

SQL was never meant to be abstracted. To be confined in the narrow boundaries of heavy mappers, hiding the beauty and simplicity of relational data. SQL was never meant to be object-oriented. SQL was never meant to be anything other than... SQL!

- +
Getting started with jOOQ @@ -109,12 +109,12 @@

This section helps you correctly interpret this manual in the context of jOOQ.

- +

Code blocks

The following are code blocks:

- + @@ -124,7 +124,7 @@ org.jooq.property=value]]>

These are useful to provide examples in code. Often, with jOOQ, it is even more useful to compare SQL code with its corresponding Java/jOOQ code. When this is done, the blocks are aligned side-by-side, with SQL usually being on the left, and Java usually being on the right:

- +

The contents of code blocks follow conventions, too. If nothing else is mentioned next to any given code block, then the following can be assumed:

- - + +

jOOQ allows to override runtime behaviour using . If nothing is specified, the default runtime settings are assumed.

- +

Sample database

See the manual's section about to learn more about the sample database. @@ -193,7 +193,7 @@ CREATE TABLE book ( title VARCHAR2(400) NOT NULL, published_in NUMBER(7) NOT NULL, language_id NUMBER(7) NOT NULL, - + CONSTRAINT fk_book_author FOREIGN KEY (author_id) REFERENCES author(id), CONSTRAINT fk_book_language FOREIGN KEY (language_id) REFERENCES language(id) ) @@ -206,7 +206,7 @@ CREATE TABLE book_to_book_store ( name VARCHAR2(400) NOT NULL, book_id INTEGER NOT NULL, stock INTEGER, - + PRIMARY KEY(name, book_id), CONSTRAINT fk_b2bs_book_store FOREIGN KEY (name) REFERENCES book_store (name) ON DELETE CASCADE, CONSTRAINT fk_b2bs_book FOREIGN KEY (book_id) REFERENCES book (id) ON DELETE CASCADE @@ -233,7 +233,7 @@ CREATE TABLE book_to_book_store (

Effectively, jOOQ was originally designed to replace any other database abstraction framework short of the ones handling connection pooling and transaction management (see also the )

- +

Use jOOQ the way you prefer

... but open source is community-driven. And the community has shown various ways of using jOOQ that diverge from its original intent. Some use cases encountered are: @@ -244,7 +244,7 @@ CREATE TABLE book_to_book_store (

  • Using jOOQ for SQL building and Spring Data for SQL execution
  • Using jOOQ without the to build the basis of a framework for dynamic SQL execution.
  • - +

    The following sections explain about various use cases for using jOOQ in your application.

    @@ -257,7 +257,7 @@ CREATE TABLE book_to_book_store (

    This is the most simple of all use cases, allowing for construction of valid SQL for any database. In this use case, you will not use and probably not even . Instead, you'll use jOOQ to wrap strings, literals and other user-defined objects into an object-oriented, type-safe AST modelling your SQL statements. An example is given here:

    - + - +

    The SQL string that you can generate as such can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools.

    @@ -294,7 +294,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID)) .where(BOOK.PUBLISHED_IN.equal(1948)) .getSQL();]]> - +

    The SQL string that you can generate as such can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools.

    @@ -314,7 +314,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    Instead of any tool mentioned in the previous chapters, you can also use jOOQ directly to execute your jOOQ-generated SQL statements. This will add a lot of convenience on top of the previously discussed API for typesafe SQL construction, when you can re-use the information from generated classes to fetch records and custom data types. An example is given here:

    - + result = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .from(BOOK) @@ -363,10 +363,10 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { // Skip previously distinguished authors if ((int) author.getDistinguished() == 1) continue; - + // Check if the author has written more than 5 books if (author.fetchChildren(Keys.FK_BOOK_AUTHOR).size() > 5) { - + // Mark the author as a "distinguished" author author.setDistinguished(1); author.store(); @@ -383,7 +383,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {
    - +
    jOOQ for PROs @@ -421,7 +421,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { This manual section is intended for new users, to help them get a running application with jOOQ, quickly.

    - +
    Step 1: Preparation @@ -430,7 +430,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { If you haven't already downloaded it, download jOOQ:
    http://www.jooq.org/download

    - +

    Alternatively, you can create a Maven dependency:

    @@ -451,14 +451,14 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    - +
    Step 2: Your database

    We're going to create a database called "guestbook" and a corresponding "posts" table. Connect to MySQL via your command line client and type the following:

    - + CREATE DATABASE guestbook; CREATE TABLE `posts` ( @@ -470,7 +470,7 @@ CREATE TABLE `posts` ( );
    - +
    Step 3: Code generation @@ -482,7 +482,7 @@ CREATE TABLE `posts` (

    The easiest way to generate a schema is to copy the jOOQ jar files (there should be 3) and the MySQL Connector jar file to a temporary directory. Then, create a guestbook.xml that looks like this:

    - + @@ -534,7 +534,7 @@ CREATE TABLE `posts` (

    generator.target.directory - the directory to output to.

    - +

    Once you have the JAR files and library.xml in your temp directory, type this on a Windows machine:

    @@ -554,12 +554,12 @@ CREATE TABLE `posts` (

    There are two things to note:

    - +
    1. The prefix slash before the /library.xml. Even though it's in our working directory, we need to prepend a slash, as the configuration file is loaded from the classpath.
    2. The "trailing" period in the classpath: .. We need this because we want the current directory on the classpath in order to find the above /library.xml file at the root of your classpath.
    - +

    Replace the filenames with your actual filenames. In this example, jOOQ {jooq-version} is being used. If everything has worked, you should see this in your console output:

    @@ -626,14 +626,14 @@ Nov 1, 2011 7:25:08 PM org.jooq.impl.JooqLogger info INFO: GENERATION FINISHED! : Total: 791.688ms, +9.143ms
    - +
    Step 4: Connect to your database

    Let's just write a vanilla main class in the project containing the generated classes:

    - +
    - +
    Step 5: Querying

    Let's add a simple query:

    - + result = create.select().from(POSTS).fetch();]]> @@ -689,7 +689,7 @@ Result result = create.select().from(POSTS).fetch();]]>

    - +
    Step 6: Iterating @@ -708,7 +708,7 @@ Result result = create.select().from(POSTS).fetch();]]>

    The full program should now look like this:

    - +
    - +
    Step 7: Explore! @@ -814,7 +814,7 @@ public class Main {
    - +
    Dependencies @@ -827,7 +827,7 @@ public class Main {
  • Small libraries with compatible licenses are incorporated into jOOQ (jOOR, jOOU, OpenCSV, json simple, commons-lang)
  • javax.persistence and javax.validation will be needed if you activate the relevant
  • - +

    Build your own

    In order to build jOOQ, please download the sources from https://github.com/jOOQ/jOOQ and use Maven to build it, preferably in Eclipse. @@ -921,7 +921,7 @@ Result result = select.fetch();]]> CONNECT BY clause to the query */ -@Support({ CUBRID }) +@Support({ CUBRID, ORACLE }) SelectConnectByConditionStep connectBy(Condition condition);]]>

    jOOQ API methods which are not annotated with the annotation, or which are annotated with the Support annotation, but without any SQL dialects can be safely used in all SQL dialects. An example for this is the factory method: @@ -942,7 +942,7 @@ SelectSelectStep select(Field... fields);]]>

    Nevertheless, the IS DISTINCT FROM predicate is supported in all dialects, as its semantics can be expressed with an equivalent . For more details, see the manual's section about the .

    - +

    jOOQ and the Oracle SQL dialect

    Oracle SQL is much more expressive than many other SQL dialects. It features many unique keywords, clauses and functions that are out of scope for the SQL standard. Some examples for this are @@ -1016,7 +1016,7 @@ Factory create = new Factory(connection, dialect, settings);]]>

    - +
    Runtime schema and table mapping @@ -1024,7 +1024,7 @@ Factory create = new Factory(connection, dialect, settings);]]>

    You may wish to design your database in a way that you have several instances of your schema. This is useful when you want to cleanly separate data belonging to several customers / organisation units / branches / users and put each of those entities' data in a separate database or schema.

    - +

    In our AUTHOR example this would mean that you provide a book reference database to several companies, such as My Book World and Books R Us. In that case, you'll probably have a schema setup like this:

    @@ -1054,7 +1054,7 @@ create.selectFrom(AUTHOR).fetch();

    The query executed with a Factory equipped with the above mapping will in fact produce this SQL statement:

    - + SELECT * FROM MY_BOOK_WORLD.AUTHOR

    Even if AUTHOR was generated from DEV. @@ -1147,7 +1147,7 @@ create.selectFrom(AUTHOR).fetch();

    The query executed with a Factory equipped with the above mapping will in fact produce this SQL statement:

    - + SELECT * FROM MY_BOOK_WORLD.MY_APP__AUTHOR

    @@ -1205,7 +1205,7 @@ MySQLFactory create = new MySQLFactory(connection);

    Here is an example to illustrate what that means:

    - +

    Note, that for historic reasons, the DSL API mixes mutable and immutable behaviour with respect to the internal representation of the being constructed. While creating , (such as functions) assumes immutable behaviour, creating does not. In other words, the following can be said:

    - +

    Read more about aliasing in the manual's section about .

    - +

    More advanced table expressions

    Apart from simple tables, you can pass any arbitrary to the jOOQ FROM clause. This may include in Oracle: @@ -1768,7 +1768,7 @@ GROUP BY ()]]> - +

    ROLLUP(), CUBE() and GROUPING SETS()

    Some databases support the SQL standard grouping functions and some extensions thereof. See the manual's section about for more details. @@ -1787,7 +1787,7 @@ GROUP BY ()]]>= 2]]>= 2]]> @@ -1966,7 +1966,7 @@ SELECT TOP 1 * FROM BOOK

    Things get a little more tricky in those databases that have no native idiom for OFFSET pagination (actual queries may vary):

    - +

    SQL allows to perform set operations as understood in standard set theory on result sets. These operations include unions, intersections, subtractions. For two subselects to be combinable by such a set operator, each subselect must return a of the same arity and type.

    - +

    UNION and UNION ALL

    These operators combine two results into one. While UNION removes all duplicate records resulting from this combination, UNION ALL leaves subselect results as they are. Typically, you should prefer UNION ALL over UNION, if you don't really need to remove duplicates. The following example shows how to use such a UNION operation in jOOQ. @@ -2119,12 +2119,12 @@ UNION ALL SELECT * FROM BOOK WHERE ID = 5]]> - +

    INTERSECT [ ALL ] and EXCEPT [ ALL ]

    INTERSECT is the operation that produces only those tuples that are returned by both subselects. EXCEPT is the operation that returns only those tuples that are returned exclusively in the first subselect. Both operators will remove duplicates from their results. The SQL standard allows to specify the ALL keyword for both of these operators as well, but this is hardly supported in any database. jOOQ does not support INTERSECT ALL, EXEPT ALL operations either.

    - +

    jOOQ's set operators and how they're different from standard SQL

    As previously mentioned in the manual's section about the , jOOQ has slightly changed the semantics of these set operators. While in SQL, a subselect may not contain any or (unless you wrap the subselect into a ), jOOQ allows you to do so. In order to select both the youngest and the oldest author from the database, you can issue the following statement with jOOQ (rendered to the MySQL dialect): @@ -2140,7 +2140,7 @@ UNION .union( create.selectFrom(AUTHOR) .orderBy(AUTHOR.DATE_OF_BIRTH.desc()).limit(1));]]> - +

    @@ -2228,7 +2228,7 @@ SELECT 101, 'Alfred', 'Döblin' FROM DUAL;create.insertInto(AUTHOR, .set(AUTHOR.ID, 101) .set(AUTHOR.FIRST_NAME, "Alfred") .set(AUTHOR.LAST_NAME, "Döblin"); - +

    As you can see, this syntax is a bit more verbose, but also more type-safe, as every field can be matched with its value. Internally, the two syntaxes are strictly equivalent.

    @@ -2237,7 +2237,7 @@ SELECT 101, 'Alfred', 'Döblin' FROM DUAL;create.insertInto(AUTHOR,

    The MySQL database supports a very convenient way to INSERT or UPDATE a record. This is a non-standard extension to the SQL syntax, which is supported by jOOQ and emulated in other RDBMS, where this is possible (i.e. if they support the SQL standard ). Here is an example how to use the ON DUPLICATE KEY UPDATE clause:

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, update the author's name create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -2246,11 +2246,11 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .set(AUTHOR.LAST_NAME, "Koontz");

    The synthetic ON DUPLICATE KEY IGNORE clause

    - +

    The MySQL database also supports an INSERT IGNORE INTO clause. This is supported by jOOQ using the more convenient SQL syntax variant of ON DUPLICATE KEY IGNORE, which can be equally emulated in other databases using a :

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, ignore the INSERT statement create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -2286,11 +2286,11 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    The INSERT SELECT statement

    - +

    In some occasions, you may prefer the INSERT SELECT syntax, for instance, when you copy records from one table to another:

    - + create.insertInto(AUTHOR_ARCHIVE) .select(create.selectFrom(AUTHOR).where(AUTHOR.DECEASED.isTrue())); @@ -2311,7 +2311,7 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .set(AUTHOR.LAST_NAME, "Hesse") .where(AUTHOR.ID.equal(3));
    - + @@ -2362,7 +2362,7 @@ WHEN NOT MATCHED THEN INSERT (LAST_NAME) VALUES ('Hitchcock')create.

    The H2 database ships with a somewhat less powerful but a little more intuitive syntax for its own version of the MERGE statement. An example more or less equivalent to the previous one can be seen here:

    - + -- Check if there is already an author called 'Hitchcock' -- If there is, rename him to John. If there isn't add him. @@ -2381,7 +2381,7 @@ VALUES ('John', 'Hitchcock')create.mergeInto(AUTHOR, This syntax can be fully emulated by jOOQ for all other databases that support the SQL standard MERGE statement. For more information about the H2 MERGE syntax, see the documentation here:
    http://www.h2database.com/html/grammar.html#merge

    - + @@ -2398,7 +2398,7 @@ VALUES ('John', 'Hitchcock')create.mergeInto(AUTHOR, TRUNCATE TABLE AUTHOR;create.truncate(AUTHOR).execute(); - +

    TRUNCATE is not supported by Ingres and SQLite. jOOQ will execute a DELETE FROM AUTHOR statement instead.

    @@ -2422,7 +2422,7 @@ VALUES ('John', 'Hitchcock')create.mergeInto(AUTHOR,

    Most of the times, when thinking about a you're probably thinking about an actual table in your database schema. If you're using jOOQ's , you will have all tables from your database schema available to you as type safe Java objects. You can then use these tables in SQL , or in other , just like any other table expression. An example is given here:

    - + - +

    The above example shows how AUTHOR and BOOK tables are joined in a . It also shows how you can access by dereferencing the relevant Java attributes of their tables.

    @@ -2469,11 +2469,11 @@ create.select() .where(a.YEAR_OF_BIRTH.greaterThan(1920) .and(a.FIRST_NAME.equal("Paulo"))) .orderBy(b.TITLE);]]>
    - +

    As you can see in the above example, calling as() on generated tables returns an object of the same type as the table. This means that the resulting object can be used to dereference fields from the aliased table. This is quite powerful in terms of having your Java compiler check the syntax of your SQL statements. If you remove a column from a table, dereferencing that column from that table alias will cause compilation errors.

    - +

    Dereferencing columns from other table expressions

    TODO document this @@ -2487,7 +2487,7 @@ create.select()

    The that can be used in are the most powerful and best supported means of creating new in SQL. Informally, the following can be said:

    - + A(colA1, ..., colAn) "join" B(colB1, ..., colBm) "produces" C(colA1, ..., colAn, colB1, ..., colBm)

    @@ -2505,7 +2505,7 @@ create.select()

    jOOQ supports all of these JOIN types (except semi-join and anti-join) directly on any :

    - + table) @@ -2543,9 +2543,9 @@ Table naturalRightOuterJoin(TableLike)]]>

    A can appear almost anywhere a can. Such a "nested SELECT" is often called a "derived table". Apart from many convenience methods accepting objects directly, a SELECT statement can always be transformed into a object using the asTable() method.

    - +

    Example: Scalar subquery

    - + SELECT * FROM BOOK @@ -2612,11 +2612,11 @@ create.select(AUTHOR.ID, books)

    If you are closely coupling your application to an Oracle database, you can take advantage of some Oracle-specific features, such as the PIVOT clause, used for statistical analyses. The formal syntax definition is as follows:

    - + -- SELECT .. FROM table PIVOT (aggregateFunction [, aggregateFunction] FOR column IN (expression [, expression])) -- WHERE .. - +

    The PIVOT clause is available from the type, as pivoting is done directly on a table. Currently, only Oracle's PIVOT clause is supported. Support for SQL Server's slightly different PIVOT clause will be added later. Also, jOOQ may emulate PIVOT for other dialects in the future.

    @@ -2679,7 +2679,7 @@ WHERE NOT EXISTS (

    The SQL standard specifies how SQL databases should implement ARRAY and TABLE types, as well as CURSOR types. Put simply, a CURSOR is a pointer to any materialised . Depending on the cursor's features, this table expression can be scrolled through in both directions, records can be locked, updated, removed, inserted, etc. Often, CURSOR types contain tuples, whereas ARRAY and TABLE types contain simple scalar values, although that is not a requirement

    - +

    ARRAY types in SQL are similar to Java's array types. They contain a "component type" or "element type" and a "dimension". This sort of ARRAY type is implemented in H2, HSQLDB and Postgres and supported by jOOQ as such. Oracle uses strongly-typed arrays, which means that an ARRAY type (VARRAY or TABLE type) has a name and possibly a maximum capacity associated with it.

    @@ -2758,7 +2758,7 @@ new Factory(SQLDialect.SYBASE ).selectOne().getSQL();]]>

    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; @@ -2811,7 +2811,7 @@ ORDER BY BOOK.TITLE]]> Just like , columns can be renamed using aliases. Here is an example:

    - + SELECT FIRST_NAME || ' ' || LAST_NAME author, COUNT(*) books FROM AUTHOR JOIN BOOK ON AUTHOR.ID = AUTHOR_ID @@ -2820,18 +2820,18 @@ GROUP BY FIRST_NAME, LAST_NAME;

    Here is how it's done with jOOQ:

    - + Record record = create.select( concat(AUTHOR.FIRST_NAME, val(" "), AUTHOR.LAST_NAME).as("author"), count().as("books")) .from(AUTHOR) .join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID)) .groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME).fetchAny(); - +

    When you alias Fields like above, you can access those Fields' values using the alias name:

    - + System.out.println("Author : " + record.getValue("author")); System.out.println("Books : " + record.getValue("books")); @@ -2845,7 +2845,7 @@ System.out.println("Books : " + record.getValue("books"));

    Sometimes, this automatic mapping might not be what you needed, or jOOQ cannot know the type of a field. In those cases you would write SQL type CASTs like this:

    - + -- Let's say, your Postgres column LAST_NAME was VARCHAR(30) -- Then you could do this: SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL @@ -2853,27 +2853,27 @@ SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL

    in jOOQ, you can write something like that:

    - + create.select(TAuthor.LAST_NAME.cast(PostgresDataType.TEXT));

    The same thing can be achieved by casting a Field directly to String.class, as TEXT is the default data type in Postgres to map to Java's String

    - + create.select(TAuthor.LAST_NAME.cast(String.class)); - +

    The complete CAST API in Field consists of these three methods:

    - + { // Cast this field to the type of another field Field cast(Field field); - + // Cast this field to a given DataType Field cast(DataType type); - + // Cast this field to the default DataType for a given Class Field cast(Class type); } @@ -2902,13 +2902,13 @@ public class Factory {

    In order to express a SQL query like this one:

    - + SELECT ((1 + 2) * (5 - 3) / 2) % 10 FROM DUAL - +

    You can write something like this in jOOQ:

    - + create.select(val(1).add(2).mul(val(5).sub(3)).div(2).mod(10);

    Datetime arithmetic expressions

    @@ -2929,14 +2929,14 @@ public class Factory { - +
    String concatenation

    The SQL standard defines the concatenation operator to be an infix operator, similar to the ones we've seen in the chapter about . This operator looks like this: ||. Some other dialects do not support this operator, but expect a concat() function, instead. jOOQ renders the right operator / function, depending on your :

    - + SELECT 'A' || 'B' || 'C' FROM DUAL -- Or in MySQL: @@ -2963,13 +2963,13 @@ create.select(concat("A", "B", "C"));
  • NVL: Get the first non-null value among two arguments.
  • NVL2: Get the second argument if the first is null, or the third argument, otherwise.
  • - +

    Please refer to the for more details.

    - +
    Numeric functions @@ -2979,7 +2979,7 @@ create.select(concat("A", "B", "C"));

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ABS: Get the absolute value of a value.
    • ACOS: Get the arc cosine of a value.
    • @@ -3010,7 +3010,7 @@ create.select(concat("A", "B", "C"));
    • TANH: Get the hyperbolic tangent of a value.
    • TRUNC: Truncate the decimals off a given value.
    - +

    Please refer to the for more details.

    @@ -3035,13 +3035,13 @@ create.select(concat("A", "B", "C"));
  • SHL: Shift bits to the left
  • SHR: Shift bits to the right
  • - +

    Some background about bitwise operation emulation

    As stated before, not all databases support all of these bitwise operations. jOOQ emulates them wherever this is possible. More details can be seen in this blog post:
    http://blog.jooq.org/2011/10/30/the-comprehensive-sql-bitwise-operations-compatibility-list/

    - +
    @@ -3054,7 +3054,7 @@ create.select(concat("A", "B", "C"));

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ASCII: Get the ASCII code of a character.
    • BIT_LENGTH: Get the length of a string in bits.
    • @@ -3075,16 +3075,16 @@ create.select(concat("A", "B", "C"));
    • TRIM: Trim a string on both sides.
    • UPPER: Get a string in upper case letters.
    - +

    Please refer to the for more details.

    - +

    Regular expressions, REGEXP, REGEXP_LIKE, etc.

    Various databases have some means of searching through columns using regular expressions if the does not provide sufficient pattern matching power. While there are many different functions and operators in the various databases, jOOQ settled for the SQL:2008 standard REGEX_LIKE operator. Being an operator (and not a function), you should use the corresponding method on :

    - +

    @@ -3100,7 +3100,7 @@ create.select(concat("A", "B", "C"));

    This is a list of date and time functions supported by jOOQ's :

    - +
    • CURRENT_DATE: Get current date as a DATE object.
    • CURRENT_TIME: Get current time as a TIME object.
    • @@ -3110,7 +3110,7 @@ create.select(concat("A", "B", "C"));
    • TIMESTAMP_ADD: Add a number of days or an interval to a timestamp.
    • TIMESTAMP_DIFF: Get the difference as an INTERVAL DAY TO SECOND between two dates.
    - +

    Intervals in jOOQ

    jOOQ fills a gap opened by JDBC, which neglects an important SQL data type as defined by the SQL standards: INTERVAL types. See the manual's section about for more details. @@ -3244,7 +3244,7 @@ GROUP BY AUTHOR_IDcreate.select(listAgg(BOOK.TITLE, ", ") WindowOverStep rank(); WindowOverStep denseRank(); WindowOverStep percentRank(); - + // Windowing functions WindowIgnoreNullsStep firstValue(Field field); WindowIgnoreNullsStep lastValue(Field field) @@ -3260,7 +3260,7 @@ GROUP BY AUTHOR_IDcreate.select(listAgg(BOOK.TITLE, ", ") // Statistical functions WindowOverStep cumeDist(); WindowOverStep ntile(int number);]]> - +

    SQL distinguishes between various window function types (e.g. "ranking functions"). Depending on the function, SQL expects mandatory PARTITION BY or ORDER BY clauses within the OVER() clause. jOOQ does not enforce those rules for two reasons:

    @@ -3275,14 +3275,14 @@ GROUP BY AUTHOR_IDcreate.select(listAgg(BOOK.TITLE, ", ")

    Here are some simple examples of window functions with jOOQ:

    - + -- Sample uses of ROW_NUMBER() ROW_NUMBER() OVER() ROW_NUMBER() OVER(PARTITION BY 1) ROW_NUMBER() OVER(ORDER BY BOOK.ID) ROW_NUMBER() OVER(PARTITION BY BOOK.AUTHOR_ID ORDER BY BOOK.ID) - + -- Sample uses of FIRST_VALUE FIRST_VALUE(BOOK.ID) OVER() FIRST_VALUE(BOOK.ID IGNORE NULLS) OVER() @@ -3292,14 +3292,14 @@ rowNumber().over() rowNumber().over().partitionByOne() rowNumber().over().partitionBy(BOOK.AUTHOR_ID) rowNumber().over().partitionBy(BOOK.AUTHOR_ID).orderBy(BOOK.ID) - + // Sample uses of firstValue() firstValue(BOOK.ID).over() firstValue(BOOK.ID).ignoreNulls().over() firstValue(BOOK.ID).respectNulls().over()
    - +

    An advanced window function example

    Window functions can be used for things like calculating a "running total". The following example fetches transactions and the running total for every transaction going back to the beginning of the transaction table (ordered by booked_at). Window functions are accessible from the previously seen type using the over() method: @@ -3324,7 +3324,7 @@ firstValue(BOOK.ID).respectNulls().over()

    In the previous chapter about , we have seen the concept of "ordered-set aggregate functions", such as Oracle's LISTAGG(). These functions have a window function / analytical function variant, as well. For example:

    - + SELECT LISTAGG(TITLE, ', ') WITHIN GROUP (ORDER BY TITLE) @@ -3404,7 +3404,7 @@ ORDER BY 1 NULLS LAST, 2 NULLS LAST

    In English, the ROLLUP() grouping function provides N+1 groupings, when N is the number of arguments to the ROLLUP() function. Each grouping has an additional group field from the ROLLUP() argument field list. The results of the second query might look something like this:

    - + GROUPING SETS() and other grouping functions:
    http://msdn.microsoft.com/en-us/library/bb510427(v=sql.105)

    - +

    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:

    - + rollup(Field... fields); Field cube(Field... fields); @@ -3506,7 +3506,7 @@ Field groupingId(Field...);]]>

    MySQL and CUBRID don't know any grouping functions, but they support a WITH ROLLUP clause, that is equivalent to simple ROLLUP() grouping functions. jOOQ emulates ROLLUP() in MySQL and CUBRID, by rendering this WITH ROLLUP clause. The following two statements mean the same:

    - + Some databases support user-defined functions, which can be embedded in any SQL statement, if you're using jOOQ's . Let's say you have the following simple function in Oracle SQL:

    - + The above function will be made available from a generated class. You can use it like any other :

    - + - +

    Note that user-defined functions returning or data types can also be used wherever can be used, if they are

    @@ -3556,7 +3556,7 @@ END echo;

    Some databases support user-defined aggregate functions, which can then be used along with or as . An example for such a database is Oracle. With Oracle, you can define the following OBJECT type (the example was taken from the Oracle 11g documentation):

    - +

    jOOQ's will detect such aggregate functions and generate them differently from regular . They implement the type, as mentioned in the manual's section about . Here's how you can use the SECOND_MAX() aggregate function with jOOQ:

    - + The of a
  • The 's ON clause
  • - +

    Boolean types in SQL

    Before SQL:1999, boolean types did not really exist in SQL. They were modelled by 0 and 1 numeric/char values. With SQL:1999, true booleans were introduced and are now supported by most databases. In short, these are possible boolean values: @@ -3858,7 +3858,7 @@ Condition combined2 = combined1.andNot(c); // The left-hand side of the AND NOT

    Here are all boolean operators on the interface:

    - + < to test for being strictly less
  • <= to test for being less or equal
  • - +

    Unfortunately, Java does not support operator overloading, hence these operators are also implemented as methods in jOOQ, like any other SQL syntax elements. The relevant parts of the interface are these:

    - + ); // = (some column expression) eq or equal(Select); // = (some scalar SELECT statement) @@ -3919,7 +3919,7 @@ ge or greaterOrEqual(Select); // >= (some scalar SELECT statement)]]><

    Note that every operator is represented by two methods. A verbose one (such as equal()) and a two-character one (such as eq()). Both methods are the same. You may choose either one, depending on your taste. The manual will always use the more verbose one.

    - +

    NULL in jOOQ's comparison predicates

    jOOQ has a special way of dealing with null bind values, when you pass them to comparison predicates equal() and notEqual(). For convenience, jOOQ will render predicates. @@ -3929,7 +3929,7 @@ ge or greaterOrEqual(Select); // >= (some scalar SELECT statement)]]><

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using comparison predicates:

    - +

    It is interesting to note that the SQL standard defines the in terms of the ANY-quantified predicate. The following two expressions are equivalent:

    - + @@ -3978,7 +3978,7 @@ BOOK.PUBLISHED_IN.greaterThanAll(1920, 1940);]]>

    In SQL, you cannot compare NULL with any value using , as the result would yield NULL again, which is neither TRUE nor FALSE (see also the manual's section about ). In order to test a for NULL, use the NULL predicate as such:

    - +

    If your database does not natively support the DISTINCT predicate, jOOQ emulates it with an equivalent , modelling the above truth table:

    - + The BETWEEN predicate can be seen as syntactic sugar for a pair of . According to the SQL standard, the following two predicates are equivalent:

    - + = [B] AND [A] <= [C]]]> @@ -4059,7 +4059,7 @@ BOOK.PUBLISHED_IN.notBetween(1920, 1940)]]>

    The SQL standard defines the SYMMETRIC keyword to be used along with BETWEEN to indicate that you do not care which bound of the range is larger than the other. A database system should simply swap range bounds, in case the first bound is greater than the second one. jOOQ supports this keyword as well, emulating it if necessary.

    - +

    The emulation is done trivially:

    - + @@ -4096,7 +4096,7 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940, 1920)]]>
    TITLE NOT LIKE '%abc%']]> - +

    Escaping operands with the LIKE predicate

    Often, your pattern may contain any of the wildcard characters "_" and "%", in case of which you may want to escape them. jOOQ does not automatically escape patterns in like() and notLike() methods. Instead, you can explicitly define an escape character as such: @@ -4114,12 +4114,12 @@ BOOK.TITLE.notLike("%The !%-Sign Book%", '!')]]>

    Please refer to your database manual for more details about escaping patterns with the LIKE predicate.

    - +

    jOOQ's convenience methods using the LIKE predicate

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using the LIKE predicate. Typical operations are "contains predicates", "starts with predicates", "ends with predicates", etc. Here is the full convenience API wrapping LIKE predicates:

    - + ) // Construct a NOT IN predicate from a subselect]]><

    A sample IN predicate might look like this:

    - + - +

    NOT IN and NULL values

    Beware that you should probably not have any NULL values in the right hand side of a NOT IN predicate, as the whole expression would evaluate to NULL, which is rarely desired. This can be shown informally using the following reasoning:

    - + -- The following conditional expressions are formally or informally equivalent A NOT IN (B, C) A != ANY(B, C) @@ -4204,7 +4204,7 @@ NULL -- [ANY] AND NULL yields NULL
  • From a using
  • From a using , and from other clauses
  • - +

    An example of an EXISTS predicate can be seen here:

    @@ -4222,7 +4222,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

    - +

    Performance of IN vs. EXISTS

    In theory, the two types of predicates can perform equally well. If your database system ships with a sophisticated cost-based optimiser, it will be able to transform one predicate into the other, if you have all necessary constraints set (e.g. referential constraints, not null constraints). However, in reality, performance between the two might differ substantially. An interesting blog post investigating this topic on the MySQL database can be seen here:
    @@ -4245,7 +4245,7 @@ notExists(create.selectOne().from(BOOK)

  • - +

    You'll probably find other examples. If verbosity scares you off, don't worry. The verbose use-cases for jOOQ are rather rare, and when they come up, you do have an option. Just write SQL the way you're used to!

    @@ -4275,7 +4275,7 @@ Condition condition(String sql, Object... bindings); // Construct a condition taking other jOOQ object arguments // Example: condition("a = {0}", val(1)); 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:

    @@ -4333,7 +4333,7 @@ Result fetch(String sql, QueryPart... parts);]]>

    Apart from the general factory methods, plain SQL is also available in various other contexts. For instance, when adding a .where("a = b") clause to a query. Hence, there exist several convenience methods where plain SQL can be inserted usefully. This is an example displaying all various use-cases in one single query:

    - + LAST_NAME = create.field("a.LAST_NAME"); @@ -4392,7 +4392,7 @@ create.select(LAST_NAME, COUNT1, COUNT2) On a JDBC level, you can also reuse the SQL string and prepared statement object instead of constructing it again, as you can bind new values to the prepared statement. jOOQ currently does not cache prepared statements, internally. - +

    The following sections explain how you can introduce bind values in jOOQ, and how you can control the way they are rendered and bound to SQL.

    @@ -4405,7 +4405,7 @@ create.select(LAST_NAME, COUNT1, COUNT2)

    JDBC only knows indexed bind values. A typical example for using bind values with JDBC is this:

    - + With dynamic SQL, keeping track of the number of question marks and their corresponding index may turn out to be hard. jOOQ abstracts this and lets you provide the bind value right where it is needed. A trivial example is this:

    - + 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

    Should you decide to run the above query outside of jOOQ, using your own , you can do so as follows:

    - + select = create.select().from(BOOK).where(BOOK.ID.equal(5)).and(BOOK.TITLE.equal("Animal Farm")); // Render the SQL statement: @@ -4556,7 +4556,7 @@ create.select()

    Special care needs to be taken when using . While jOOQ's API allows you to specify bind values for use with plain SQL, you're not forced to do that. For instance, both of the following queries will lead to the same, valid result:

    - +

    A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] FROM AUTHOR JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID @@ -4749,7 +4749,7 @@ BindContext bindValues(Object... values) throws DataAccessException;]]>
    A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] WHERE AUTHOR.ID = ? -- [...] @@ -4776,7 +4776,7 @@ public final void bind(BindContext context) throws DataAccessException {

    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:

    - + extends AbstractField {} public abstract class CustomCondition extends AbstractCondition {} public abstract class CustomTable> extends TableImpl {} @@ -4785,7 +4785,7 @@ public abstract class CustomRecord> extends TableRecord

    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 and methods, as discussed before:

    - + 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 showing how to create a field multiplying another field by 2

    - + IDx2 = new CustomField(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(" * ?"); @@ -4822,10 +4822,10 @@ final Field IDx2 = new CustomField(BOOK.ID.getName(), BOOK.ID. @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)); } @@ -4852,7 +4852,7 @@ create.select(IDx2).from(BOOK);]]>

    The above distinction is best explained using an example:

    - +

    In a previous section of the manual, we've seen how jOOQ can be used to that can be executed with any API including JDBC or ... jOOQ. This section of the manual deals with various means of actually executing SQL with jOOQ.

    - +

    SQL execution with JDBC

    JDBC calls executable objects "". It distinguishes between three types of statements: @@ -4916,7 +4916,7 @@ create.attach(select);]]>

    Today, the JDBC API may look weird to users being used to object-oriented design. While statements hide a lot of SQL dialect-specific implementation details quite well, they assume a lot of knowledge about the internal state of a statement. For instance, you can use the method, to add a the prepared statement being created to an "internal list" of batch statements. Instead of returning a new type, this method forces user to reflect on the prepared statement's internal state or "mode".

    - +

    jOOQ is wrapping JDBC

    These things are abstracted away by jOOQ, which exposes such concepts in a more object-oriented way. For more details about jOOQ's batch query execution, see the manual's section about . @@ -4938,7 +4938,7 @@ create.attach(select);]]>

  • Both APIs return the number of affected records in non-result queries. JDBC: , jOOQ:
  • Both APIs return a scrollable result set type from result queries. JDBC: , jOOQ:
  • - +

    Differences to JDBC

    Some of the most important differences between JDBC and jOOQ are listed here: @@ -4952,14 +4952,14 @@ create.attach(select);]]> - +

    Query vs. ResultQuery

    Unlike JDBC, jOOQ has a lot of knowledge about a SQL query's structure and internals (see the manual's section about ). Hence, jOOQ distinguishes between these two fundamental types of queries. While every can be executed, only can return results (see the manual's section about to learn more about fetching results). With plain SQL, the distinction can be made clear most easily:

    - + result = resultQuery.fetch();]]>
  • : Some databases allow for returning many result sets from a single query. JDBC can handle this but it's very verbose. A list of results should be returned instead.
  • : Some queries take too long to execute to wait for their results. You should be able to spawn query execution in a separate process.
  • - +

    Convenience and how ResultQuery, Result, and Record share API

    The term "fetch" is always reused in jOOQ when you can fetch data from the database. An provides many overloaded means of fetching data:

    - +

    Various modes of fetching

    These modes of fetching are also documented in subsequent sections of the manual

    - + fetch(); @@ -5020,7 +5020,7 @@ List> fetchMany(); // Execute a ResultQuery with jOOQ, but return a JDBC ResultSet, not a jOOQ object ResultSet fetchResultSet();]]> - +

    Fetch convenience

    These means of fetching are also available from and APIs @@ -5066,11 +5066,11 @@ ResultSet fetchResultSet();]]>

    These means of fetching are also available from and APIs

    - + Map fetchMap(Field key); Map fetchMap(Field key, Field value); @@ -5099,7 +5099,7 @@ ResultSet fetchResultSet();]]>

    jOOQ understands that SQL is much more expressive than Java, when it comes to the declarative typing of . As a declarative language, SQL allows for creating ad-hoc tuples (records with indexed columns) and records (records with named columns). In Java, this is not possible to the same extent. Yet, still, sometimes you wish to use strongly typed records, when you know that you're selecting only from a single table

    - +

    Fetching strongly or weakly typed records

    When fetching data only from a single table, the type is known to jOOQ if you use jOOQ's to generate for your database tables. In order to fetch such strongly typed records, you will have to use the : @@ -5111,7 +5111,7 @@ BookRecord book = create.selectFrom(BOOK).where(BOOK.ID.equal(1)).fetchOne(); // Typesafe field access is now possible: 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:

    @@ -5121,12 +5121,12 @@ System.out.println("Published in: " + book.getPublishedIn());]]>
  • - +

    Scala's tuple classes

    With the introduction of generics in Java 5, it is possible in principle, to pre-define a set of tuple types. This is what Scala does. In essence, tuple types look something like this:

    - + extends Tuple { T1 get1(); void set1(T1 t1); @@ -5189,7 +5189,7 @@ for (tuple <- create

    By default, jOOQ returns an object, which is essentially a of . Often, you will find yourself wanting to transform this result object into a type that corresponds more to your specific needs. Or you just want to list all values of one specific column. Here are some examples to illustrate those use cases:

    - + titles1 = create.select().from(BOOK).fetch().getValues(BOOK.TITLE); List titles2 = create.select().from(BOOK).fetch(BOOK.TITLE); @@ -5224,7 +5224,7 @@ Map> group4 = create.selectFrom(BOOK).fetchGroups(BO

    In a more functional operating mode, you might want to write callbacks that receive records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + () {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -5257,7 +5257,7 @@ create.selectFrom(BOOK)

    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.

    - +

    Using JPA-annotated POJOs

    jOOQ tries to find JPA annotations on your POJO types. If it finds any, they are used as the primary source for mapping meta-information. Only the annotation is used and understood by jOOQ. An example: @@ -5267,7 +5267,7 @@ create.selectFrom(BOOK) public class MyBook { @Column(name = "ID") public int myId; - + @Column(name = "TITLE") public String myTitle; } @@ -5276,16 +5276,16 @@ public class MyBook { MyBook myBook = create.select().from(BOOK).fetchAny().into(MyBook.class); List myBooks = create.select().from(BOOK).fetch().into(MyBook.class); List myBooks = create.select().from(BOOK).fetchInto(MyBook.class);]]> - +

    Just as with any other JPA implementation, you can put the annotation on any class member, including attributes, setters and getters. Please refer to the Javadoc for more details.

    - +

    Using simple POJOs

    If jOOQ does not find any JPA-annotations, columns are mapped to the "best-matching" constructor, attribute or setter. An example illustrates this:

    - + myBooks = create.select().from(BOOK).fetch().into(MyBook1.class); List myBooks = create.select().from(BOOK).fetchInto(MyBook1.class); - + // An "immutable" POJO class public class MyBook2 { public final int id; public final String title; - + public MyBook2(int id, String title) { this.id = id; this.title = title; @@ -5312,7 +5312,7 @@ public class MyBook2 { MyBook2 myBook = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchAny().into(MyBook2.class); List myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetch().into(MyBook2.class); List myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchInto(MyBook2.class);]]> - +

    Please refer to the Javadoc for more details.

    @@ -5321,12 +5321,12 @@ List myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchInto(

    jOOQ also allows for fetching data into abstract classes or interfaces, or in other words, "proxyable" types. This means that jOOQ will return a wrapped in a implementing your custom type. An example of this is given here:

    - + - +

    Note: Because of your manual setting of ID = 10, jOOQ's store() method will asume that you want to insert a new record. See the manual's section about for more details on this.

    - +

    Interaction with DAOs

    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: @@ -5393,7 +5393,7 @@ bookDao.update(book); // Delete it again bookDao.delete(book);]]> - +

    More complex data structures

    jOOQ currently doesn't support more complex data structures, the way Hibernate/JPA attempt to map relational data onto POJOs. While future developments in this direction are not excluded, jOOQ claims that generic mapping strategies lead to an enormous additional complexity that only serves very few use cases. You are likely to find a solution using any of jOOQ's various , with only little boiler-plate code on the client side. @@ -5407,7 +5407,7 @@ bookDao.delete(book);]]>

    Unlike JDBC's , jOOQ's does not represent an open database cursor with various fetch modes and scroll modes, that needs to be closed after usage. jOOQ's results are simple in-memory Java objects, containing all of the result values. If your result sets are large, or if you have a lot of network latency, you may wish to fetch records one-by-one, or in small chunks. jOOQ supports a type for that purpose. In order to obtain such a reference, use the method. An example is given here:

    - + cursor = null; @@ -5417,7 +5417,7 @@ try { // Cursor has similar methods as Iterator while (cursor.hasNext()) { BookRecord book = cursor.fetchOne(); - + Util.doThingsWithBook(book); } } @@ -5432,7 +5432,7 @@ finally {

    As a holds an internal reference to an open , it may need to be closed at the end of iteration. If a cursor is completely scrolled through, it will conveniently close the underlying ResultSet. However, you should not rely on that.

    - +

    Cursors ship with all the other fetch features

    Like or , gives access to all of the other fetch features that we've seen so far, i.e. @@ -5473,7 +5473,7 @@ finally {

    The correct (and verbose) way to do this with JDBC is as follows:

    - +

    As previously discussed in the chapter about , jOOQ does not rely on an internal state of any JDBC object, which is "externalised" by Javadoc. Instead, it has a straight-forward API allowing you to do the above in a one-liner:

    - + > results = create.fetchMany("sp_help 'author'");]]> @@ -5516,7 +5516,7 @@ List> results = create.fetchMany("sp_help 'author'");]]>
    Some queries take very long to execute, yet they are not crucial for the continuation of the main program. For instance, you could be generating a complicated report in a Swing application, and while this report is being calculated in your database, you want to display a background progress bar, allowing the user to pursue some other work. This can be achived simply with jOOQ, by creating a , a type that extends . An example is given here:

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(); @@ -5532,7 +5532,7 @@ Result result = future.get();]]>

    Note, that instead of letting jOOQ spawn a new thread, you can also provide jOOQ with your own :

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(service);]]> @@ -5544,7 +5544,7 @@ FutureResult future = create.selectFrom(BOOK).where(... complex pred

    When interacting with legacy applications, you may prefer to have jOOQ return a , rather than jOOQ's own types. This can be done simply, in two ways:

    - + cursor = create.fetchLazy(rs);]]>

    Apart from a few extra features (see the manual's section about and ), jOOQ only supports basic types as supported by the JDBC API. In your application, you may choose to transform these data types into your own ones, without writing too much boiler-plate code. This can be done using jOOQ's types. A converter essentially allows for two-way conversion between two Java data types <T> and <U>. By convention, the <T> type corresponds to the type in your database whereas the <U> type corresponds to your own user type. The Converter API is given here:

    - + extends Serializable { /** @@ -5612,12 +5612,12 @@ Cursor cursor = create.fetchLazy(rs);]]>

    Such a converter can be used in many parts of the jOOQ API. Some examples have been illustrated in the manual's section about .

    - +

    A Converter for GregorianCalendar

    Here is a some more elaborate example involving a Converter for :

    - + { @@ -5648,12 +5648,12 @@ public class CalendarConverter implements Converter dates1 = create.selectFrom(BOOK).fetch().getValues(BOOK.PUBLISHING_DATE, new CalendarConverter()); List dates2 = create.selectFrom(BOOK).fetch(BOOK.PUBLISHING_DATE, new CalendarConverter()); ]]> - +

    Enum Converters

    jOOQ ships with a built-in default , that you can use to map VARCHAR values to enum literals or NUMBER values to enum ordinals (both modes are supported). Let's say, you want to map a YES / NO / MAYBE column to a custom Enum:

    - + - +

    Using Converters in generated source code

    jOOQ also allows for generated source code to reference your own custom converters, in order to permanently replace a <T> type by your own, custom <U> type. See the manual's section about for details. @@ -5683,7 +5683,7 @@ for (BookRecord book : create.selectFrom(BOOK).fetch()) {

    - +
    Static statements vs. Prepared Statements @@ -5693,7 +5693,7 @@ for (BookRecord book : create.selectFrom(BOOK).fetch()) {

    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 factory will be executed as static statements, with all bind values inlined. An example is given here:

    - + @@ -5722,7 +5722,7 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    Whichever aproach is more optimal for you cannot be decided by jOOQ. In most cases, prepared statements are probably better. But you always have the option of forcing jOOQ to render inlined bind values.

    - +

    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 @@ -5762,22 +5762,22 @@ try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO author(id stmt.setString(2, "Erich"); stmt.setString(3, "Gamma"); stmt.addBatch(); - + stmt.setInt(1, 2); stmt.setString(2, "Richard"); stmt.setString(3, "Helm"); stmt.addBatch(); - + stmt.setInt(1, 3); stmt.setString(2, "Ralph"); stmt.setString(3, "Johnson"); stmt.addBatch(); - + stmt.setInt(1, 4); stmt.setString(2, "John"); stmt.setString(3, "Vlissides"); stmt.addBatch(); - + int[] result = stmt.executeBatch(); }]]> @@ -5786,7 +5786,7 @@ try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO author(id

    jOOQ supports executing queries in batch mode as follows:

    - + Instead of actually phrasing a select statement, you can also use the convenience methods:

    - + - +

    Inlining sequence references in SQL

    You can inline sequence references in jOOQ SQL statements. The following are examples of how to do that:

    - + The general distinction between (stored) procedures and (stored) functions can be summarised like this:

    - +

    Procedures

    • Are called using JDBC CallableStatement
    • Have no return value
    • Usually support OUT parameters
    - +

    Functions

    • Can be used in SQL statements
    • Have a return value
    • Usually don't support OUT parameters
    - +

    Exceptions to these rules

    • DB2, H2, and HSQLDB don't allow for JDBC escape syntax when calling functions. Functions must be used in a SELECT statement
    • @@ -5888,19 +5888,19 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

      To simplify things a little bit, jOOQ handles both procedures and functions the same way, using a more general type.

      - +

      Using jOOQ for standalone calls to stored procedures and functions

      If you're using jOOQ's , it will generate objects for you. Let's consider the following example:

      - +

      The generated artefacts can then be used as follows:

      - + - +

      But you can also call the procedure using a generated convenience method in a global Routines class:

      @@ -5927,7 +5927,7 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]>

      For more details about for procedures, see the manual's section about .

      - +

      Inlining stored function references in SQL

      Unlike procedures, functions can be inlined in SQL statements to generate or , if you're using . Assume you have a function like this: @@ -5935,11 +5935,11 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]> - +

      The generated artefacts can then be used as follows:

      - + - +

      For more info about inlining stored function references in SQL statements, please refer to the manual's section about .

      @@ -5979,7 +5979,7 @@ create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]>

      Oracle UDTs can have object-oriented structures including member functions and procedures. With Oracle, you can do things like this:

      - +

      CRUD always uses the same patterns, regardless of the nature of underlying tables. This again, leads to a lot of boilerplate code, if you have to issue your statements yourself. Like Hibernate / JPA and other ORMs, jOOQ facilitates CRUD using a specific API involving types.

      - +

      Primary keys and updatability

      In normalised databases, every table has a primary key by which a tuple/record within that table can be uniquely identified. In simple cases, this is a (possibly auto-generated) number called ID. But in many cases, primary keys include several non-numeric columns. An important feature of such keys is the fact that in most databases, they are enforced using an index that allows for very fast random access to the table. A typical way to access / modify / delete a book is this:

      - + - +

      Normalised databases assume that a primary key is unique "forever", i.e. that a key, once inserted into a table, will never be changed or re-inserted after deletion. In order to use jOOQ's operations correctly, you should design your database accordingly.

      - +

      Main UNIQUE keys

      In SQL, a primary key is always also a unique key. In fact, unique keys have very similar properties as primary keys. For instance, they can be referenced from other tables' foreign keys in most databases. In the absence of a formal primary key, jOOQ assumes that the first unique key it encounters will serve as a primary key substitute. This is called the "main key" in jOOQ. In other words, a main key is: @@ -6321,7 +6321,7 @@ DELETE FROM BOOK WHERE ID = 5;]]>

    • The primary key, if available
    • The first unique key, otherwise
    - +

    For simplicity, the term "primary key" will be used in the sense of such a "main unique key" in this manual.

    @@ -6334,7 +6334,7 @@ DELETE FROM BOOK WHERE ID = 5;]]>

    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:

    - + - +

    See the manual's section about for some more insight on "attached" objects.

    - +

    Storing

    Storing a record will perform an or an . In general, new records are always inserted, whereas records loaded from the database are always updated. This is best visualised in code: @@ -6373,7 +6373,7 @@ BookRecord book2 = create.fetchOne(BOOK, BOOK.ID.equal(id)); // Update the record: UPDATE BOOK SET TITLE = 'Animal Farm' WHERE ID = [id] book2.setTitle("Animal Farm"); book2.store();]]> - +

    Some remarks about storing:

    @@ -6383,18 +6383,18 @@ book2.store();]]>
  • When loading records from , jOOQ will assume the record is a new record. It will hence attempt to INSERT it.
  • When you activate , storing a record may fail, if the underlying database record has been changed in the mean time.
  • - +

    Deleting

    Deleting a record will remove it from the database. Here's how you delete records:

    - + - +

    Refreshing

    Refreshing a record from the database means that jOOQ will issue a to refresh all record values that are not the primary key. This is particularly useful when you use jOOQ's feature, in case a modified record is "stale" and cannot be stored to the database, because the underlying database record has changed in the mean time. @@ -6413,7 +6413,7 @@ book.refresh();]]>

    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 :

    - + Many databases support the concept of IDENTITY values, or key values. This is reflected by JDBC's method. jOOQ abstracts using this method as many databases and JDBC drivers behave differently with respect to generated keys. Let's assume the following SQL Server BOOK table:

    - +

    If you're using jOOQ's , the above table will generate a with an IDENTITY column. This information is used by jOOQ internally, to update IDs after calling :

    - +

    When using jOOQ's along with its , generated records can have navigation methods contained in them, if properly . These navigation methods allow for "navigating" inbound or outbound foreign key references by executing an appropriate query. An example is given here:

    - + books = author.fetchBookList();]]>

    These methods are safe for use with several foreign keys referencing the same tables:

    - + books = coAuthor.fetchBookListByCoAuthorId();]]>

    Tables without UNIQUE keys are considered non-updatable by jOOQ, as jOOQ has no way of uniquely identifying such a record within the database. If you're using jOOQ's , such tables will generate classes, instead of classes. When you fetch from such a table, the returned records will not allow for calling any of the methods.

    - +

    Note, that some databases use internal rowid or object-id values to identify such records. jOOQ does not support these vendor-specific record meta-data.

    @@ -6596,7 +6596,7 @@ List books = coAuthor.fetchBookListByCoAuthorId();]]>
    - +

    Optimised optimistic locking using TIMESTAMP fields

    If you're using jOOQ's , you can take indicate TIMESTAMP or UPDATE COUNTER fields for every generated table in the . Let's say we have this table:

    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:

    - +

    As before, without the added TIMESTAMP column, optimistic locking is transparent to the API.

    - +

    Optimised optimistic locking using VERSION fields

    Instead of using TIMESTAMPs, you may also use numeric VERSION fields, containing version numbers that are incremented by jOOQ upon store() calls. @@ -6665,7 +6665,7 @@ book2.store();]]>

    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:

    - + books = create.fetch(BOOK); @@ -6690,7 +6690,7 @@ create.batchStore(books);]]>

    If you're using jOOQ's , you can configure it to generate and DAOs for you. jOOQ then generates one DAO per , i.e. per table with a single-column primary key. Generated DAOs implement a common jOOQ type called . This type contains the following methods:

    - + corresponds to the DAO's related table //

    corresponds to the DAO's related generated POJO type // corresponds to the DAO's related table's primary key type. @@ -6701,23 +6701,23 @@ public interface DAO, P, T> { void insert(P object) throws DataAccessException; void insert(P... objects) throws DataAccessException; void insert(Collection

    objects) throws DataAccessException; - + // These methods allow for updating POJOs based on their primary key void update(P object) throws DataAccessException; void update(P... objects) throws DataAccessException; void update(Collection

    objects) throws DataAccessException; - + // These methods allow for deleting POJOs based on their primary key void delete(P... objects) throws DataAccessException; void delete(Collection

    objects) throws DataAccessException; void deleteById(T... ids) throws DataAccessException; void deleteById(Collection ids) throws DataAccessException; - + // These methods allow for checking record existence boolean exists(P object) throws DataAccessException; boolean existsById(T id) throws DataAccessException; long count() throws DataAccessException; - + // These methods allow for retrieving POJOs by primary key or by some other field List

    findAll() throws DataAccessException; P findById(T id) throws DataAccessException; @@ -6746,7 +6746,7 @@ public class BookDao extends DAOImpl {

    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:

    - +

    With jOOQ, it's simple. All of jOOQ's exceptions are "system exceptions", hence they are all unchecked.

    - +

    jOOQ's DataAccessException

    jOOQ uses its own to wrap any underlying that might have occurred. Note that all methods in jOOQ that may cause such a DataAccessException document this both in the Javadoc as well as in their method signature. @@ -6795,7 +6795,7 @@ bookDao.delete(book);]]>

  • InvalidResultException: An operation was performed expecting only one result, but several results were returned.
  • MappingException: Something went wrong when loading a record from a or when mapping a record into a POJO
  • - +

    Override jOOQ's exception handling

    The following section about documents means of overriding jOOQ's exception handling, if you wish to deal separately with some types of constraint violations, or if you raise business errors from your database, etc. @@ -6827,11 +6827,11 @@ public class StatisticsListener extends DefaultExecuteListener { public void start(ExecuteContext ctx) { synchronized (STATISTICS) { Integer count = STATISTICS.get(ctx.type()); - + if (count == null) { count = 0; } - + STATISTICS.put(ctx.type(), count + 1); } } @@ -6885,7 +6885,7 @@ for (ExecuteType type : ExecuteType.values()) {

    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:

    - + @@ -6903,7 +6903,7 @@ for (ExecuteType type : ExecuteType.values()) {

    With the above configuration, let's fetch some data with jOOQ

    - + @@ -6952,7 +6952,7 @@ Finishing : Total: 4.814ms, +3.375ms
  • 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
  • - +

    Optimise wisely

    Don't be put off by the above paragraphs. You should optimise wisely, i.e. only in places where you really need very high throughput to your database. jOOQ's overhead compared to plain JDBC is typically less than 1ms per query. @@ -7009,7 +7009,7 @@ Finishing : Total: 4.814ms, +3.375ms

    You need to tell jOOQ some things about your database connection. Here's an example of how to do it for an Oracle database

    - + @@ -7018,7 +7018,7 @@ Finishing : Total: 4.814ms, +3.375ms jdbc:oracle:thin:@[your jdbc connection parameters] [your database user] [your database password] - + user[db-user] @@ -7096,13 +7096,13 @@ Finishing : Total: 4.814ms, +3.375ms

    Code generation works by calling this class with the above property file as argument.

    - + org.jooq.util.GenerationTool /jooq-config.xml

    Be sure that these elements are located on the classpath:

    - +
    • The XML configuration file
    • jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar
    • @@ -7159,7 +7159,7 @@ Finishing : Total: 4.814ms, +3.375ms

      You can also use an ant task to generate your classes. As a rule of thumb, remove the dots "." and dashes "-" from the .properties file's property names to get the ant task's arguments:

      - + @@ -7425,7 +7425,7 @@ public class AsInDatabaseStrategy extends DefaultGeneratorStrategy { optimistic locking (several Java regular expressions, separated by comma). See UpdatableRecord.store() and UpdatableRecord.delete() for details --> REC_TIMESTAMP - + @@ -7555,12 +7555,12 @@ public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {
    • Tables.java: This file contains all table objects in the form of static member references to the actual singleton object
    • UDTs.java: This file contains all UDT objects in the form of static member references to the actual singleton object
    - +

    Referencing global artefacts

    When referencing global artefacts from your client application, you would typically static import them as such:

    - + @@ -7582,7 +7582,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate a implementation that looks like this:

    - + { // The singleton instance @@ -7598,7 +7598,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE) public Book as(java.lang.String alias) { return new Book(alias); } - + // [...] }]]> @@ -7615,7 +7615,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)
  • instanceFields: This flag controls the "static" keyword on table columns, as well as aliasing convenience
  • records: The generated record type is referenced from tables allowing for type-safe single-table record fetching
  • - +

    Flags controlling table generation

    Table generation cannot be deactivated @@ -7629,7 +7629,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate an implementation that looks like this:

    - + - +

    Flags influencing generated records

    These flags from the influence generated records: @@ -7686,7 +7686,7 @@ implements IBook {

  • interfaces: If interfaces are generated, records will implement them
  • jpaAnnotations: JPA annotations are used on generated records
  • - +

    Flags controlling record generation

    Record generation can be deactivated using the records flag @@ -7700,7 +7700,7 @@ implements IBook {

    Every table in your database will generate a POJO implementation that looks like this:

    - + - +

    Flags influencing generated POJOs

    These flags from the influence generated POJOs: @@ -7749,7 +7749,7 @@ public class Book implements java.io.Serializable

  • jpaAnnotations: JPA annotations are used on generated records
  • validationAnnotations: JSR-303 validation annotations are used on generated records
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the pojos flag @@ -7763,16 +7763,16 @@ public class Book implements java.io.Serializable

    Every table in your database will generate an interface that looks like this:

    - + - +

    Flags influencing generated interfaces

    These flags from the influence generated interfaces: @@ -7781,7 +7781,7 @@ public class Book implements java.io.Serializable

  • dateAsTimestamp: This influences all relevant getters and setters
  • unsignedTypes: This influences all relevant getters and setters
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the interfaces flag @@ -7796,7 +7796,7 @@ public class Book implements java.io.Serializable

    Every table in your database will generate a implementation that looks like this:

    - + { // Generated constructors @@ -7820,10 +7820,10 @@ public class Book implements java.io.Serializable public List fetchByAuthorId(Integer... values) { return fetch(BOOK.AUTHOR_ID, values); } - + // [...] }]]> - +

    Flags controlling DAO generation

    DAO generation can be activated using the daos flag @@ -7837,13 +7837,13 @@ public class Book implements java.io.Serializable

    Every sequence in your database will generate a implementation that looks like this:

    - + S_AUTHOR_ID = new SequenceImpl("S_AUTHOR_ID", TEST, SQLDataType.INTEGER); }]]> - +

    Flags controlling sequence generation

    Sequence generation cannot be deactivated @@ -7881,7 +7881,7 @@ public class Book implements java.io.Serializable public BigDecimal getResult() { return getValue(RESULT); } - + // [...] }]]> @@ -7903,7 +7903,7 @@ public class Book implements java.io.Serializable

    Every UDT in your database will generate a implementation that looks like this:

    - + { // The singleton UDT instance @@ -7916,10 +7916,10 @@ public class Book implements java.io.Serializable createField("CITY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); public static final UDTField COUNTRY = createField("COUNTRY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); - + // [...] }]]> - +

    Besides the implementation, a implementation is also generated

    @@ -7934,7 +7934,7 @@ public class Book implements java.io.Serializable public String getCity() {...} public void setCountry(String value) {...} public String getCountry() {...} - + // [...] }]]> @@ -7959,7 +7959,7 @@ public class Book implements java.io.Serializable

    As previously discussed, you can configure master data tables as follows:

    - + @@ -7981,7 +7981,7 @@ public class Book implements java.io.Serializable

    The results of this will be a Java enum that looks similar to this:

    - + { /** @@ -8015,7 +8015,7 @@ public class Book implements java.io.Serializable

    In the above example, you can see how the configured primary key is mapped to the id member, the configured literal column is mapped to the cd member and the configured description member is mapped to the description member and output as Javadoc. In other words, LANGUAGE is a table with 4 rows and at least three columns.

    - +

    The general contract is that there must be

    @@ -8040,7 +8040,7 @@ public class Book implements java.io.Serializable

    Which can then be used in the BookRecord directly:

    - + { // [...] @@ -8188,7 +8188,7 @@ create.selectFrom(AUTHOR)
    • Google Cloud SQL (MySQL)
    - +

    Databases planned for support

    Any of the following databases might be available in the future @@ -8202,7 +8202,7 @@ create.selectFrom(AUTHOR)

  • Sybase SQL Anywhere OnDemand
  • Teradata
  • - +

    Databases being watched

    Any of the following databases are being observed for a potential integration @@ -8237,7 +8237,7 @@ create.selectFrom(AUTHOR) This chapter should document the most important notes about SQL, JDBC and jOOQ data types.

    - +
    BLOBs and CLOBs @@ -8247,7 +8247,7 @@ create.selectFrom(AUTHOR)

    - +
    Unsigned integer types @@ -8271,7 +8271,7 @@ create.selectFrom(AUTHOR)
    - +
    INTERVAL data types @@ -8282,11 +8282,11 @@ create.selectFrom(AUTHOR)
  • YEAR TO MONTH: This interval type models a number of months and years
  • DAY TO SECOND: This interval type models a number of days, hours, minutes, seconds and milliseconds
  • - +

    Both interval types ship with a variant of subtypes, such as DAY TO HOUR, HOUR TO SECOND, etc. jOOQ models these types as Java objects extending : (where Number.intValue() corresponds to the absolute number of months) and (where Number.intValue() corresponds to the absolute number of milliseconds)

    - +

    Interval arithmetic

    In addition to the documented previously, interval arithmetic is also supported by jOOQ. Essentially, the following operations are supported: @@ -8301,7 +8301,7 @@ create.selectFrom(AUTHOR)

    - +
    XML data types @@ -8310,7 +8310,7 @@ create.selectFrom(AUTHOR)

    - +
    Geospacial data types @@ -8320,7 +8320,7 @@ create.selectFrom(AUTHOR)

    - +
    CURSOR data types @@ -8329,22 +8329,22 @@ create.selectFrom(AUTHOR)

    > cursor;]]> - +

    In fact, such a cursor will be fetched immediately by jOOQ and wrapped in an object.

    - +
    ARRAY and TABLE data types

    The SQL standard specifies ARRAY data types, that can be mapped to Java arrays as such:

    - + intArray;]]> - +

    The above array type is supported by these SQL dialects:

    @@ -8353,7 +8353,7 @@ create.selectFrom(AUTHOR)
  • HSQLDB
  • Postgres
  • - +

    Oracle typed arrays

    Oracle has strongly-typed arrays and table types (as opposed to the previously seen anonymously typed arrays). These arrays are wrapped by types. diff --git a/jOOQ-manual/src/main/resources/org/jooq/web/manual-2.6.xml b/jOOQ-manual/src/main/resources/org/jooq/web/manual-2.6.xml index c71bd4206c..b795de6f71 100644 --- a/jOOQ-manual/src/main/resources/org/jooq/web/manual-2.6.xml +++ b/jOOQ-manual/src/main/resources/org/jooq/web/manual-2.6.xml @@ -86,30 +86,30 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ is different

    SQL was never meant to be abstracted. To be confined in the narrow boundaries of heavy mappers, hiding the beauty and simplicity of relational data. SQL was never meant to be object-oriented. SQL was never meant to be anything other than... SQL!

    - + - +
    Getting started with jOOQ @@ -222,12 +222,12 @@ and Maintenance Agreement for more details: http://www.jooq.org/licensing

    This section helps you correctly interpret this manual in the context of jOOQ.

    - +

    Code blocks

    The following are code blocks:

    - + @@ -237,7 +237,7 @@ org.jooq.property=value]]>

    These are useful to provide examples in code. Often, with jOOQ, it is even more useful to compare SQL code with its corresponding Java/jOOQ code. When this is done, the blocks are aligned side-by-side, with SQL usually being on the left, and Java usually being on the right:

    - +

    The contents of code blocks follow conventions, too. If nothing else is mentioned next to any given code block, then the following can be assumed:

    - - + +

    jOOQ allows to override runtime behaviour using . If nothing is specified, the default runtime settings are assumed.

    - +

    Sample database

    See the manual's section about to learn more about the sample database. @@ -306,7 +306,7 @@ CREATE TABLE book ( title VARCHAR2(400) NOT NULL, published_in NUMBER(7) NOT NULL, language_id NUMBER(7) NOT NULL, - + CONSTRAINT fk_book_author FOREIGN KEY (author_id) REFERENCES author(id), CONSTRAINT fk_book_language FOREIGN KEY (language_id) REFERENCES language(id) ) @@ -319,7 +319,7 @@ CREATE TABLE book_to_book_store ( name VARCHAR2(400) NOT NULL, book_id INTEGER NOT NULL, stock INTEGER, - + PRIMARY KEY(name, book_id), CONSTRAINT fk_b2bs_book_store FOREIGN KEY (name) REFERENCES book_store (name) ON DELETE CASCADE, CONSTRAINT fk_b2bs_book FOREIGN KEY (book_id) REFERENCES book (id) ON DELETE CASCADE @@ -346,7 +346,7 @@ CREATE TABLE book_to_book_store (

    Effectively, jOOQ was originally designed to replace any other database abstraction framework short of the ones handling connection pooling and transaction management (see also the )

    - +

    Use jOOQ the way you prefer

    ... but open source is community-driven. And the community has shown various ways of using jOOQ that diverge from its original intent. Some use cases encountered are: @@ -357,7 +357,7 @@ CREATE TABLE book_to_book_store (

  • Using jOOQ for SQL building and Spring Data for SQL execution
  • Using jOOQ without the to build the basis of a framework for dynamic SQL execution.
  • - +

    The following sections explain about various use cases for using jOOQ in your application.

    @@ -370,7 +370,7 @@ CREATE TABLE book_to_book_store (

    This is the most simple of all use cases, allowing for construction of valid SQL for any database. In this use case, you will not use and probably not even . Instead, you'll use jOOQ to wrap strings, literals and other user-defined objects into an object-oriented, type-safe AST modelling your SQL statements. An example is given here:

    - + - +

    The SQL string that you can generate as such can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools.

    @@ -407,7 +407,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID)) .where(BOOK.PUBLISHED_IN.equal(1948)) .getSQL();]]> - +

    The SQL string that you can generate as such can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools.

    @@ -427,7 +427,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    Instead of any tool mentioned in the previous chapters, you can also use jOOQ directly to execute your jOOQ-generated SQL statements. This will add a lot of convenience on top of the previously discussed API for typesafe SQL construction, when you can re-use the information from generated classes to fetch records and custom data types. An example is given here:

    - + result = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .from(BOOK) @@ -476,10 +476,10 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { // Skip previously distinguished authors if ((int) author.getDistinguished() == 1) continue; - + // Check if the author has written more than 5 books if (author.fetchChildren(Keys.FK_BOOK_AUTHOR).size() > 5) { - + // Mark the author as a "distinguished" author author.setDistinguished(1); author.store(); @@ -496,7 +496,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {
    - +
    jOOQ for PROs @@ -534,7 +534,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { This manual section is intended for new users, to help them get a running application with jOOQ, quickly.

    - +
    Step 1: Preparation @@ -543,7 +543,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { If you haven't already downloaded it, download jOOQ:
    http://www.jooq.org/download

    - +

    Alternatively, you can create a Maven dependency:

    @@ -564,14 +564,14 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    - +
    Step 2: Your database

    We're going to create a database called "guestbook" and a corresponding "posts" table. Connect to MySQL via your command line client and type the following:

    - + CREATE DATABASE guestbook; CREATE TABLE `posts` ( @@ -583,7 +583,7 @@ CREATE TABLE `posts` ( );
    - +
    Step 3: Code generation @@ -595,7 +595,7 @@ CREATE TABLE `posts` (

    The easiest way to generate a schema is to copy the jOOQ jar files (there should be 3) and the MySQL Connector jar file to a temporary directory. Then, create a guestbook.xml that looks like this:

    - + @@ -667,12 +667,12 @@ CREATE TABLE `posts` (

    There are two things to note:

    - +
    1. The prefix slash before the /library.xml. Even though it's in our working directory, we need to prepend a slash, as the configuration file is loaded from the classpath.
    2. The "trailing" period in the classpath: .. We need this because we want the current directory on the classpath in order to find the above /library.xml file at the root of your classpath.
    - +

    Replace the filenames with your actual filenames. In this example, jOOQ {jooq-version} is being used. If everything has worked, you should see this in your console output:

    @@ -737,14 +737,14 @@ Nov 1, 2011 7:25:08 PM org.jooq.impl.JooqLogger info INFO: GENERATION FINISHED! : Total: 791.688ms, +9.143ms
    - +
    Step 4: Connect to your database

    Let's just write a vanilla main class in the project containing the generated classes:

    - +
    - +
    Step 5: Querying

    Let's add a simple query:

    - + result = create.select().from(POSTS).fetch();]]> @@ -800,7 +800,7 @@ Result result = create.select().from(POSTS).fetch();]]>

    - +
    Step 6: Iterating @@ -819,7 +819,7 @@ Result result = create.select().from(POSTS).fetch();]]>

    The full program should now look like this:

    - +
    - +
    Step 7: Explore! @@ -925,7 +925,7 @@ public class Main {
    - +
    jOOQ and Scala @@ -938,7 +938,7 @@ public class Main {
  • Optioanl ";" at the end of a Scala statement
  • Type inference using "var" and "val" keywords
  • - +

    But jOOQ also leverages other useful Scala features, such as

    @@ -946,11 +946,11 @@ public class Main {
  • implicit defs for operator overloading
  • Scala Macros (soon to come)
  • - +

    A short example jOOQ application in Scala might look like this:

    - +
    - +
    Dependencies @@ -1010,7 +1010,7 @@ object Test { //
  • Small libraries with compatible licenses are incorporated into jOOQ (jOOR, jOOU, OpenCSV, json simple, commons-lang)
  • javax.persistence and javax.validation will be needed if you activate the relevant
  • - +

    Build your own

    In order to build jOOQ, please download the sources from https://github.com/jOOQ/jOOQ and use Maven to build it, preferably in Eclipse. @@ -1104,7 +1104,7 @@ Result result = select.fetch();]]> CONNECT BY clause to the query */ -@Support({ CUBRID }) +@Support({ CUBRID, ORACLE }) SelectConnectByConditionStep connectBy(Condition condition);]]>

    jOOQ API methods which are not annotated with the annotation, or which are annotated with the Support annotation, but without any SQL dialects can be safely used in all SQL dialects. An example for this is the factory method: @@ -1125,7 +1125,7 @@ SelectSelectStep select(Field... fields);]]>

    Nevertheless, the IS DISTINCT FROM predicate is supported in all dialects, as its semantics can be expressed with an equivalent . For more details, see the manual's section about the .

    - +

    jOOQ and the Oracle SQL dialect

    Oracle SQL is much more expressive than many other SQL dialects. It features many unique keywords, clauses and functions that are out of scope for the SQL standard. Some examples for this are @@ -1199,7 +1199,7 @@ Factory create = new Factory(connection, dialect, settings);]]>

    - +
    Runtime schema and table mapping @@ -1207,7 +1207,7 @@ Factory create = new Factory(connection, dialect, settings);]]>

    You may wish to design your database in a way that you have several instances of your schema. This is useful when you want to cleanly separate data belonging to several customers / organisation units / branches / users and put each of those entities' data in a separate database or schema.

    - +

    In our AUTHOR example this would mean that you provide a book reference database to several companies, such as My Book World and Books R Us. In that case, you'll probably have a schema setup like this:

    @@ -1237,7 +1237,7 @@ create.selectFrom(AUTHOR).fetch();

    The query executed with a Factory equipped with the above mapping will in fact produce this SQL statement:

    - + SELECT * FROM MY_BOOK_WORLD.AUTHOR

    Even if AUTHOR was generated from DEV. @@ -1330,7 +1330,7 @@ create.selectFrom(AUTHOR).fetch();

    The query executed with a Factory equipped with the above mapping will in fact produce this SQL statement:

    - + SELECT * FROM MY_BOOK_WORLD.MY_APP__AUTHOR

    @@ -1388,7 +1388,7 @@ MySQLFactory create = new MySQLFactory(connection);

    Here is an example to illustrate what that means:

    - +

    Note, that for historic reasons, the DSL API mixes mutable and immutable behaviour with respect to the internal representation of the being constructed. While creating , (such as functions) assumes immutable behaviour, creating does not. In other words, the following can be said:

    - +

    Read more about aliasing in the manual's section about .

    - +

    More advanced table expressions

    Apart from simple tables, you can pass any arbitrary to the jOOQ FROM clause. This may include in Oracle: @@ -1903,12 +1903,12 @@ ORDER BY 1]]> Note that this syntax is also supported in the CUBRID database.

    - +

    ORDER SIBLINGS

    The Oracle database allows for specifying a SIBLINGS keyword in the . Instead of ordering the overall result, this will only order siblings among each other, keeping the hierarchy intact. An example is given here:

    - + - +
    @@ -1972,7 +1972,7 @@ GROUP BY ()]]> - +

    ROLLUP(), CUBE() and GROUPING SETS()

    Some databases support the SQL standard grouping functions and some extensions thereof. See the manual's section about for more details. @@ -1991,7 +1991,7 @@ GROUP BY ()]]>= 2]]>= 2]]> @@ -2126,8 +2126,8 @@ ORDER BY CASE TITLE

    The SQL standard defines that a "query expression" can be ordered, and that query expressions can contain , whose subqueries cannot be ordered. While this is defined as such in the SQL standard, many databases allowing for the non-standard in one way or another, do not adhere to this part of the SQL standard. Hence, jOOQ allows for ordering all SELECT statements, regardless whether they are constructed as a part of a UNION or not. Corner-cases are handled internally by jOOQ, by introducing synthetic subselects to adhere to the correct syntax, where this is needed.

    - - + +

    Oracle's ORDER SIBLINGS BY clause

    jOOQ also supports Oracle's SIBLINGS keyword to be used with ORDER BY clauses for @@ -2176,7 +2176,7 @@ SELECT TOP 1 * FROM BOOK

    Things get a little more tricky in those databases that have no native idiom for OFFSET pagination (actual queries may vary):

    - +

    SQL allows to perform set operations as understood in standard set theory on result sets. These operations include unions, intersections, subtractions. For two subselects to be combinable by such a set operator, each subselect must return a of the same arity and type.

    - +

    UNION and UNION ALL

    These operators combine two results into one. While UNION removes all duplicate records resulting from this combination, UNION ALL leaves subselect results as they are. Typically, you should prefer UNION ALL over UNION, if you don't really need to remove duplicates. The following example shows how to use such a UNION operation in jOOQ. @@ -2329,12 +2329,12 @@ UNION ALL SELECT * FROM BOOK WHERE ID = 5]]> - +

    INTERSECT [ ALL ] and EXCEPT [ ALL ]

    INTERSECT is the operation that produces only those s that are returned by both subselects. EXCEPT is the operation that returns only those s that are returned exclusively in the first subselect. Both operators will remove duplicates from their results. The SQL standard allows to specify the ALL keyword for both of these operators as well, but this is hardly supported in any database. jOOQ does not support INTERSECT ALL, EXEPT ALL operations either.

    - +

    jOOQ's set operators and how they're different from standard SQL

    As previously mentioned in the manual's section about the , jOOQ has slightly changed the semantics of these set operators. While in SQL, a subselect may not contain any or (unless you wrap the subselect into a ), jOOQ allows you to do so. In order to select both the youngest and the oldest author from the database, you can issue the following statement with jOOQ (rendered to the MySQL dialect): @@ -2350,7 +2350,7 @@ UNION .union( create.selectFrom(AUTHOR) .orderBy(AUTHOR.DATE_OF_BIRTH.desc()).limit(1));]]> - +

    @@ -2438,7 +2438,7 @@ SELECT 101, 'Alfred', 'Döblin' FROM DUAL;
    create.insertInto(AUTHOR, .set(AUTHOR.ID, 101) .set(AUTHOR.FIRST_NAME, "Alfred") .set(AUTHOR.LAST_NAME, "Döblin"); - +

    As you can see, this syntax is a bit more verbose, but also more type-safe, as every field can be matched with its value. Internally, the two syntaxes are strictly equivalent.

    @@ -2447,7 +2447,7 @@ SELECT 101, 'Alfred', 'Döblin' FROM DUAL;create.insertInto(AUTHOR,

    The MySQL database supports a very convenient way to INSERT or UPDATE a record. This is a non-standard extension to the SQL syntax, which is supported by jOOQ and emulated in other RDBMS, where this is possible (i.e. if they support the SQL standard ). Here is an example how to use the ON DUPLICATE KEY UPDATE clause:

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, update the author's name create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -2456,11 +2456,11 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .set(AUTHOR.LAST_NAME, "Koontz");

    The synthetic ON DUPLICATE KEY IGNORE clause

    - +

    The MySQL database also supports an INSERT IGNORE INTO clause. This is supported by jOOQ using the more convenient SQL syntax variant of ON DUPLICATE KEY IGNORE, which can be equally emulated in other databases using a :

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, ignore the INSERT statement create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -2496,11 +2496,11 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    The INSERT SELECT statement

    - +

    In some occasions, you may prefer the INSERT SELECT syntax, for instance, when you copy records from one table to another:

    - + create.insertInto(AUTHOR_ARCHIVE) .select(create.selectFrom(AUTHOR).where(AUTHOR.DECEASED.isTrue())); @@ -2521,7 +2521,7 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .set(AUTHOR.LAST_NAME, "Hesse") .where(AUTHOR.ID.equal(3));
    - + @@ -2572,7 +2572,7 @@ WHEN NOT MATCHED THEN INSERT (LAST_NAME) VALUES ('Hitchcock')create.

    The H2 database ships with a somewhat less powerful but a little more intuitive syntax for its own version of the MERGE statement. An example more or less equivalent to the previous one can be seen here:

    - + -- Check if there is already an author called 'Hitchcock' -- If there is, rename him to John. If there isn't add him. @@ -2591,7 +2591,7 @@ VALUES ('John', 'Hitchcock')create.mergeInto(AUTHOR, This syntax can be fully emulated by jOOQ for all other databases that support the SQL standard MERGE statement. For more information about the H2 MERGE syntax, see the documentation here:
    http://www.h2database.com/html/grammar.html#merge

    - + @@ -2608,7 +2608,7 @@ VALUES ('John', 'Hitchcock')create.mergeInto(AUTHOR, TRUNCATE TABLE AUTHOR;create.truncate(AUTHOR).execute(); - +

    TRUNCATE is not supported by Ingres and SQLite. jOOQ will execute a DELETE FROM AUTHOR statement instead.

    @@ -2632,7 +2632,7 @@ VALUES ('John', 'Hitchcock')create.mergeInto(AUTHOR,

    Most of the times, when thinking about a you're probably thinking about an actual table in your database schema. If you're using jOOQ's , you will have all tables from your database schema available to you as type safe Java objects. You can then use these tables in SQL , or in other , just like any other table expression. An example is given here:

    - + - +

    The above example shows how AUTHOR and BOOK tables are joined in a . It also shows how you can access by dereferencing the relevant Java attributes of their tables.

    @@ -2679,11 +2679,11 @@ create.select() .where(a.YEAR_OF_BIRTH.greaterThan(1920) .and(a.FIRST_NAME.equal("Paulo"))) .orderBy(b.TITLE);]]>
    - +

    As you can see in the above example, calling as() on generated tables returns an object of the same type as the table. This means that the resulting object can be used to dereference fields from the aliased table. This is quite powerful in terms of having your Java compiler check the syntax of your SQL statements. If you remove a column from a table, dereferencing that column from that table alias will cause compilation errors.

    - +

    Dereferencing columns from other table expressions

    TODO document this @@ -2697,7 +2697,7 @@ create.select()

    The that can be used in are the most powerful and best supported means of creating new in SQL. Informally, the following can be said:

    - + A(colA1, ..., colAn) "join" B(colB1, ..., colBm) "produces" C(colA1, ..., colAn, colB1, ..., colBm)

    @@ -2715,7 +2715,7 @@ create.select()

    jOOQ supports all of these JOIN types (except semi-join and anti-join) directly on any :

    - + table) @@ -2753,9 +2753,9 @@ Table naturalRightOuterJoin(TableLike)]]>

    A can appear almost anywhere a can. Such a "nested SELECT" is often called a "derived table". Apart from many convenience methods accepting objects directly, a SELECT statement can always be transformed into a object using the asTable() method.

    - +

    Example: Scalar subquery

    - + SELECT * FROM BOOK @@ -2822,11 +2822,11 @@ create.select(AUTHOR.ID, books)

    If you are closely coupling your application to an Oracle database, you can take advantage of some Oracle-specific features, such as the PIVOT clause, used for statistical analyses. The formal syntax definition is as follows:

    - + -- SELECT .. FROM table PIVOT (aggregateFunction [, aggregateFunction] FOR column IN (expression [, expression])) -- WHERE .. - +

    The PIVOT clause is available from the type, as pivoting is done directly on a table. Currently, only Oracle's PIVOT clause is supported. Support for SQL Server's slightly different PIVOT clause will be added later. Also, jOOQ may emulate PIVOT for other dialects in the future.

    @@ -2889,7 +2889,7 @@ WHERE NOT EXISTS (

    The SQL standard specifies how SQL databases should implement ARRAY and TABLE types, as well as CURSOR types. Put simply, a CURSOR is a pointer to any materialised . Depending on the cursor's features, this table expression can be scrolled through in both directions, records can be locked, updated, removed, inserted, etc. Often, CURSOR types contain s, whereas ARRAY and TABLE types contain simple scalar values, although that is not a requirement

    - +

    ARRAY types in SQL are similar to Java's array types. They contain a "component type" or "element type" and a "dimension". This sort of ARRAY type is implemented in H2, HSQLDB and Postgres and supported by jOOQ as such. Oracle uses strongly-typed arrays, which means that an ARRAY type (VARRAY or TABLE type) has a name and possibly a maximum capacity associated with it.

    @@ -2968,12 +2968,12 @@ new Factory(SQLDialect.SYBASE ).selectOne().getSQL();]]>

    Column expressions can be used in various SQL clauses in order to refer to one or several columns. This chapter explains how to form various types of column expressions with jOOQ. A particular type of column expression is given in the section about , where an expression may have a degree of more than one.

    - +

    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:

    - + field1 = BOOK.TITLE; @@ -3026,7 +3026,7 @@ ORDER BY BOOK.TITLE]]> Just like , columns can be renamed using aliases. Here is an example:

    - + SELECT FIRST_NAME || ' ' || LAST_NAME author, COUNT(*) books FROM AUTHOR JOIN BOOK ON AUTHOR.ID = AUTHOR_ID @@ -3035,18 +3035,18 @@ GROUP BY FIRST_NAME, LAST_NAME;

    Here is how it's done with jOOQ:

    - + Record record = create.select( concat(AUTHOR.FIRST_NAME, val(" "), AUTHOR.LAST_NAME).as("author"), count().as("books")) .from(AUTHOR) .join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID)) .groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME).fetchAny(); - +

    When you alias Fields like above, you can access those Fields' values using the alias name:

    - + System.out.println("Author : " + record.getValue("author")); System.out.println("Books : " + record.getValue("books")); @@ -3060,7 +3060,7 @@ System.out.println("Books : " + record.getValue("books"));

    Sometimes, this automatic mapping might not be what you needed, or jOOQ cannot know the type of a field. In those cases you would write SQL type CASTs like this:

    - + -- Let's say, your Postgres column LAST_NAME was VARCHAR(30) -- Then you could do this: SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL @@ -3068,27 +3068,27 @@ SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL

    in jOOQ, you can write something like that:

    - + create.select(TAuthor.LAST_NAME.cast(PostgresDataType.TEXT));

    The same thing can be achieved by casting a Field directly to String.class, as TEXT is the default data type in Postgres to map to Java's String

    - + create.select(TAuthor.LAST_NAME.cast(String.class)); - +

    The complete CAST API in Field consists of these three methods:

    - + { // Cast this field to the type of another field Field cast(Field field); - + // Cast this field to a given DataType Field cast(DataType type); - + // Cast this field to the default DataType for a given Class Field cast(Class type); } @@ -3117,13 +3117,13 @@ public class Factory {

    In order to express a SQL query like this one:

    - + SELECT ((1 + 2) * (5 - 3) / 2) % 10 FROM DUAL - +

    You can write something like this in jOOQ:

    - + create.select(val(1).add(2).mul(val(5).sub(3)).div(2).mod(10);

    Datetime arithmetic expressions

    @@ -3144,14 +3144,14 @@ public class Factory { - +
    String concatenation

    The SQL standard defines the concatenation operator to be an infix operator, similar to the ones we've seen in the chapter about . This operator looks like this: ||. Some other dialects do not support this operator, but expect a concat() function, instead. jOOQ renders the right operator / function, depending on your :

    - + SELECT 'A' || 'B' || 'C' FROM DUAL -- Or in MySQL: @@ -3178,13 +3178,13 @@ create.select(concat("A", "B", "C"));
  • NVL: Get the first non-null value among two arguments.
  • NVL2: Get the second argument if the first is null, or the third argument, otherwise.
  • - +

    Please refer to the for more details.

    - +
    Numeric functions @@ -3194,7 +3194,7 @@ create.select(concat("A", "B", "C"));

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ABS: Get the absolute value of a value.
    • ACOS: Get the arc cosine of a value.
    • @@ -3225,7 +3225,7 @@ create.select(concat("A", "B", "C"));
    • TANH: Get the hyperbolic tangent of a value.
    • TRUNC: Truncate the decimals off a given value.
    - +

    Please refer to the for more details.

    @@ -3250,13 +3250,13 @@ create.select(concat("A", "B", "C"));
  • SHL: Shift bits to the left
  • SHR: Shift bits to the right
  • - +

    Some background about bitwise operation emulation

    As stated before, not all databases support all of these bitwise operations. jOOQ emulates them wherever this is possible. More details can be seen in this blog post:
    http://blog.jooq.org/2011/10/30/the-comprehensive-sql-bitwise-operations-compatibility-list/

    - +
    @@ -3269,7 +3269,7 @@ create.select(concat("A", "B", "C"));

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ASCII: Get the ASCII code of a character.
    • BIT_LENGTH: Get the length of a string in bits.
    • @@ -3290,16 +3290,16 @@ create.select(concat("A", "B", "C"));
    • TRIM: Trim a string on both sides.
    • UPPER: Get a string in upper case letters.
    - +

    Please refer to the for more details.

    - +

    Regular expressions, REGEXP, REGEXP_LIKE, etc.

    Various databases have some means of searching through columns using regular expressions if the does not provide sufficient pattern matching power. While there are many different functions and operators in the various databases, jOOQ settled for the SQL:2008 standard REGEX_LIKE operator. Being an operator (and not a function), you should use the corresponding method on :

    - +

    @@ -3315,7 +3315,7 @@ create.select(concat("A", "B", "C"));

    This is a list of date and time functions supported by jOOQ's :

    - +
    • CURRENT_DATE: Get current date as a DATE object.
    • CURRENT_TIME: Get current time as a TIME object.
    • @@ -3325,7 +3325,7 @@ create.select(concat("A", "B", "C"));
    • TIMESTAMP_ADD: Add a number of days or an interval to a timestamp.
    • TIMESTAMP_DIFF: Get the difference as an INTERVAL DAY TO SECOND between two dates.
    - +

    Intervals in jOOQ

    jOOQ fills a gap opened by JDBC, which neglects an important SQL data type as defined by the SQL standards: INTERVAL types. See the manual's section about for more details. @@ -3470,7 +3470,7 @@ GROUP BY AUTHOR_IDcreate.select(listAgg(BOOK.TITLE, ", ") WindowOverStep rank(); WindowOverStep denseRank(); WindowOverStep percentRank(); - + // Windowing functions WindowIgnoreNullsStep firstValue(Field field); WindowIgnoreNullsStep lastValue(Field field) @@ -3486,7 +3486,7 @@ GROUP BY AUTHOR_IDcreate.select(listAgg(BOOK.TITLE, ", ") // Statistical functions WindowOverStep cumeDist(); WindowOverStep ntile(int number);]]> - +

    SQL distinguishes between various window function types (e.g. "ranking functions"). Depending on the function, SQL expects mandatory PARTITION BY or ORDER BY clauses within the OVER() clause. jOOQ does not enforce those rules for two reasons:

    @@ -3501,14 +3501,14 @@ GROUP BY AUTHOR_IDcreate.select(listAgg(BOOK.TITLE, ", ")

    Here are some simple examples of window functions with jOOQ:

    - + -- Sample uses of ROW_NUMBER() ROW_NUMBER() OVER() ROW_NUMBER() OVER(PARTITION BY 1) ROW_NUMBER() OVER(ORDER BY BOOK.ID) ROW_NUMBER() OVER(PARTITION BY BOOK.AUTHOR_ID ORDER BY BOOK.ID) - + -- Sample uses of FIRST_VALUE FIRST_VALUE(BOOK.ID) OVER() FIRST_VALUE(BOOK.ID IGNORE NULLS) OVER() @@ -3518,14 +3518,14 @@ rowNumber().over() rowNumber().over().partitionByOne() rowNumber().over().partitionBy(BOOK.AUTHOR_ID) rowNumber().over().partitionBy(BOOK.AUTHOR_ID).orderBy(BOOK.ID) - + // Sample uses of firstValue() firstValue(BOOK.ID).over() firstValue(BOOK.ID).ignoreNulls().over() firstValue(BOOK.ID).respectNulls().over()
    - +

    An advanced window function example

    Window functions can be used for things like calculating a "running total". The following example fetches transactions and the running total for every transaction going back to the beginning of the transaction table (ordered by booked_at). Window functions are accessible from the previously seen type using the over() method: @@ -3550,7 +3550,7 @@ firstValue(BOOK.ID).respectNulls().over()

    In the previous chapter about , we have seen the concept of "ordered-set aggregate functions", such as Oracle's LISTAGG(). These functions have a window function / analytical function variant, as well. For example:

    - + SELECT LISTAGG(TITLE, ', ') WITHIN GROUP (ORDER BY TITLE) @@ -3630,7 +3630,7 @@ ORDER BY 1 NULLS LAST, 2 NULLS LAST

    In English, the ROLLUP() grouping function provides N+1 groupings, when N is the number of arguments to the ROLLUP() function. Each grouping has an additional group field from the ROLLUP() argument field list. The results of the second query might look something like this:

    - + GROUPING SETS() and other grouping functions:
    http://msdn.microsoft.com/en-us/library/bb510427(v=sql.105)

    - +

    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:

    - + rollup(Field... fields); Field cube(Field... fields); @@ -3732,7 +3732,7 @@ Field groupingId(Field...);]]>

    MySQL and CUBRID don't know any grouping functions, but they support a WITH ROLLUP clause, that is equivalent to simple ROLLUP() grouping functions. jOOQ emulates ROLLUP() in MySQL and CUBRID, by rendering this WITH ROLLUP clause. The following two statements mean the same:

    - + Some databases support user-defined functions, which can be embedded in any SQL statement, if you're using jOOQ's . Let's say you have the following simple function in Oracle SQL:

    - + The above function will be made available from a generated class. You can use it like any other :

    - + - +

    Note that user-defined functions returning or data types can also be used wherever can be used, if they are

    @@ -3782,7 +3782,7 @@ END echo;

    Some databases support user-defined aggregate functions, which can then be used along with or as . An example for such a database is Oracle. With Oracle, you can define the following OBJECT type (the example was taken from the Oracle 11g documentation):

    - +

    jOOQ's will detect such aggregate functions and generate them differently from regular . They implement the type, as mentioned in the manual's section about . Here's how you can use the SECOND_MAX() aggregate function with jOOQ:

    - + - +
    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 s / rows. jOOQ's allows for the construction of type-safe s up to the degree / arity of 8. Higher-degree s are supported as well, but without any type-safety. types are modelled as follows:

    - + Row1 row(T1 t1) { ... } public static Row2 row(T1 t1, T2 t2) { ... } @@ -3996,7 +3996,7 @@ public static RowN row(Object... values) { ... }]]>

    Row value expressions are incompatible with most other , but they can be used as a basis for constructing various , such as , , or the "degree 2 row value expression only" . See the relevant sections for more details about how to use row value expressions in predicates.

    - +

    Using row value expressions in UPDATE statements

    The also supports a variant where row value expressions are updated, rather than single columns. See the relevant section for more details @@ -4020,7 +4020,7 @@ public static RowN row(Object... values) { ... }]]>

  • The of a
  • The 's ON clause
  • - +

    Boolean types in SQL

    Before SQL:1999, boolean types did not really exist in SQL. They were modelled by 0 and 1 numeric/char values. With SQL:1999, true booleans were introduced and are now supported by most databases. In short, these are possible boolean values: @@ -4114,7 +4114,7 @@ Condition combined2 = combined1.andNot(c); // The left-hand side of the AND NOT

    Here are all boolean operators on the interface:

    - + < to test for being strictly less
  • <= to test for being less or equal
  • - +

    Unfortunately, Java does not support operator overloading, hence these operators are also implemented as methods in jOOQ, like any other SQL syntax elements. The relevant parts of the interface are these:

    - + ); // = (some column expression) eq or equal(Select); // = (some scalar SELECT statement) @@ -4175,7 +4175,7 @@ ge or greaterOrEqual(Select); // >= (some scalar SELECT statement)]]><

    Note that every operator is represented by two methods. A verbose one (such as equal()) and a two-character one (such as eq()). Both methods are the same. You may choose either one, depending on your taste. The manual will always use the more verbose one.

    - +

    NULL in jOOQ's comparison predicates

    jOOQ has a special way of dealing with null bind values, when you pass them to comparison predicates equal() and notEqual(). For convenience, jOOQ will render predicates. @@ -4185,7 +4185,7 @@ ge or greaterOrEqual(Select); // >= (some scalar SELECT statement)]]><

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using comparison predicates:

    - +

    It is interesting to note that the SQL standard defines the in terms of the ANY-quantified predicate. The following two expressions are equivalent:

    - + @@ -4234,7 +4234,7 @@ BOOK.PUBLISHED_IN.greaterThanAll(1920, 1940);]]>

    In SQL, you cannot compare NULL with any value using , as the result would yield NULL again, which is neither TRUE nor FALSE (see also the manual's section about ). In order to test a for NULL, use the NULL predicate as such:

    - +

    If your database does not natively support the DISTINCT predicate, jOOQ emulates it with an equivalent , modelling the above truth table:

    - + The BETWEEN predicate can be seen as syntactic sugar for a pair of . According to the SQL standard, the following two predicates are equivalent:

    - + = [B] AND [A] <= [C]]]> @@ -4315,7 +4315,7 @@ BOOK.PUBLISHED_IN.notBetween(1920).and(1940)]]>

    The SQL standard defines the SYMMETRIC keyword to be used along with BETWEEN to indicate that you do not care which bound of the range is larger than the other. A database system should simply swap range bounds, in case the first bound is greater than the second one. jOOQ supports this keyword as well, emulating it if necessary.

    - +

    The emulation is done trivially:

    - + @@ -4352,7 +4352,7 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]> TITLE NOT LIKE '%abc%']]>
    - +

    Escaping operands with the LIKE predicate

    Often, your pattern may contain any of the wildcard characters "_" and "%", in case of which you may want to escape them. jOOQ does not automatically escape patterns in like() and notLike() methods. Instead, you can explicitly define an escape character as such: @@ -4370,12 +4370,12 @@ BOOK.TITLE.notLike("%The !%-Sign Book%", '!')]]>

    Please refer to your database manual for more details about escaping patterns with the LIKE predicate.

    - +

    jOOQ's convenience methods using the LIKE predicate

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using the LIKE predicate. Typical operations are "contains predicates", "starts with predicates", "ends with predicates", etc. Here is the full convenience API wrapping LIKE predicates:

    - + ) // Construct a NOT IN predicate from a subselect]]><

    A sample IN predicate might look like this:

    - + - +

    NOT IN and NULL values

    Beware that you should probably not have any NULL values in the right hand side of a NOT IN predicate, as the whole expression would evaluate to NULL, which is rarely desired. This can be shown informally using the following reasoning:

    - + -- The following conditional expressions are formally or informally equivalent A NOT IN (B, C) A != ANY(B, C) @@ -4460,7 +4460,7 @@ NULL -- [ANY] AND NULL yields NULL
  • From a using
  • From a using , and from other clauses
  • - +

    An example of an EXISTS predicate can be seen here:

    @@ -4478,7 +4478,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

    - +

    Performance of IN vs. EXISTS

    In theory, the two types of predicates can perform equally well. If your database system ships with a sophisticated cost-based optimiser, it will be able to transform one predicate into the other, if you have all necessary constraints set (e.g. referential constraints, not null constraints). However, in reality, performance between the two might differ substantially. An interesting blog post investigating this topic on the MySQL database can be seen here:
    @@ -4486,7 +4486,7 @@ notExists(create.selectOne().from(BOOK)

    - +
    OVERLAPS predicate @@ -4524,7 +4524,7 @@ row(Date.valueOf('2010-01-01'), new DayToSecond(2)).overlaps(Date.valueOf('2010-

    Unlike the standard (or any database implementing the standard), jOOQ also supports the OVERLAPS predicate for comparing arbitrary . For instance, (1, 3) OVERLAPS (2, 4) will yield true in jOOQ. This is emulated as such

    - +
  • - +

    You'll probably find other examples. If verbosity scares you off, don't worry. The verbose use-cases for jOOQ are rather rare, and when they come up, you do have an option. Just write SQL the way you're used to!

    @@ -4576,7 +4576,7 @@ Condition condition(String sql, Object... bindings); // Construct a condition taking other jOOQ object arguments // Example: condition("a = {0}", val(1)); 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:

    @@ -4634,7 +4634,7 @@ Result fetch(String sql, QueryPart... parts);]]>

    Apart from the general factory methods, plain SQL is also available in various other contexts. For instance, when adding a .where("a = b") clause to a query. Hence, there exist several convenience methods where plain SQL can be inserted usefully. This is an example displaying all various use-cases in one single query:

    - + LAST_NAME = create.field("a.LAST_NAME"); @@ -4693,7 +4693,7 @@ create.select(LAST_NAME, COUNT1, COUNT2) On a JDBC level, you can also reuse the SQL string and prepared statement object instead of constructing it again, as you can bind new values to the prepared statement. jOOQ currently does not cache prepared statements, internally. - +

    The following sections explain how you can introduce bind values in jOOQ, and how you can control the way they are rendered and bound to SQL.

    @@ -4706,7 +4706,7 @@ create.select(LAST_NAME, COUNT1, COUNT2)

    JDBC only knows indexed bind values. A typical example for using bind values with JDBC is this:

    - + With dynamic SQL, keeping track of the number of question marks and their corresponding index may turn out to be hard. jOOQ abstracts this and lets you provide the bind value right where it is needed. A trivial example is this:

    - + 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

    Should you decide to run the above query outside of jOOQ, using your own , you can do so as follows:

    - + select = create.select().from(BOOK).where(BOOK.ID.equal(5)).and(BOOK.TITLE.equal("Animal Farm")); // Render the SQL statement: @@ -4857,7 +4857,7 @@ create.select()

    Special care needs to be taken when using . While jOOQ's API allows you to specify bind values for use with plain SQL, you're not forced to do that. For instance, both of the following queries will lead to the same, valid result:

    - +

    A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] FROM AUTHOR JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID @@ -5022,15 +5022,15 @@ public final void toSQL(RenderContext context) {

    As mentioned in the previous chapter about , there are some elements in the that are used for formatting / pretty-printing rendered SQL. In order to obtain pretty-printed SQL, just use the following :

    - - + +

    And then, use the above factory to render pretty-printed SQL:

    - + A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] WHERE AUTHOR.ID = ? -- [...] @@ -5118,7 +5118,7 @@ public final void bind(BindContext context) throws DataAccessException {

    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:

    - + extends AbstractField {} public abstract class CustomCondition extends AbstractCondition {} public abstract class CustomTable> extends TableImpl {} @@ -5127,7 +5127,7 @@ public abstract class CustomRecord> extends TableRecord

    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 and methods, as discussed before:

    - + 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 showing how to create a field multiplying another field by 2

    - + IDx2 = new CustomField(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(" * ?"); @@ -5164,10 +5164,10 @@ final Field IDx2 = new CustomField(BOOK.ID.getName(), BOOK.ID. @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)); } @@ -5194,7 +5194,7 @@ create.select(IDx2).from(BOOK);]]>

    The above distinction is best explained using an example:

    - +
    - +
    SQL building in Scala

    jOOQ-Scala is a maven module used for leveraging some advanced Scala features for those users that wish to use jOOQ with Scala.

    - +

    Using Scala's implicit defs to allow for operator overloading

    The most obvious Scala feature to use in jOOQ are implicit defs for implicit conversions in order to enhance the type with SQL-esque operators. @@ -5251,7 +5251,7 @@ create.attach(select);]]>

    The following depicts a trait which wraps all fields:

    - + The following depicts a trait which wraps numeric fields:

    - + An example query using such overloaded operators would then look like this:

    - +

    In a previous section of the manual, we've seen how jOOQ can be used to that can be executed with any API including JDBC or ... jOOQ. This section of the manual deals with various means of actually executing SQL with jOOQ.

    - +

    SQL execution with JDBC

    JDBC calls executable objects "". It distinguishes between three types of statements: @@ -5391,7 +5391,7 @@ fetch]]>

    Today, the JDBC API may look weird to users being used to object-oriented design. While statements hide a lot of SQL dialect-specific implementation details quite well, they assume a lot of knowledge about the internal state of a statement. For instance, you can use the method, to add a the prepared statement being created to an "internal list" of batch statements. Instead of returning a new type, this method forces user to reflect on the prepared statement's internal state or "mode".

    - +

    jOOQ is wrapping JDBC

    These things are abstracted away by jOOQ, which exposes such concepts in a more object-oriented way. For more details about jOOQ's batch query execution, see the manual's section about . @@ -5413,7 +5413,7 @@ fetch]]>

  • Both APIs return the number of affected records in non-result queries. JDBC: , jOOQ:
  • Both APIs return a scrollable result set type from result queries. JDBC: , jOOQ:
  • - +

    Differences to JDBC

    Some of the most important differences between JDBC and jOOQ are listed here: @@ -5428,14 +5428,14 @@ fetch]]>

    - +
    Query vs. ResultQuery

    Unlike JDBC, jOOQ has a lot of knowledge about a SQL query's structure and internals (see the manual's section about ). Hence, jOOQ distinguishes between these two fundamental types of queries. While every can be executed, only can return results (see the manual's section about to learn more about fetching results). With plain SQL, the distinction can be made clear most easily:

    - + result = resultQuery.fetch();]]>
  • : Some databases allow for returning many result sets from a single query. JDBC can handle this but it's very verbose. A list of results should be returned instead.
  • : Some queries take too long to execute to wait for their results. You should be able to spawn query execution in a separate process.
  • - +

    Convenience and how ResultQuery, Result, and Record share API

    The term "fetch" is always reused in jOOQ when you can fetch data from the database. An provides many overloaded means of fetching data:

    - +

    Various modes of fetching

    These modes of fetching are also documented in subsequent sections of the manual

    - + fetch(); @@ -5500,7 +5500,7 @@ List> fetchMany(); // Execute a ResultQuery with jOOQ, but return a JDBC ResultSet, not a jOOQ object ResultSet fetchResultSet();]]> - +

    Fetch convenience

    These means of fetching are also available from and APIs @@ -5546,11 +5546,11 @@ ResultSet fetchResultSet();]]>

    These means of fetching are also available from and APIs

    - + Map fetchMap(Field key); Map fetchMap(Field key, Field value); @@ -5587,7 +5587,7 @@ ResultSet fetchResultSet();]]>

    jOOQ understands that SQL is much more expressive than Java, when it comes to the declarative typing of . As a declarative language, SQL allows for creating ad-hoc row value expressions (records with indexed columns) and records (records with named columns). In Java, this is not possible to the same extent. Yet, still, sometimes you wish to use strongly typed records, when you know that you're selecting only from a single table

    - +

    Fetching strongly or weakly typed records

    When fetching data only from a single table, the type is known to jOOQ if you use jOOQ's to generate for your database tables. In order to fetch such strongly typed records, you will have to use the : @@ -5599,7 +5599,7 @@ BookRecord book = create.selectFrom(BOOK).where(BOOK.ID.equal(1)).fetchOne(); // Typesafe field access is now possible: 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:

    @@ -5618,7 +5618,7 @@ System.out.println("Published in: " + book.getPublishedIn());]]>

    By default, jOOQ returns an object, which is essentially a of . Often, you will find yourself wanting to transform this result object into a type that corresponds more to your specific needs. Or you just want to list all values of one specific column. Here are some examples to illustrate those use cases:

    - + titles1 = create.select().from(BOOK).fetch().getValues(BOOK.TITLE); List titles2 = create.select().from(BOOK).fetch(BOOK.TITLE); @@ -5653,7 +5653,7 @@ Map> group4 = create.selectFrom(BOOK).fetchGroups(BO

    In a more functional operating mode, you might want to write callbacks that receive records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + () {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -5688,7 +5688,7 @@ create.selectFrom(BOOK)

    In a more functional operating mode, you might want to write callbacks that map records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + ids = create.selectFrom(BOOK) @@ -5700,12 +5700,12 @@ create.selectFrom(BOOK) return book.getId(); } }); - + // Or more concisely create.selectFrom(BOOK) .orderBy(BOOK.ID) .fetch(new RecordMapper() {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -5727,7 +5727,7 @@ create.selectFrom(BOOK)

    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.

    - +

    Using JPA-annotated POJOs

    jOOQ tries to find JPA annotations on your POJO types. If it finds any, they are used as the primary source for mapping meta-information. Only the annotation is used and understood by jOOQ. An example: @@ -5737,7 +5737,7 @@ create.selectFrom(BOOK) public class MyBook { @Column(name = "ID") public int myId; - + @Column(name = "TITLE") public String myTitle; } @@ -5746,16 +5746,16 @@ public class MyBook { MyBook myBook = create.select().from(BOOK).fetchAny().into(MyBook.class); List myBooks = create.select().from(BOOK).fetch().into(MyBook.class); List myBooks = create.select().from(BOOK).fetchInto(MyBook.class);]]> - +

    Just as with any other JPA implementation, you can put the annotation on any class member, including attributes, setters and getters. Please refer to the Javadoc for more details.

    - +

    Using simple POJOs

    If jOOQ does not find any JPA-annotations, columns are mapped to the "best-matching" constructor, attribute or setter. An example illustrates this:

    - + myBooks = create.select().from(BOOK).fetchInto(MyBook1.class);]]><

    Please refer to the Javadoc for more details.

    - +

    Using "immutable" POJOs

    If jOOQ does not find any default constructor, columns are mapped to the "best-matching" constructor. This allows for using "immutable" POJOs with jOOQ. An example illustrates this:

    - + myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchInto( public class MyBook3 { public final String title; public final int id; - + @ConstructorProperties({ "title", "id"}) public MyBook2(String title, int id) { this.title = title; @@ -5810,7 +5810,7 @@ MyBook3 myBook = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchA List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetch().into(MyBook3.class); List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchInto(MyBook3.class); ]]> - +

    Please refer to the Javadoc for more details.

    @@ -5819,12 +5819,12 @@ List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchI

    jOOQ also allows for fetching data into abstract classes or interfaces, or in other words, "proxyable" types. This means that jOOQ will return a wrapped in a implementing your custom type. An example of this is given here:

    - + - +

    Note: Because of your manual setting of ID = 10, jOOQ's store() method will asume that you want to insert a new record. See the manual's section about for more details on this.

    - +

    Interaction with DAOs

    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: @@ -5891,7 +5891,7 @@ bookDao.update(book); // Delete it again bookDao.delete(book);]]> - +

    More complex data structures

    jOOQ currently doesn't support more complex data structures, the way Hibernate/JPA attempt to map relational data onto POJOs. While future developments in this direction are not excluded, jOOQ claims that generic mapping strategies lead to an enormous additional complexity that only serves very few use cases. You are likely to find a solution using any of jOOQ's various , with only little boiler-plate code on the client side. @@ -5905,7 +5905,7 @@ bookDao.delete(book);]]>

    Unlike JDBC's , jOOQ's does not represent an open database cursor with various fetch modes and scroll modes, that needs to be closed after usage. jOOQ's results are simple in-memory Java objects, containing all of the result values. If your result sets are large, or if you have a lot of network latency, you may wish to fetch records one-by-one, or in small chunks. jOOQ supports a type for that purpose. In order to obtain such a reference, use the method. An example is given here:

    - + cursor = null; @@ -5915,7 +5915,7 @@ try { // Cursor has similar methods as Iterator while (cursor.hasNext()) { BookRecord book = cursor.fetchOne(); - + Util.doThingsWithBook(book); } } @@ -5930,7 +5930,7 @@ finally {

    As a holds an internal reference to an open , it may need to be closed at the end of iteration. If a cursor is completely scrolled through, it will conveniently close the underlying ResultSet. However, you should not rely on that.

    - +

    Cursors ship with all the other fetch features

    Like or , gives access to all of the other fetch features that we've seen so far, i.e. @@ -5972,7 +5972,7 @@ finally {

    The correct (and verbose) way to do this with JDBC is as follows:

    - +

    As previously discussed in the chapter about , jOOQ does not rely on an internal state of any JDBC object, which is "externalised" by Javadoc. Instead, it has a straight-forward API allowing you to do the above in a one-liner:

    - + > results = create.fetchMany("sp_help 'author'");]]> @@ -6015,7 +6015,7 @@ List> results = create.fetchMany("sp_help 'author'");]]>
    Some queries take very long to execute, yet they are not crucial for the continuation of the main program. For instance, you could be generating a complicated report in a Swing application, and while this report is being calculated in your database, you want to display a background progress bar, allowing the user to pursue some other work. This can be achived simply with jOOQ, by creating a , a type that extends . An example is given here:

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(); @@ -6031,7 +6031,7 @@ Result result = future.get();]]>

    Note, that instead of letting jOOQ spawn a new thread, you can also provide jOOQ with your own :

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(service);]]> @@ -6043,7 +6043,7 @@ FutureResult future = create.selectFrom(BOOK).where(... complex pred

    When interacting with legacy applications, you may prefer to have jOOQ return a , rather than jOOQ's own types. This can be done simply, in two ways:

    - + cursor = create.fetchLazy(rs);]]>

    Apart from a few extra features (see the manual's section about and ), jOOQ only supports basic types as supported by the JDBC API. In your application, you may choose to transform these data types into your own ones, without writing too much boiler-plate code. This can be done using jOOQ's types. A converter essentially allows for two-way conversion between two Java data types <T> and <U>. By convention, the <T> type corresponds to the type in your database whereas the <U> type corresponds to your own user type. The Converter API is given here:

    - + extends Serializable { /** @@ -6111,12 +6111,12 @@ Cursor cursor = create.fetchLazy(rs);]]>

    Such a converter can be used in many parts of the jOOQ API. Some examples have been illustrated in the manual's section about .

    - +

    A Converter for GregorianCalendar

    Here is a some more elaborate example involving a Converter for :

    - + { @@ -6147,12 +6147,12 @@ public class CalendarConverter implements Converter dates1 = create.selectFrom(BOOK).fetch().getValues(BOOK.PUBLISHING_DATE, new CalendarConverter()); List dates2 = create.selectFrom(BOOK).fetch(BOOK.PUBLISHING_DATE, new CalendarConverter()); ]]> - +

    Enum Converters

    jOOQ ships with a built-in default , that you can use to map VARCHAR values to enum literals or NUMBER values to enum ordinals (both modes are supported). Let's say, you want to map a YES / NO / MAYBE column to a custom Enum:

    - + - +

    Using Converters in generated source code

    jOOQ also allows for generated source code to reference your own custom converters, in order to permanently replace a <T> type by your own, custom <U> type. See the manual's section about for details. @@ -6182,7 +6182,7 @@ for (BookRecord book : create.selectFrom(BOOK).fetch()) {

    - +
    Static statements vs. Prepared Statements @@ -6192,7 +6192,7 @@ for (BookRecord book : create.selectFrom(BOOK).fetch()) {

    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 factory will be executed as static statements, with all bind values inlined. An example is given here:

    - + @@ -6221,7 +6221,7 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    Whichever aproach is more optimal for you cannot be decided by jOOQ. In most cases, prepared statements are probably better. But you always have the option of forcing jOOQ to render inlined bind values.

    - +

    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 @@ -6235,15 +6235,15 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    As previously discussed in the chapter about , reusing PreparedStatements is handled a bit differently in jOOQ from how it is handled in JDBC

    - +

    Keeping open PreparedStatements with JDBC

    With JDBC, you can easily reuse a by not closing it between subsequent executions. An example is given here:

    - + The above technique can be quite useful when you want to reuse expensive database resources. This can be the case when your statement is executed very frequently and your database would take non-negligible time to soft-parse the prepared statement and generate a new statement / cursor resource.

    - +

    Keeping open PreparedStatements with jOOQ

    This is also modeled in jOOQ. However, the difference to JDBC is that closing a statement is the default action, whereas keeping it open has to be configured explicitly. This is better than JDBC, because the default action should be the one that is used most often. Keeping open statements is rarely done in average applications. Here's an example of how to keep open PreparedStatements with jOOQ:

    - + query = create.selectOne().keepStatement(true); @@ -6312,22 +6312,22 @@ try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO author(id stmt.setString(2, "Erich"); stmt.setString(3, "Gamma"); stmt.addBatch(); - + stmt.setInt(1, 2); stmt.setString(2, "Richard"); stmt.setString(3, "Helm"); stmt.addBatch(); - + stmt.setInt(1, 3); stmt.setString(2, "Ralph"); stmt.setString(3, "Johnson"); stmt.addBatch(); - + stmt.setInt(1, 4); stmt.setString(2, "John"); stmt.setString(3, "Vlissides"); stmt.addBatch(); - + int[] result = stmt.executeBatch(); }]]> @@ -6336,7 +6336,7 @@ try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO author(id

    jOOQ supports executing queries in batch mode as follows:

    - + Instead of actually phrasing a select statement, you can also use the convenience methods:

    - + - +

    Inlining sequence references in SQL

    You can inline sequence references in jOOQ SQL statements. The following are examples of how to do that:

    - + The general distinction between (stored) procedures and (stored) functions can be summarised like this:

    - +

    Procedures

    • Are called using JDBC CallableStatement
    • Have no return value
    • Usually support OUT parameters
    - +

    Functions

    • Can be used in SQL statements
    • Have a return value
    • Usually don't support OUT parameters
    - +

    Exceptions to these rules

    • DB2, H2, and HSQLDB don't allow for JDBC escape syntax when calling functions. Functions must be used in a SELECT statement
    • @@ -6438,19 +6438,19 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

      To simplify things a little bit, jOOQ handles both procedures and functions the same way, using a more general type.

      - +

      Using jOOQ for standalone calls to stored procedures and functions

      If you're using jOOQ's , it will generate objects for you. Let's consider the following example:

      - +

      The generated artefacts can then be used as follows:

      - + - +

      But you can also call the procedure using a generated convenience method in a global Routines class:

      @@ -6477,7 +6477,7 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]>

      For more details about for procedures, see the manual's section about .

      - +

      Inlining stored function references in SQL

      Unlike procedures, functions can be inlined in SQL statements to generate or , if you're using . Assume you have a function like this: @@ -6485,11 +6485,11 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]> - +

      The generated artefacts can then be used as follows:

      - + - +

      For more info about inlining stored function references in SQL statements, please refer to the manual's section about .

      @@ -6529,7 +6529,7 @@ create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]>

      Oracle UDTs can have object-oriented structures including member functions and procedures. With Oracle, you can do things like this:

      - + {"name":"field-n","type":"type-n"}], "records":[[value-1-1,value-1-2,...,value-1-n], [value-2-1,value-2-2,...,value-2-n]]} - +

      Note: This format has changed in jOOQ 2.6.0

      @@ -6854,12 +6854,12 @@ Query query = error.query();]]>

      CRUD always uses the same patterns, regardless of the nature of underlying tables. This again, leads to a lot of boilerplate code, if you have to issue your statements yourself. Like Hibernate / JPA and other ORMs, jOOQ facilitates CRUD using a specific API involving types.

      - +

      Primary keys and updatability

      In normalised databases, every table has a primary key by which a tuple/record within that table can be uniquely identified. In simple cases, this is a (possibly auto-generated) number called ID. But in many cases, primary keys include several non-numeric columns. An important feature of such keys is the fact that in most databases, they are enforced using an index that allows for very fast random access to the table. A typical way to access / modify / delete a book is this:

      - + - +

      Normalised databases assume that a primary key is unique "forever", i.e. that a key, once inserted into a table, will never be changed or re-inserted after deletion. In order to use jOOQ's operations correctly, you should design your database accordingly.

      - +

      Main UNIQUE keys

      In SQL, a primary key is always also a unique key. In fact, unique keys have very similar properties as primary keys. For instance, they can be referenced from other tables' foreign keys in most databases. In the absence of a formal primary key, jOOQ assumes that the first unique key it encounters will serve as a primary key substitute. This is called the "main key" in jOOQ. In other words, a main key is: @@ -6880,7 +6880,7 @@ DELETE FROM BOOK WHERE ID = 5;]]>

    • The primary key, if available
    • The first unique key, otherwise
    - +

    For simplicity, the term "primary key" will be used in the sense of such a "main unique key" in this manual.

    @@ -6893,7 +6893,7 @@ DELETE FROM BOOK WHERE ID = 5;]]>

    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:

    - + - +

    See the manual's section about for some more insight on "attached" objects.

    - +

    Storing

    Storing a record will perform an or an . In general, new records are always inserted, whereas records loaded from the database are always updated. This is best visualised in code: @@ -6932,7 +6932,7 @@ BookRecord book2 = create.fetchOne(BOOK, BOOK.ID.equal(id)); // Update the record: UPDATE BOOK SET TITLE = 'Animal Farm' WHERE ID = [id] book2.setTitle("Animal Farm"); book2.store();]]> - +

    Some remarks about storing:

    @@ -6942,18 +6942,18 @@ book2.store();]]>
  • When loading records from , jOOQ will assume the record is a new record. It will hence attempt to INSERT it.
  • When you activate , storing a record may fail, if the underlying database record has been changed in the mean time.
  • - +

    Deleting

    Deleting a record will remove it from the database. Here's how you delete records:

    - + - +

    Refreshing

    Refreshing a record from the database means that jOOQ will issue a to refresh all record values that are not the primary key. This is particularly useful when you use jOOQ's feature, in case a modified record is "stale" and cannot be stored to the database, because the underlying database record has changed in the mean time. @@ -6972,7 +6972,7 @@ book.refresh();]]>

    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 :

    - + Many databases support the concept of IDENTITY values, or key values. This is reflected by JDBC's method. jOOQ abstracts using this method as many databases and JDBC drivers behave differently with respect to generated keys. Let's assume the following SQL Server BOOK table:

    - +

    If you're using jOOQ's , the above table will generate a with an IDENTITY column. This information is used by jOOQ internally, to update IDs after calling :

    - +

    When using jOOQ's along with its , generated records can have navigation methods contained in them, if properly . These navigation methods allow for "navigating" inbound or outbound foreign key references by executing an appropriate query. An example is given here:

    - + books = author.fetchBookList();]]>

    These methods are safe for use with several foreign keys referencing the same tables:

    - + books = coAuthor.fetchBookListByCoAuthorId();]]>

    Tables without UNIQUE keys are considered non-updatable by jOOQ, as jOOQ has no way of uniquely identifying such a record within the database. If you're using jOOQ's , such tables will generate classes, instead of classes. When you fetch from such a table, the returned records will not allow for calling any of the methods.

    - +

    Note, that some databases use internal rowid or object-id values to identify such records. jOOQ does not support these vendor-specific record meta-data.

    @@ -7155,7 +7155,7 @@ List books = coAuthor.fetchBookListByCoAuthorId();]]>
    - +

    Optimised optimistic locking using TIMESTAMP fields

    If you're using jOOQ's , you can take indicate TIMESTAMP or UPDATE COUNTER fields for every generated table in the . Let's say we have this table:

    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:

    - +

    As before, without the added TIMESTAMP column, optimistic locking is transparent to the API.

    - +

    Optimised optimistic locking using VERSION fields

    Instead of using TIMESTAMPs, you may also use numeric VERSION fields, containing version numbers that are incremented by jOOQ upon store() calls. @@ -7224,7 +7224,7 @@ book2.store();]]>

    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:

    - + books = create.fetch(BOOK); @@ -7249,7 +7249,7 @@ create.batchStore(books);]]>

    If you're using jOOQ's , you can configure it to generate and DAOs for you. jOOQ then generates one DAO per , i.e. per table with a single-column primary key. Generated DAOs implement a common jOOQ type called . This type contains the following methods:

    - + corresponds to the DAO's related table //

    corresponds to the DAO's related generated POJO type // corresponds to the DAO's related table's primary key type. @@ -7260,23 +7260,23 @@ public interface DAO, P, T> { void insert(P object) throws DataAccessException; void insert(P... objects) throws DataAccessException; void insert(Collection

    objects) throws DataAccessException; - + // These methods allow for updating POJOs based on their primary key void update(P object) throws DataAccessException; void update(P... objects) throws DataAccessException; void update(Collection

    objects) throws DataAccessException; - + // These methods allow for deleting POJOs based on their primary key void delete(P... objects) throws DataAccessException; void delete(Collection

    objects) throws DataAccessException; void deleteById(T... ids) throws DataAccessException; void deleteById(Collection ids) throws DataAccessException; - + // These methods allow for checking record existence boolean exists(P object) throws DataAccessException; boolean existsById(T id) throws DataAccessException; long count() throws DataAccessException; - + // These methods allow for retrieving POJOs by primary key or by some other field List

    findAll() throws DataAccessException; P findById(T id) throws DataAccessException; @@ -7305,7 +7305,7 @@ public class BookDao extends DAOImpl {

    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:

    - +

    With jOOQ, it's simple. All of jOOQ's exceptions are "system exceptions", hence they are all unchecked.

    - +

    jOOQ's DataAccessException

    jOOQ uses its own to wrap any underlying that might have occurred. Note that all methods in jOOQ that may cause such a DataAccessException document this both in the Javadoc as well as in their method signature. @@ -7354,7 +7354,7 @@ bookDao.delete(book);]]>

  • InvalidResultException: An operation was performed expecting only one result, but several results were returned.
  • MappingException: Something went wrong when loading a record from a or when mapping a record into a POJO
  • - +

    Override jOOQ's exception handling

    The following section about documents means of overriding jOOQ's exception handling, if you wish to deal separately with some types of constraint violations, or if you raise business errors from your database, etc. @@ -7386,11 +7386,11 @@ public class StatisticsListener extends DefaultExecuteListener { public void start(ExecuteContext ctx) { synchronized (STATISTICS) { Integer count = STATISTICS.get(ctx.type()); - + if (count == null) { count = 0; } - + STATISTICS.put(ctx.type(), count + 1); } } @@ -7432,7 +7432,7 @@ for (ExecuteType type : ExecuteType.values()) {

    Please read the for more details

    - +

    Writing a custom ExecuteListener for logging

    The following depicts an example of a custom ExecuteListener, which pretty-prints all queries being executed by jOOQ to stdout: @@ -7455,7 +7455,7 @@ public class PrettyPrinter extends DefaultExecuteListener { // Create a new factory for logging rendering purposes // This factory doesn't need a connection, only the SQLDialect... Factory factory = new Factory(ctx.getDialect(), - + // ... and the flag for pretty-printing new Settings().withRenderFormatted(true)); @@ -7463,12 +7463,12 @@ public class PrettyPrinter extends DefaultExecuteListener { if (ctx.query() != null) { System.out.println(factory.renderInlined(ctx.query())); } - + // If we're executing a routine else if (ctx.routine() != null) { System.out.println(factory.renderInlined(ctx.routine())); } - + // If we're executing anything else (e.g. plain SQL) else if (!StringUtils.isBlank(ctx.sql())) { System.out.println(ctx.sql()); @@ -7487,7 +7487,7 @@ public class PrettyPrinter extends DefaultExecuteListener {

    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:

    - + @@ -7505,7 +7505,7 @@ public class PrettyPrinter extends DefaultExecuteListener {

    With the above configuration, let's fetch some data with jOOQ

    - + @@ -7554,7 +7554,7 @@ Finishing : Total: 4.814ms, +3.375ms
  • 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
  • - +

    Optimise wisely

    Don't be put off by the above paragraphs. You should optimise wisely, i.e. only in places where you really need very high throughput to your database. jOOQ's overhead compared to plain JDBC is typically less than 1ms per query. @@ -7611,7 +7611,7 @@ Finishing : Total: 4.814ms, +3.375ms

    You need to tell jOOQ some things about your database connection. Here's an example of how to do it for an Oracle database

    - + @@ -7620,7 +7620,7 @@ Finishing : Total: 4.814ms, +3.375ms jdbc:oracle:thin:@[your jdbc connection parameters] [your database user] [your database password] - + user[db-user] @@ -7698,13 +7698,13 @@ Finishing : Total: 4.814ms, +3.375ms

    Code generation works by calling this class with the above property file as argument.

    - + org.jooq.util.GenerationTool /jooq-config.xml

    Be sure that these elements are located on the classpath:

    - +
    • The XML configuration file
    • jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar
    • @@ -7761,7 +7761,7 @@ Finishing : Total: 4.814ms, +3.375ms

      You can also use an ant task to generate your classes. As a rule of thumb, remove the dots "." and dashes "-" from the .properties file's property names to get the ant task's arguments:

      - + @@ -8027,7 +8027,7 @@ public class AsInDatabaseStrategy extends DefaultGeneratorStrategy { optimistic locking (several Java regular expressions, separated by comma). See UpdatableRecord.store() and UpdatableRecord.delete() for details --> REC_TIMESTAMP - + @@ -8157,12 +8157,12 @@ public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {
    • Tables.java: This file contains all table objects in the form of static member references to the actual singleton object
    • UDTs.java: This file contains all UDT objects in the form of static member references to the actual singleton object
    - +

    Referencing global artefacts

    When referencing global artefacts from your client application, you would typically static import them as such:

    - + @@ -8184,7 +8184,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate a implementation that looks like this:

    - + { // The singleton instance @@ -8200,7 +8200,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE) public Book as(java.lang.String alias) { return new Book(alias); } - + // [...] }]]> @@ -8217,7 +8217,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)
  • instanceFields: This flag controls the "static" keyword on table columns, as well as aliasing convenience
  • records: The generated record type is referenced from tables allowing for type-safe single-table record fetching
  • - +

    Flags controlling table generation

    Table generation cannot be deactivated @@ -8231,7 +8231,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate an implementation that looks like this:

    - + - +

    Flags influencing generated records

    These flags from the influence generated records: @@ -8288,7 +8288,7 @@ implements IBook {

  • interfaces: If interfaces are generated, records will implement them
  • jpaAnnotations: JPA annotations are used on generated records
  • - +

    Flags controlling record generation

    Record generation can be deactivated using the records flag @@ -8302,7 +8302,7 @@ implements IBook {

    Every table in your database will generate a POJO implementation that looks like this:

    - + - +

    Flags influencing generated POJOs

    These flags from the influence generated POJOs: @@ -8351,7 +8351,7 @@ public class Book implements java.io.Serializable

  • jpaAnnotations: JPA annotations are used on generated records
  • validationAnnotations: JSR-303 validation annotations are used on generated records
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the pojos flag @@ -8365,16 +8365,16 @@ public class Book implements java.io.Serializable

    Every table in your database will generate an interface that looks like this:

    - + - +

    Flags influencing generated interfaces

    These flags from the influence generated interfaces: @@ -8383,7 +8383,7 @@ public class Book implements java.io.Serializable

  • dateAsTimestamp: This influences all relevant getters and setters
  • unsignedTypes: This influences all relevant getters and setters
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the interfaces flag @@ -8398,7 +8398,7 @@ public class Book implements java.io.Serializable

    Every table in your database will generate a implementation that looks like this:

    - + { // Generated constructors @@ -8422,10 +8422,10 @@ public class Book implements java.io.Serializable public List fetchByAuthorId(Integer... values) { return fetch(BOOK.AUTHOR_ID, values); } - + // [...] }]]> - +

    Flags controlling DAO generation

    DAO generation can be activated using the daos flag @@ -8439,13 +8439,13 @@ public class Book implements java.io.Serializable

    Every sequence in your database will generate a implementation that looks like this:

    - + S_AUTHOR_ID = new SequenceImpl("S_AUTHOR_ID", TEST, SQLDataType.INTEGER); }]]> - +

    Flags controlling sequence generation

    Sequence generation cannot be deactivated @@ -8483,7 +8483,7 @@ public class Book implements java.io.Serializable public BigDecimal getResult() { return getValue(RESULT); } - + // [...] }]]> @@ -8505,7 +8505,7 @@ public class Book implements java.io.Serializable

    Every UDT in your database will generate a implementation that looks like this:

    - + { // The singleton UDT instance @@ -8518,10 +8518,10 @@ public class Book implements java.io.Serializable createField("CITY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); public static final UDTField COUNTRY = createField("COUNTRY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); - + // [...] }]]> - +

    Besides the implementation, a implementation is also generated

    @@ -8536,7 +8536,7 @@ public class Book implements java.io.Serializable public String getCity() {...} public void setCountry(String value) {...} public String getCountry() {...} - + // [...] }]]> @@ -8561,7 +8561,7 @@ public class Book implements java.io.Serializable

    As previously discussed, you can configure master data tables as follows:

    - + @@ -8583,7 +8583,7 @@ public class Book implements java.io.Serializable

    The results of this will be a Java enum that looks similar to this:

    - + { /** @@ -8617,7 +8617,7 @@ public class Book implements java.io.Serializable

    In the above example, you can see how the configured primary key is mapped to the id member, the configured literal column is mapped to the cd member and the configured description member is mapped to the description member and output as Javadoc. In other words, LANGUAGE is a table with 4 rows and at least three columns.

    - +

    The general contract is that there must be

    @@ -8642,7 +8642,7 @@ public class Book implements java.io.Serializable

    Which can then be used in the BookRecord directly:

    - + { // [...] @@ -8790,7 +8790,7 @@ create.selectFrom(AUTHOR)
    • Google Cloud SQL (MySQL)
    - +

    Databases planned for support

    Any of the following databases might be available in the future @@ -8804,7 +8804,7 @@ create.selectFrom(AUTHOR)

  • Sybase SQL Anywhere OnDemand
  • Teradata
  • - +

    Databases being watched

    Any of the following databases are being observed for a potential integration @@ -8839,7 +8839,7 @@ create.selectFrom(AUTHOR) This chapter should document the most important notes about SQL, JDBC and jOOQ data types.

    - +
    BLOBs and CLOBs @@ -8849,7 +8849,7 @@ create.selectFrom(AUTHOR)

    - +
    Unsigned integer types @@ -8873,7 +8873,7 @@ create.selectFrom(AUTHOR)
    - +
    INTERVAL data types @@ -8884,11 +8884,11 @@ create.selectFrom(AUTHOR)
  • YEAR TO MONTH: This interval type models a number of months and years
  • DAY TO SECOND: This interval type models a number of days, hours, minutes, seconds and milliseconds
  • - +

    Both interval types ship with a variant of subtypes, such as DAY TO HOUR, HOUR TO SECOND, etc. jOOQ models these types as Java objects extending : (where Number.intValue() corresponds to the absolute number of months) and (where Number.intValue() corresponds to the absolute number of milliseconds)

    - +

    Interval arithmetic

    In addition to the documented previously, interval arithmetic is also supported by jOOQ. Essentially, the following operations are supported: @@ -8903,7 +8903,7 @@ create.selectFrom(AUTHOR)

    - +
    XML data types @@ -8912,7 +8912,7 @@ create.selectFrom(AUTHOR)

    - +
    Geospacial data types @@ -8922,7 +8922,7 @@ create.selectFrom(AUTHOR)

    - +
    CURSOR data types @@ -8931,22 +8931,22 @@ create.selectFrom(AUTHOR)

    > cursor;]]> - +

    In fact, such a cursor will be fetched immediately by jOOQ and wrapped in an object.

    - +
    ARRAY and TABLE data types

    The SQL standard specifies ARRAY data types, that can be mapped to Java arrays as such:

    - + intArray;]]> - +

    The above array type is supported by these SQL dialects:

    @@ -8955,7 +8955,7 @@ create.selectFrom(AUTHOR)
  • HSQLDB
  • Postgres
  • - +

    Oracle typed arrays

    Oracle has strongly-typed arrays and table types (as opposed to the previously seen anonymously typed arrays). These arrays are wrapped by types. diff --git a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.0.xml b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.0.xml index d53a6c878c..9eb338b326 100644 --- a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.0.xml +++ b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.0.xml @@ -86,7 +86,7 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ's reason for being - compared to SQL / JDBC

    So why not just use SQL? @@ -109,30 +109,30 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ is different

    SQL was never meant to be abstracted. To be confined in the narrow boundaries of heavy mappers, hiding the beauty and simplicity of relational data. SQL was never meant to be object-oriented. SQL was never meant to be anything other than... SQL!

    - + - +
    Getting started with jOOQ @@ -291,12 +291,12 @@ and Maintenance Agreement for more details: http://www.jooq.org/licensing

    This section helps you correctly interpret this manual in the context of jOOQ.

    - +

    Code blocks

    The following are code blocks:

    - + @@ -306,7 +306,7 @@ org.jooq.property=value]]>

    These are useful to provide examples in code. Often, with jOOQ, it is even more useful to compare SQL code with its corresponding Java/jOOQ code. When this is done, the blocks are aligned side-by-side, with SQL usually being on the left, and an equivalent jOOQ DSL query in Java usually being on the right:

    - +

    The contents of code blocks follow conventions, too. If nothing else is mentioned next to any given code block, then the following can be assumed:

    - - + +

    Your naming may differ, of course. For instance, you could name the "create" instance "db", instead.

    - +

    Execution

    - +

    When you're coding PL/SQL, T-SQL or some other procedural SQL language, SQL statements are always executed immediately at the semi-colon. This is not the case in jOOQ, because as an internal DSL, jOOQ can never be sure that your statement is complete until you call fetch() or execute(). The manual tries to apply fetch() and execute() as thoroughly as possible. If not, it is implied:

    @@ -365,7 +365,7 @@ create.update(T).set(T.V, 1).execute();]]>

    jOOQ allows to override runtime behaviour using . If nothing is specified, the default runtime settings are assumed.

    - +

    Sample database

    jOOQ query examples run against the sample database. See the manual's section about to learn more about the sample database. @@ -400,7 +400,7 @@ CREATE TABLE book ( title VARCHAR2(400) NOT NULL, published_in NUMBER(7) NOT NULL, language_id NUMBER(7) NOT NULL, - + CONSTRAINT fk_book_author FOREIGN KEY (author_id) REFERENCES author(id), CONSTRAINT fk_book_language FOREIGN KEY (language_id) REFERENCES language(id) ); @@ -413,7 +413,7 @@ CREATE TABLE book_to_book_store ( name VARCHAR2(400) NOT NULL, book_id INTEGER NOT NULL, stock INTEGER, - + PRIMARY KEY(name, book_id), CONSTRAINT fk_b2bs_book_store FOREIGN KEY (name) REFERENCES book_store (name) ON DELETE CASCADE, CONSTRAINT fk_b2bs_book FOREIGN KEY (book_id) REFERENCES book (id) ON DELETE CASCADE @@ -424,7 +424,7 @@ CREATE TABLE book_to_book_store (

    In addition to the above, you may assume the following sample data:

    - + Effectively, jOOQ was originally designed to replace any other database abstraction framework short of the ones handling connection pooling and transaction management (see also the )

    - +

    Use jOOQ the way you prefer

    ... but open source is community-driven. And the community has shown various ways of using jOOQ that diverge from its original intent. Some use cases encountered are: @@ -483,7 +483,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]>Using jOOQ for SQL building and Spring Data for SQL execution

  • Using jOOQ without the to build the basis of a framework for dynamic SQL execution.
  • - +

    The following sections explain about various use cases for using jOOQ in your application.

    @@ -496,7 +496,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]> This is the most simple of all use cases, allowing for construction of valid SQL for any database. In this use case, you will not use and probably not even . Instead, you'll use to wrap strings, literals and other user-defined objects into an object-oriented, type-safe AST modelling your SQL statements. An example is given here:

    - + - +

    The SQL string built with the jOOQ query DSL can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools (note that since jOOQ uses PreparedStatement by default, this will generate a bind variable for "1948". ).

    @@ -533,7 +533,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID)) .where(BOOK.PUBLISHED_IN.equal(1948)) .getSQL();]]> - +

    The SQL string that you can generate as such can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools.

    @@ -553,7 +553,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    Instead of any tool mentioned in the previous chapters, you can also use jOOQ directly to execute your jOOQ-generated SQL statements. This will add a lot of convenience on top of the previously discussed API for typesafe SQL construction, when you can re-use the information from generated classes to fetch records and custom data types. An example is given here:

    - + > result = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) @@ -607,10 +607,10 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { // Skip previously distinguished authors if ((int) author.getDistinguished() == 1) continue; - + // Check if the author has written more than 5 books if (author.fetchChildren(Keys.FK_BOOK_AUTHOR).size() > 5) { - + // Mark the author as a "distinguished" author author.setDistinguished(1); author.store(); @@ -627,7 +627,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {
    - +
    jOOQ for PROs @@ -666,7 +666,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { This manual section is intended for new users, to help them get a running application with jOOQ, quickly.

    - +
    Step 1: Preparation @@ -675,7 +675,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { If you haven't already downloaded it, download jOOQ:
    http://www.jooq.org/download

    - +

    Alternatively, you can create a Maven dependency to download jOOQ artefacts:

    @@ -709,14 +709,14 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    - +
    Step 2: Your database

    We're going to create a database called "guestbook" and a corresponding "posts" table. Connect to MySQL via your command line client and type the following:

    - + CREATE DATABASE guestbook; CREATE TABLE `posts` ( @@ -728,7 +728,7 @@ CREATE TABLE `posts` ( );
    - +
    Step 3: Code generation @@ -740,7 +740,7 @@ CREATE TABLE `posts` (

    The easiest way to generate a schema is to copy the jOOQ jar files (there should be 3) and the MySQL Connector jar file to a temporary directory. Then, create a guestbook.xml that looks like this:

    - + @@ -794,7 +794,7 @@ CREATE TABLE `posts` (

    generator.target.directory - the directory to output to.

    - +

    Once you have the JAR files and library.xml in your temp directory, type this on a Windows machine:

    @@ -814,12 +814,12 @@ CREATE TABLE `posts` (

    There are two things to note:

    - +
    1. The prefix slash before the /library.xml. Even though it's in our working directory, we need to prepend a slash, as the configuration file is loaded from the classpath.
    2. The "trailing" period in the classpath: .. We need this because we want the current directory on the classpath in order to find the above /library.xml file at the root of your classpath.
    - +

    Replace the filenames with your actual filenames. In this example, jOOQ {jooq-version} is being used. If everything has worked, you should see this in your console output:

    @@ -882,14 +882,14 @@ Nov 1, 2011 7:25:08 PM org.jooq.impl.JooqLogger info INFO: GENERATION FINISHED! : Total: 791.688ms, +9.143ms
    - +
    Step 4: Connect to your database

    Let's just write a vanilla main class in the project containing the generated classes:

    - +
    - +
    Step 5: Querying

    Let's add a simple query constructed with jOOQ's query DSL:

    - + result = create.select().from(POSTS).fetch();]]> @@ -945,7 +945,7 @@ Result result = create.select().from(POSTS).fetch();]]>

    - +
    Step 6: Iterating @@ -964,7 +964,7 @@ Result result = create.select().from(POSTS).fetch();]]>

    The full program should now look like this:

    - +
    - +
    Step 7: Explore! @@ -1064,7 +1064,7 @@ public class Main {
    - +
    jOOQ and Scala @@ -1077,7 +1077,7 @@ public class Main {
  • Optioanl ";" at the end of a Scala statement
  • Type inference using "var" and "val" keywords
  • - +

    But jOOQ also leverages other useful Scala features, such as

    @@ -1085,15 +1085,15 @@ public class Main {
  • implicit defs for operator overloading
  • Scala Macros (soon to come)
  • - +

    All of the above heavily improve jOOQ's querying DSL API experience for Scala developers.

    - +

    A short example jOOQ application in Scala might look like this:

    - +
    - +
    jOOQ and NoSQL @@ -1158,7 +1158,7 @@ object Test { //

    - +
    Dependencies @@ -1176,7 +1176,7 @@ object Test { //
    - +
    Build your own @@ -1205,7 +1205,7 @@ object Test { //
    - +
    jOOQ and backwards-compatibility @@ -1217,7 +1217,7 @@ object Test { //
  • If a minor release includes backwards-compatible, API-relevant new features, [Y] is incremented by one and [Z] is reset to zero.
  • If a major release includes backwards-incompatible, API-relevant new features, [X] is incremented by one and [Y], [Z] are reset to zero.
  • - +

    jOOQ's understanding of backwards-compatibility

    Backwards-compatibility is important to jOOQ. You've chosen jOOQ as a strategic SQL engine and you don't want your SQL to break. That is why there is at most one major release per year, which changes only those parts of jOOQ's API and functionality, which were agreed upon on the user group. During the year, only minor releases are shipped, adding new features in a backwards-compatible way @@ -1230,11 +1230,11 @@ object Test { //

  • Overloading methods for convenience
  • Changing the type hierarchy of interfaces
  • - +

    It becomes obvious that it would be impossible to add new language elements (e.g. new , new ) to the API without breaking any client code that actually implements those interfaces. Hence, the following rule should be observed:

    - +

    jOOQ's DSL interfaces should not be implemented by client code! Extend only those extension points that are explicitly documented as "extendable" (e.g. )

    @@ -1259,7 +1259,7 @@ object Test { // - +
    The query DSL type @@ -1289,7 +1289,7 @@ object Test { // // ... which is in fact the same as: DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    DSL subclasses @@ -1308,7 +1308,7 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME));
    - + @@ -1317,14 +1317,14 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME));
    - +
    The DSLContext class

    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.

    - +

    Fluent creation of a DSLContext object

    The DSLContext object can be created fluently from the : @@ -1339,7 +1339,7 @@ DSLContext create = DSL.using(connection, dialect);]]>

    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

    A Configuration can be supplied with these objects: @@ -1357,7 +1357,7 @@ DSLContext create = DSL.using(connection, dialect);]]> - +

    Wrapping a Configuration object, a DSLContext can construct , for later . An example is given here:

    @@ -1398,7 +1398,7 @@ DSL.using(connection, dialect) CONNECT BY clause to the query */ -@Support({ SQLDialect.CUBRID, SQLDialect.}) +@Support({ SQLDialect.CUBRID, SQLDialect.ORACLE }) SelectConnectByConditionStep connectBy(Condition condition);]]>

    @@ -1420,7 +1420,7 @@ SelectSelectStep select(Field... fields);]]>

    Nevertheless, the IS DISTINCT FROM predicate is supported by jOOQ in all dialects, as its semantics can be expressed with an equivalent . For more details, see the manual's section about the .

    - +

    jOOQ and the Oracle SQL dialect

    Oracle SQL is much more expressive than many other SQL dialects. It features many unique keywords, clauses and functions that are out of scope for the SQL standard. Some examples for this are @@ -1448,7 +1448,7 @@ SelectSelectStep select(Field... fields);]]>

    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.

    - +

    Interact with JDBC DataSources

    If you're in a J2EE or Spring context, however, you may wish to use a instead. Connections obtained from such a DataSource will be closed after query execution by jOOQ. The semantics of such a close operation should be the returning of the connection into a connection pool, not the actual closing of the underlying connection. Typically, this makes sense in an environment using distributed JTA transactions. An example of using DataSources with jOOQ can be seen in the tutorial section about . @@ -1456,17 +1456,17 @@ SelectSelectStep select(Field... fields);]]>

    Note, in this case, jOOQ will internally use a , which you can reference directly if you prefer that.

    - +

    Inject custom behaviour

    If your specific environment works differently from any of the above approaches, you can inject your own custom implementation of a ConnectionProvider into jOOQ. This is the API contract you have to fulfil:

    - + @@ -1476,19 +1476,19 @@ 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...

    - +
    - +

    Here is an example of how to use the custom data API. Let's assume that you have written an , that prevents INSERT statements, when a given flag is set to true:

    @@ -1498,10 +1498,10 @@ public class NoInsertListener extends DefaultExecuteListener { @Override public void start(ExecuteContext ctx) { - + // This listener is active only, when your custom flag is set to true 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) { throw new DataAccessException("No INSERT statements allowed"); @@ -1512,11 +1512,11 @@ public class NoInsertListener extends DefaultExecuteListener {

    See the manual's section about to learn more about how to implement an ExecuteListener.

    - +

    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:

    - + ExecuteListeners are a useful tool to...

    - +
    • implement custom logging
    • apply triggers written in Java
    • collect query execution statistics
    • integrate with the
    - +

    ExecuteListeners are hooked into your by returning them from an :

    @@ -1575,7 +1575,7 @@ configuration.set( new DefaultExecuteListenerProvider(new PerformanceLoggingListener()), new DefaultExecuteListenerProvider(new NoInsertListener()) );]]>
    - +

    See the manual's section about to see examples of such listener implementations.

    @@ -1622,7 +1622,7 @@ DSLContext create = DSL.using(connection, dialect, settings);]]>

    - +
    Runtime schema and table mapping @@ -1630,7 +1630,7 @@ DSLContext create = DSL.using(connection, dialect, settings);]]>

    You may wish to design your database in a way that you have several instances of your schema. This is useful when you want to cleanly separate data belonging to several customers / organisation units / branches / users and put each of those entities' data in a separate database or schema.

    - +

    In our AUTHOR example this would mean that you provide a book reference database to several companies, such as My Book World and Books R Us. In that case, you'll probably have a schema setup like this:

    @@ -1660,7 +1660,7 @@ create.selectFrom(AUTHOR).fetch();

    The query executed with a Configuration equipped with the above mapping will in fact produce this SQL statement:

    - + SELECT * FROM MY_BOOK_WORLD.AUTHOR

    Even if AUTHOR was generated from DEV. @@ -1735,7 +1735,7 @@ create.selectFrom(AUTHOR).fetch();

    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

    @@ -1769,7 +1769,7 @@ create.selectFrom(AUTHOR).fetch();

    Here is an example to illustrate what that means:

    - + 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) @@ -1840,7 +1840,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); @@ -1867,7 +1867,7 @@ query.addJoin(BOOK, BOOK.AUTHOR_ID.equal(AUTHOR.ID));]]>

    Note, that for historic reasons, the DSL API mixes mutable and immutable behaviour with respect to the internal representation of the being constructed. While creating , (such as functions) assumes immutable behaviour, creating does not. In other words, the following can be said:

    - + select2 = create.selectOne();]]>

    jOOQ does not explicitly support the asterisk operator in projections. However, you can omit the projection as in these examples:

    - +

    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:

    - + select(Collection> fields); public static SelectSelectStep select(Field... fields); @@ -2043,14 +2043,14 @@ public static SelectSelectStep> select(Field SelectSelectStep> select(Field field1, Field field2); public static SelectSelectStep> select(Field field1, Field field2, Field field3); // [...]]]> - +

    Since the generic R type is bound to some , the associated T type information can be used in various other contexts, e.g. the . Such a SELECT statement can be assigned typesafely:

    > s1 = create.select(BOOK.ID, BOOK.TITLE); Select> s2 = create.select(BOOK.ID, trim(BOOK.TITLE));]]> - +

    For more information about typesafe record types with degree up to {max-row-degree}, see the manual's section about .

    @@ -2075,7 +2075,7 @@ create.selectOne().from(BOOK.as("b"), AUTHOR.as("a"));]]>

    Read more about aliasing in the manual's section about .

    - +

    More advanced table expressions

    Apart from simple tables, you can pass any arbitrary to the jOOQ FROM clause. This may include in Oracle: @@ -2344,12 +2344,12 @@ ORDER BY 1]]> Note that this syntax is also supported in the CUBRID database and might be emulated in other dialects supporting common table expressions in the future.

    - +

    ORDER SIBLINGS

    The Oracle database allows for specifying a SIBLINGS keyword in the . Instead of ordering the overall result, this will only order siblings among each other, keeping the hierarchy intact. An example is given here:

    - + - +
    @@ -2387,7 +2387,7 @@ GROUP BY AUTHOR_ID]]> Note, as defined in the SQL standard, when grouping, you may no longer project any columns that are not a formal part of the GROUP BY clause, or .

    - +

    MySQL's deviation from the SQL standard

    MySQL has a peculiar way of not adhering to this standard behaviour. This is documented in the MySQL manual. In short, with MySQL, you can also project any other field that is not part of the GROUP BY clause. The projected values will just be arbitrary values from within the group. You cannot rely on any ordering. For example: @@ -2416,7 +2416,7 @@ GROUP BY ()]]> - +

    ROLLUP(), CUBE() and GROUPING SETS()

    Some databases support the SQL standard grouping functions and some extensions thereof. See the manual's section about for more details. @@ -2435,7 +2435,7 @@ GROUP BY ()]]>= 2]]>= 2]]> @@ -2570,8 +2570,8 @@ ORDER BY CASE TITLE

    The SQL standard defines that a "query expression" can be ordered, and that query expressions can contain , whose subqueries cannot be ordered. While this is defined as such in the SQL standard, many databases allowing for the non-standard in one way or another, do not adhere to this part of the SQL standard. Hence, jOOQ allows for ordering all SELECT statements, regardless whether they are constructed as a part of a UNION or not. Corner-cases are handled internally by jOOQ, by introducing synthetic subselects to adhere to the correct syntax, where this is needed.

    - - + +

    Oracle's ORDER SIBLINGS BY clause

    jOOQ also supports Oracle's SIBLINGS keyword to be used with ORDER BY clauses for @@ -2620,7 +2620,7 @@ SELECT TOP 1 * FROM BOOK

    Things get a little more tricky in those databases that have no native idiom for OFFSET pagination (actual queries may vary):

    - + 1]]>

    As you can see, jOOQ will take care of the incredibly painful ROW_NUMBER() OVER() (or ROWNUM for Oracle) filtering in subselects for you, you'll just have to write limit(1).offset(2) in any dialect.

    - +

    Side-note: If you're interested in understanding why we chose ROWNUM for Oracle, please refer to this very interesting benchmark, comparing the different approaches of doing pagination in Oracle: http://www.inf.unideb.hu/~gabora/pagination/results.html.

    @@ -2766,7 +2766,7 @@ SELECT * FROM author ORDER BY id DESC;]]>

    SQL allows to perform set operations as understood in standard set theory on result sets. These operations include unions, intersections, subtractions. For two subselects to be combinable by such a set operator, each subselect must return a of the same degree and type.

    - +

    UNION and UNION ALL

    These operators combine two results into one. While UNION removes all duplicate records resulting from this combination, UNION ALL leaves subselect results as they are. Typically, you should prefer UNION ALL over UNION, if you don't really need to remove duplicates. The following example shows how to use such a UNION operation in jOOQ. @@ -2778,12 +2778,12 @@ UNION ALL SELECT * FROM BOOK WHERE ID = 5]]> - +

    INTERSECT [ ALL ] and EXCEPT [ ALL ]

    INTERSECT is the operation that produces only those values that are returned by both subselects. EXCEPT is the operation that returns only those values that are returned exclusively in the first subselect. Both operators will remove duplicates from their results. The SQL standard allows to specify the ALL keyword for both of these operators as well, but this is hardly supported in any database. jOOQ does not support INTERSECT ALL, EXEPT ALL operations either.

    - +

    jOOQ's set operators and how they're different from standard SQL

    As previously mentioned in the manual's section about the , jOOQ has slightly changed the semantics of these set operators. While in SQL, a subselect may not contain any or (unless you wrap the subselect into a ), jOOQ allows you to do so. In order to select both the youngest and the oldest author from the database, you can issue the following statement with jOOQ (rendered to the MySQL dialect): @@ -2799,12 +2799,12 @@ UNION .union( create.selectFrom(AUTHOR) .orderBy(AUTHOR.DATE_OF_BIRTH.desc()).limit(1));]]> - +

    Projection typesafety for degrees between 1 and {max-row-degree}

    Two subselects that are combined by a set operator are required to be of the same degree and, in most databases, also of the same type. jOOQ 3.0's introduction of helps compile-checking these constraints:

    - + > s1 = select(BOOK.ID, BOOK.TITLE).from(BOOK); Select> s2 = selectOne(); @@ -2838,7 +2838,7 @@ s1.union(s4); // OK. The two Record[N] types match]]>

    Note that you can pass any string in the .hint() clause. If you use that clause, the passed string will always be put in between the SELECT [DISTINCT] keywords and the actual projection list. This can be useful in other databases too, such as MySQL, for instance:

    - +
    - +
    Lexical and logical SELECT clause order

    SQL has a lexical and a logical order of SELECT clauses. The lexical order of SELECT clauses is inspired by the English language. As SQL statements are commands for the database, it is natural to express a statement in an imperative tense, such as "SELECT this and that!".

    - +

    Logical SELECT clause order

    The logical order of SELECT clauses, however, does not correspond to the syntax. In fact, the logical order is this:

    - +
    • : First, all data sources are defined and joined
    • : Then, data is filtered as early as possible
    • @@ -2873,11 +2873,11 @@ FROM table1
    • : Then, a paging view is created for the ordered tuples
    • : Finally, pessimistic locking is applied
    - +

    The SQL Server documentation also explains this, with slightly different clauses:

    - +
    • FROM
    • ON
    • @@ -2891,16 +2891,16 @@ FROM table1
    • ORDER BY
    • TOP
    - +

    As can be seen, databases have to logically reorder a SQL statement in order to determine the best execution plan.

    - +

    Alternative syntaxes: LINQ, SLICK

    Some "higher-level" abstractions, such as C#'s LINQ or Scala's SLICK try to inverse the lexical order of SELECT clauses to what appears to be closer to the logical order. The obvious advantage of moving the SELECT clause to the end is the fact that the projection type, which is the record type returned by the SELECT statement can be re-used more easily in the target environment of the internal domain specific language.

    - +

    A LINQ example:

    @@ -2913,11 +2913,11 @@ Where p.UnitsInStock <= p.ReorderLevel AndAlso Not p.Discontinued // SELECT clause Select p]]> - +

    A SLICK example:

    - + create.insertInto(AUTHOR, .set(AUTHOR.ID, 101) .set(AUTHOR.FIRST_NAME, "Alfred") .set(AUTHOR.LAST_NAME, "Döblin"); - +

    As you can see, this syntax is a bit more verbose, but also more readable, as every field can be matched with its value. Internally, the two syntaxes are strictly equivalent.

    @@ -3013,7 +3013,7 @@ SELECT 101, 'Alfred', 'Döblin' FROM DUAL;create.insertInto(AUTHOR,

    The MySQL database supports a very convenient way to INSERT or UPDATE a record. This is a non-standard extension to the SQL syntax, which is supported by jOOQ and emulated in other RDBMS, where this is possible (i.e. if they support the SQL standard ). Here is an example how to use the ON DUPLICATE KEY UPDATE clause:

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, update the author's name create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -3022,11 +3022,11 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .set(AUTHOR.LAST_NAME, "Koontz");

    The synthetic ON DUPLICATE KEY IGNORE clause

    - +

    The MySQL database also supports an INSERT IGNORE INTO clause. This is supported by jOOQ using the more convenient SQL syntax variant of ON DUPLICATE KEY IGNORE, which can be equally emulated in other databases using a :

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, ignore the INSERT statement create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -3062,11 +3062,11 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    The INSERT SELECT statement

    - +

    In some occasions, you may prefer the INSERT SELECT syntax, for instance, when you copy records from one table to another:

    - + create.insertInto(AUTHOR_ARCHIVE) .select(create.selectFrom(AUTHOR).where(AUTHOR.DECEASED.isTrue()));
    @@ -3113,7 +3113,7 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    jOOQ supports formal in various contexts, among which the UPDATE statement. Only one row value expression can be updated at a time. Here's an example:

    - + UPDATE AUTHOR SET (FIRST_NAME, LAST_NAME) = @@ -3147,12 +3147,12 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    The above row value expressions usages are completely typesafe.

    - +

    UPDATE .. RETURNING

    The Firebird and Postgres databases support a RETURNING clause on their UPDATE statements, similar as the RETURNING clause in . This is useful to fetch trigger-generated values in one go. An example is given here:

    - + create.

    The H2 database ships with a somewhat less powerful but a little more intuitive syntax for its own version of the MERGE statement. An example more or less equivalent to the previous one can be seen here:

    - + -- Check if there is already an author called 'Hitchcock' -- If there is, rename him to John. If there isn't add him. @@ -3237,7 +3237,7 @@ VALUES ('John', 'Hitchcock')create.mergeInto(AUTHOR, This syntax can be fully emulated by jOOQ for all other databases that support the SQL standard MERGE statement. For more information about the H2 MERGE syntax, see the documentation here:
    http://www.h2database.com/html/grammar.html#merge

    - +

    Typesafety of VALUES() for degrees up to {max-row-degree}

    Much like the , the MERGE statement's VALUES() clause provides typesafety for degrees up to {max-row-degree}, in both the standard syntax variant as well as the H2 variant. @@ -3258,7 +3258,7 @@ VALUES ('John', 'Hitchcock')create.mergeInto(AUTHOR, TRUNCATE TABLE AUTHOR;create.truncate(AUTHOR).execute(); - +

    TRUNCATE is not supported by Ingres and SQLite. jOOQ will execute a DELETE FROM AUTHOR statement instead.

    @@ -3282,7 +3282,7 @@ VALUES ('John', 'Hitchcock')
    create.mergeInto(AUTHOR,

    Most of the times, when thinking about a you're probably thinking about an actual table in your database schema. If you're using jOOQ's , you will have all tables from your database schema available to you as type safe Java objects. You can then use these tables in SQL , or in other , just like any other table expression. An example is given here:

    - + - +

    The above example shows how AUTHOR and BOOK tables are joined in a . It also shows how you can access by dereferencing the relevant Java attributes of their tables.

    @@ -3329,11 +3329,11 @@ create.select() .where(a.YEAR_OF_BIRTH.greaterThan(1920) .and(a.FIRST_NAME.equal("Paulo"))) .orderBy(b.TITLE);]]>
    - +

    As you can see in the above example, calling as() on generated tables returns an object of the same type as the table. This means that the resulting object can be used to dereference fields from the aliased table. This is quite powerful in terms of having your Java compiler check the syntax of your SQL statements. If you remove a column from a table, dereferencing that column from that table alias will cause compilation errors.

    - +

    Dereferencing columns from other table expressions

    Only few table expressions provide the SQL syntax typesafety as shown above, where generated tables are used. Most tables, however, expose their fields through field() methods: @@ -3345,12 +3345,12 @@ Table a = AUTHOR.as("a"); // Get fields from a: Field id = a.field("ID"); Field firstName = a.field("FIRST_NAME");]]> - +

    Derived column lists

    The SQL standard specifies how a table can be renamed / aliased in one go along with its columns. It references the term "derived column list" for the following syntax (as supported by Postgres, for instance):

    - + In jOOQ, you would simply specify a varargs list of column aliases as such:

    - + The that can be used in are the most powerful and best supported means of creating new in SQL. Informally, the following can be said:

    - + A(colA1, ..., colAn) "join" B(colB1, ..., colBm) "produces" C(colA1, ..., colAn, colB1, ..., colBm)

    @@ -3423,7 +3423,7 @@ create.select().from(values(

    jOOQ supports all of these JOIN types (except semi-join and anti-join) directly on any :

    - + table) @@ -3461,7 +3461,7 @@ Table naturalRightOuterJoin(TableLike)]]>

    Some databases allow for expressing in-memory temporary tables using a VALUES() constructor. This constructor usually works the same way as the VALUES() clause known from the or from the . With jOOQ, you can also use the VALUES() table constructor, to create tables that can be used in a :

    - + Note, that it is usually quite useful to provide column aliases ("derived column lists") along with the table alias for the VALUES() constructor.

    - +

    The above statement is emulated by jOOQ for those databases that do not support the VALUES() constructor, natively (actual emulations may vary):

    - + A can appear almost anywhere a can. Such a "nested SELECT" is often called a "derived table". Apart from many convenience methods accepting objects directly, a SELECT statement can always be transformed into a object using the asTable() method.

    - +

    Example: Scalar subquery

    - + SELECT * FROM BOOK @@ -3574,11 +3574,11 @@ create.select(AUTHOR.ID, books)

    If you are closely coupling your application to an Oracle database, you can take advantage of some Oracle-specific features, such as the PIVOT clause, used for statistical analyses. The formal syntax definition is as follows:

    - + -- SELECT .. FROM table PIVOT (aggregateFunction [, aggregateFunction] FOR column IN (expression [, expression])) -- WHERE .. - +

    The PIVOT clause is available from the type, as pivoting is done directly on a table. Currently, only Oracle's PIVOT clause is supported. Support for SQL Server's slightly different PIVOT clause will be added later. Also, jOOQ may emulate PIVOT for other dialects in the future.

    @@ -3641,7 +3641,7 @@ WHERE NOT EXISTS (

    The SQL standard specifies how SQL databases should implement ARRAY and TABLE types, as well as CURSOR types. Put simply, a CURSOR is a pointer to any materialised . Depending on the cursor's features, this table expression can be scrolled through in both directions, records can be locked, updated, removed, inserted, etc. Often, CURSOR types contain s, whereas ARRAY and TABLE types contain simple scalar values, although that is not a requirement

    - +

    ARRAY types in SQL are similar to Java's array types. They contain a "component type" or "element type" and a "dimension". This sort of ARRAY type is implemented in H2, HSQLDB and Postgres and supported by jOOQ as such. Oracle uses strongly-typed arrays, which means that an ARRAY type (VARRAY or TABLE type) has a name and possibly a maximum capacity associated with it.

    @@ -3722,12 +3722,12 @@ DSL.using(SQLDialect.SYBASE ).selectOne().getSQL();]]>

    Column expressions can be used in various SQL clauses in order to refer to one or several columns. This chapter explains how to form various types of column expressions with jOOQ. A particular type of column expression is given in the section about , where an expression may have a degree of more than one.

    - +

    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:

    - + field1 = BOOK.TITLE; @@ -3780,7 +3780,7 @@ ORDER BY BOOK.TITLE]]>
    Just like , columns can be renamed using aliases. Here is an example:

    - + SELECT FIRST_NAME || ' ' || LAST_NAME author, COUNT(*) books FROM AUTHOR JOIN BOOK ON AUTHOR.ID = AUTHOR_ID @@ -3789,18 +3789,18 @@ GROUP BY FIRST_NAME, LAST_NAME;

    Here is how it's done with jOOQ:

    - + Record record = create.select( concat(AUTHOR.FIRST_NAME, val(" "), AUTHOR.LAST_NAME).as("author"), count().as("books")) .from(AUTHOR) .join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID)) .groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME).fetchAny(); - +

    When you alias Fields like above, you can access those Fields' values using the alias name:

    - + System.out.println("Author : " + record.getValue("author")); System.out.println("Books : " + record.getValue("books")); @@ -3814,7 +3814,7 @@ System.out.println("Books : " + record.getValue("books"));

    Sometimes, this automatic mapping might not be what you needed, or jOOQ cannot know the type of a field. In those cases you would write SQL type CAST like this:

    - + -- Let's say, your Postgres column LAST_NAME was VARCHAR(30) -- Then you could do this: SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL @@ -3822,27 +3822,27 @@ SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL

    in jOOQ, you can write something like that:

    - + create.select(TAuthor.LAST_NAME.cast(PostgresDataType.TEXT));

    The same thing can be achieved by casting a Field directly to String.class, as TEXT is the default data type in Postgres to map to Java's String

    - + create.select(TAuthor.LAST_NAME.cast(String.class)); - +

    The complete CAST API in consists of these three methods:

    - + { // Cast this field to the type of another field Field cast(Field field); - + // Cast this field to a given DataType Field cast(DataType type); - + // Cast this field to the default DataType for a given Class Field cast(Class type); } @@ -3871,13 +3871,13 @@ public class DSL {

    In order to express a SQL query like this one:

    - + SELECT ((1 + 2) * (5 - 3) / 2) % 10 FROM DUAL - +

    You can write something like this in jOOQ:

    - + create.select(val(1).add(2).mul(val(5).sub(3)).div(2).mod(10);

    Datetime arithmetic expressions

    @@ -3898,14 +3898,14 @@ public class DSL { - +
    String concatenation

    The SQL standard defines the concatenation operator to be an infix operator, similar to the ones we've seen in the chapter about . This operator looks like this: ||. Some other dialects do not support this operator, but expect a concat() function, instead. jOOQ renders the right operator / function, depending on your :

    - + SELECT 'A' || 'B' || 'C' FROM DUAL -- Or in MySQL: @@ -3932,13 +3932,13 @@ create.select(concat("A", "B", "C"));
  • NVL: Get the first non-null value among two arguments.
  • NVL2: Get the second argument if the first is null, or the third argument, otherwise.
  • - +

    Please refer to the for more details.

    - +
    Numeric functions @@ -3948,7 +3948,7 @@ create.select(concat("A", "B", "C"));

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ABS: Get the absolute value of a value.
    • ACOS: Get the arc cosine of a value.
    • @@ -3979,7 +3979,7 @@ create.select(concat("A", "B", "C"));
    • TANH: Get the hyperbolic tangent of a value.
    • TRUNC: Truncate the decimals off a given value.
    - +

    Please refer to the for more details.

    @@ -4004,13 +4004,13 @@ create.select(concat("A", "B", "C"));
  • SHL: Shift bits to the left
  • SHR: Shift bits to the right
  • - +

    Some background about bitwise operation emulation

    As stated before, not all databases support all of these bitwise operations. jOOQ emulates them wherever this is possible. More details can be seen in this blog post:
    http://blog.jooq.org/2011/10/30/the-comprehensive-sql-bitwise-operations-compatibility-list/

    - +
    @@ -4023,7 +4023,7 @@ create.select(concat("A", "B", "C"));

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ASCII: Get the ASCII code of a character.
    • BIT_LENGTH: Get the length of a string in bits.
    • @@ -4044,16 +4044,16 @@ create.select(concat("A", "B", "C"));
    • TRIM: Trim a string on both sides.
    • UPPER: Get a string in upper case letters.
    - +

    Please refer to the for more details.

    - +

    Regular expressions, REGEXP, REGEXP_LIKE, etc.

    Various databases have some means of searching through columns using regular expressions if the does not provide sufficient pattern matching power. While there are many different functions and operators in the various databases, jOOQ settled for the SQL:2008 standard REGEX_LIKE operator. Being an operator (and not a function), you should use the corresponding method on :

    - +

    @@ -4069,7 +4069,7 @@ create.select(concat("A", "B", "C"));

    This is a list of date and time functions supported by jOOQ's :

    - +
    • CURRENT_DATE: Get current date as a DATE object.
    • CURRENT_TIME: Get current time as a TIME object.
    • @@ -4079,7 +4079,7 @@ create.select(concat("A", "B", "C"));
    • TIMESTAMP_ADD: Add a number of days or an interval to a timestamp.
    • TIMESTAMP_DIFF: Get the difference as an INTERVAL DAY TO SECOND between two dates.
    - +

    Intervals in jOOQ

    jOOQ fills a gap opened by JDBC, which neglects an important SQL data type as defined by the SQL standards: INTERVAL types. See the manual's section about for more details. @@ -4224,7 +4224,7 @@ GROUP BY AUTHOR_IDcreate.select(listAgg(BOOK.TITLE, ", ") WindowOverStep rank(); WindowOverStep denseRank(); WindowOverStep percentRank(); - + // Windowing functions WindowIgnoreNullsStep firstValue(Field field); WindowIgnoreNullsStep lastValue(Field field) @@ -4240,7 +4240,7 @@ GROUP BY AUTHOR_IDcreate.select(listAgg(BOOK.TITLE, ", ") // Statistical functions WindowOverStep cumeDist(); WindowOverStep ntile(int number);]]> - +

    SQL distinguishes between various window function types (e.g. "ranking functions"). Depending on the function, SQL expects mandatory PARTITION BY or ORDER BY clauses within the OVER() clause. jOOQ does not enforce those rules for two reasons:

    @@ -4255,14 +4255,14 @@ GROUP BY AUTHOR_ID
    create.select(listAgg(BOOK.TITLE, ", ")

    Here are some simple examples of window functions with jOOQ:

    - + -- Sample uses of ROW_NUMBER() ROW_NUMBER() OVER() ROW_NUMBER() OVER(PARTITION BY 1) ROW_NUMBER() OVER(ORDER BY BOOK.ID) ROW_NUMBER() OVER(PARTITION BY BOOK.AUTHOR_ID ORDER BY BOOK.ID) - + -- Sample uses of FIRST_VALUE FIRST_VALUE(BOOK.ID) OVER() FIRST_VALUE(BOOK.ID IGNORE NULLS) OVER() @@ -4272,14 +4272,14 @@ rowNumber().over() rowNumber().over().partitionByOne() rowNumber().over().partitionBy(BOOK.AUTHOR_ID) rowNumber().over().partitionBy(BOOK.AUTHOR_ID).orderBy(BOOK.ID) - + // Sample uses of firstValue() firstValue(BOOK.ID).over() firstValue(BOOK.ID).ignoreNulls().over() firstValue(BOOK.ID).respectNulls().over()
    - +

    An advanced window function example

    Window functions can be used for things like calculating a "running total". The following example fetches transactions and the running total for every transaction going back to the beginning of the transaction table (ordered by booked_at). Window functions are accessible from the previously seen type using the over() method: @@ -4304,7 +4304,7 @@ firstValue(BOOK.ID).respectNulls().over()

    In the previous chapter about , we have seen the concept of "ordered-set aggregate functions", such as Oracle's LISTAGG(). These functions have a window function / analytical function variant, as well. For example:

    - + SELECT LISTAGG(TITLE, ', ') WITHIN GROUP (ORDER BY TITLE) @@ -4384,7 +4384,7 @@ ORDER BY 1 NULLS LAST, 2 NULLS LAST

    In English, the ROLLUP() grouping function provides N+1 groupings, when N is the number of arguments to the ROLLUP() function. Each grouping has an additional group field from the ROLLUP() argument field list. The results of the second query might look something like this:

    - + GROUPING SETS() and other grouping functions:
    http://msdn.microsoft.com/en-us/library/bb510427(v=sql.105)

    - +

    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:

    - + ... fields); GroupField cube(Field... fields); @@ -4486,7 +4486,7 @@ Field groupingId(Field...);]]>

    MySQL and CUBRID don't know any grouping functions, but they support a WITH ROLLUP clause, that is equivalent to simple ROLLUP() grouping functions. jOOQ emulates ROLLUP() in MySQL and CUBRID, by rendering this WITH ROLLUP clause. The following two statements mean the same:

    - + Some databases support user-defined functions, which can be embedded in any SQL statement, if you're using jOOQ's . Let's say you have the following simple function in Oracle SQL:

    - + The above function will be made available from a generated class. You can use it like any other :

    - + - +

    Note that user-defined functions returning or data types can also be used wherever can be used, if they are

    @@ -4536,7 +4536,7 @@ END echo;

    Some databases support user-defined aggregate functions, which can then be used along with or as . An example for such a database is Oracle. With Oracle, you can define the following OBJECT type (the example was taken from the Oracle 11g documentation):

    - +

    jOOQ's will detect such aggregate functions and generate them differently from regular . They implement the type, as mentioned in the manual's section about . Here's how you can use the SECOND_MAX() aggregate function with jOOQ:

    - + - +
    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:

    - + Row1 row(T1 t1) { ... } public static Row2 row(T1 t1, T2 t2) { ... } @@ -4760,12 +4760,12 @@ public static RowN row(Object... values) { ... }]]>

    See the relevant sections for more details about how to use row value expressions in predicates.

    - +

    Using row value expressions in UPDATE statements

    The also supports a variant where row value expressions are updated, rather than single columns. See the relevant section for more details

    - +

    Higher-degree row value expressions

    jOOQ chose to explicitly support degrees up to {max-row-degree} to match Scala's typesafe tuple, function and product support. Unlike Scala, however, jOOQ also supports higher degrees without the additional typesafety. @@ -4789,7 +4789,7 @@ public static RowN row(Object... values) { ... }]]>

  • The of a
  • The 's ON clause
  • - +

    Boolean types in SQL

    Before SQL:1999, boolean types did not really exist in SQL. They were modelled by 0 and 1 numeric/char values. With SQL:1999, true booleans were introduced and are now supported by most databases. In short, these are possible boolean values: @@ -4883,7 +4883,7 @@ Condition combined2 = combined1.andNot(c); // The left-hand side of the AND NOT

    Here are all boolean operators on the interface:

    - + < to test for being strictly less
  • <= to test for being less or equal
  • - +

    Unfortunately, Java does not support operator overloading, hence these operators are also implemented as methods in jOOQ, like any other SQL syntax elements. The relevant parts of the interface are these:

    - + ); // = (some column expression) eq or equal(Select>); // = (some scalar SELECT statement) @@ -4944,12 +4944,12 @@ ge or greaterOrEqual(Select>); // >= (some scalar SELECT st

    Note that every operator is represented by two methods. A verbose one (such as equal()) and a two-character one (such as eq()). Both methods are the same. You may choose either one, depending on your taste. The manual will always use the more verbose one.

    - +

    jOOQ's convenience methods using comparison operators

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using comparison predicates:

    - +

    All variants of the that we've seen in the previous chapter also work for . If your database does not support row value expression comparison predicates, jOOQ emulates them the way they are defined in the SQL standard:

    - + (X, Y))]]>

    jOOQ supports all of the above row value expression comparison predicates, both with and at the right-hand side:

    - +
    - +
    Quantified comparison predicate @@ -5060,7 +5060,7 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    It is interesting to note that the SQL standard defines the in terms of the ANY-quantified predicate. The following two expressions are equivalent:

    - + @@ -5070,14 +5070,14 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    - +
    NULL predicate

    In SQL, you cannot compare NULL with any value using , as the result would yield NULL again, which is neither TRUE nor FALSE (see also the manual's section about ). In order to test a for NULL, use the NULL predicate as such:

    - + The SQL standard contains a nice truth table for the above rules:

    - + +-----------------------+-----------+---------------+---------------+-------------------+ | Expression | R IS NULL | R IS NOT NULL | NOT R IS NULL | NOT R IS NOT NULL | +-----------------------+-----------+---------------+---------------+-------------------+ @@ -5127,11 +5127,11 @@ NOT((A, B) IS NOT NULL)]]>
    In jOOQ, you would simply use the isNull() and isNotNull() methods on row value expressions. Again, as with the , the row value expression NULL predicate is emulated by jOOQ, if your database does not natively support it:

    - +
    - +
    DISTINCT predicate @@ -5157,7 +5157,7 @@ BOOK.TITLE.isNotDistinctFrom(BOOK.SUB_TITLE)]]>

    If your database does not natively support the DISTINCT predicate, jOOQ emulates it with an equivalent , modelling the above truth table:

    - + The BETWEEN predicate can be seen as syntactic sugar for a pair of . According to the SQL standard, the following two predicates are equivalent:

    - + = [B] AND [A] <= [C]]]> @@ -5203,7 +5203,7 @@ BOOK.PUBLISHED_IN.notBetween(1920).and(1940)]]>

    The SQL standard defines the SYMMETRIC keyword to be used along with BETWEEN to indicate that you do not care which bound of the range is larger than the other. A database system should simply swap range bounds, in case the first bound is greater than the second one. jOOQ supports this keyword as well, emulating it if necessary.

    - +

    The emulation is done trivially:

    - + @@ -5227,24 +5227,24 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The SQL BETWEEN predicate also works well for . Much like the , it is defined in terms of a pair of regular :

    - + = [B] AND [A] <= [C] ([A] >= [B] AND [A] <= [C]) OR ([A] >= [C] AND [A] <= [B])]]> - +

    The above can be factored out according to the rules listed in the manual's section about .

    - +

    jOOQ supports the BETWEEN [SYMMETRIC] predicate and emulates it in all SQL dialects where necessary. An example is given here:

    - +
    - +
    LIKE predicate @@ -5264,7 +5264,7 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]> TITLE NOT LIKE '%abc%']]> - +

    Escaping operands with the LIKE predicate

    Often, your pattern may contain any of the wildcard characters "_" and "%", in case of which you may want to escape them. jOOQ does not automatically escape patterns in like() and notLike() methods. Instead, you can explicitly define an escape character as such: @@ -5282,12 +5282,12 @@ BOOK.TITLE.notLike("%The !%-Sign Book%", '!')]]>

    Please refer to your database manual for more details about escaping patterns with the LIKE predicate.

    - +

    jOOQ's convenience methods using the LIKE predicate

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using the LIKE predicate. Typical operations are "contains predicates", "starts with predicates", "ends with predicates", etc. Here is the full convenience API wrapping LIKE predicates:

    - + >) // Construct a NOT IN predicate from a subse

    A sample IN predicate might look like this:

    - + - +

    NOT IN and NULL values

    Beware that you should probably not have any NULL values in the right hand side of a NOT IN predicate, as the whole expression would evaluate to NULL, which is rarely desired. This can be shown informally using the following reasoning:

    - + -- The following conditional expressions are formally or informally equivalent A NOT IN (B, C) A != ANY(B, C) @@ -5375,10 +5375,10 @@ NULL -- [ANY] AND NULL yields NULL

    jOOQ supports the IN predicate. Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value. An example is given here:

    - +
    - +
    EXISTS predicate @@ -5390,7 +5390,7 @@ NULL -- [ANY] AND NULL yields NULL
  • From a using
  • From a using , and from other clauses
  • - +

    An example of an EXISTS predicate can be seen here:

    @@ -5408,7 +5408,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

    - +

    Performance of IN vs. EXISTS

    In theory, the two types of predicates can perform equally well. If your database system ships with a sophisticated cost-based optimiser, it will be able to transform one predicate into the other, if you have all necessary constraints set (e.g. referential constraints, not null constraints). However, in reality, performance between the two might differ substantially. An interesting blog post investigating this topic on the MySQL database can be seen here:
    @@ -5416,7 +5416,7 @@ notExists(create.selectOne().from(BOOK)

    - +
    OVERLAPS predicate @@ -5454,7 +5454,7 @@ row(Date.valueOf('2010-01-01'), new DayToSecond(2)).overlaps(Date.valueOf('2010-

    Unlike the standard (or any database implementing the standard), jOOQ also supports the OVERLAPS predicate for comparing arbitrary . For instance, (1, 3) OVERLAPS (2, 4) will yield true in jOOQ. This is emulated as such

    - +
    - +
    Dynamic SQL

    In most cases, , , and as introduced in the previous chapters will be embedded into different SQL statement clauses as if the statement were a static SQL statement (e.g. in a view or stored procedure):

    - + - +

    It is, however, interesting to think of all of the above expressions as what they are: expressions. And as such, nothing keeps users from extracting expressions and referencing them from outside the statement. The following statement is exactly equivalent:

    @@ -5497,26 +5497,26 @@ create.select(select) .groupBy(groupBy) .orderBy() .fetch();]]> - +

    Each individual expression, and collection of expressions can be seen as an independent entity that can be

    - +
    1. Constructed dynamically
    2. Reused across queries
    - +

    Dynamic construction is particularly useful in the case of the , for dynamic predicate building. For instance:

    - +

    The dynamic SQL building power may be one of the biggest advantages of using a runtime query model like the one offered by jOOQ. Queries can be created dynamically, of arbitrary complexity. In the above example, we've just constructed a dynamic . The same can be done for any other clauses, including dynamic as needed.

    @@ -5552,7 +5552,7 @@ create.select()
  • - +

    You'll probably find other examples. If verbosity scares you off, don't worry. The verbose use-cases for jOOQ are rather rare, and when they come up, you do have an option. Just write SQL the way you're used to!

    @@ -5582,7 +5582,7 @@ Condition condition(String sql, Object... bindings); // Construct a condition taking other jOOQ object arguments // Example: condition("a = {0}", val(1)); 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 DSL:

    @@ -5640,7 +5640,7 @@ Result fetch(String sql, QueryPart... parts);]]>

    Apart from the general factory methods, plain SQL is also available in various other contexts. For instance, when adding a .where("a = b") clause to a query. Hence, there exist several convenience methods where plain SQL can be inserted usefully. This is an example displaying all various use-cases in one single query:

    - + LAST_NAME = create.field("a.LAST_NAME"); @@ -5699,7 +5699,7 @@ create.select(LAST_NAME, COUNT1, COUNT2) On a JDBC level, you can also reuse the SQL string and prepared statement object instead of constructing it again, as you can bind new values to the prepared statement. jOOQ currently does not cache prepared statements, internally. - +

    The following sections explain how you can introduce bind values in jOOQ, and how you can control the way they are rendered and bound to SQL.

    @@ -5712,7 +5712,7 @@ create.select(LAST_NAME, COUNT1, COUNT2)

    JDBC only knows indexed bind values. A typical example for using bind values with JDBC is this:

    - + With dynamic SQL, keeping track of the number of question marks and their corresponding index may turn out to be hard. jOOQ abstracts this and lets you provide the bind value right where it is needed. A trivial example is this:

    - + 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

    Should you decide to run the above query outside of jOOQ, using your own , you can do so as follows:

    - + select = create.select().from(BOOK).where(BOOK.ID.equal(5)).and(BOOK.TITLE.equal("Animal Farm")); // Render the SQL statement: @@ -5863,7 +5863,7 @@ create.select()

    Special care needs to be taken when using . While jOOQ's API allows you to specify bind values for use with plain SQL, you're not forced to do that. For instance, both of the following queries will lead to the same, valid result:

    - +

    A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] FROM AUTHOR JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID @@ -6006,15 +6006,15 @@ public final void toSQL(RenderContext context) {

    As mentioned in the previous chapter about , there are some elements in the that are used for formatting / pretty-printing rendered SQL. In order to obtain pretty-printed SQL, just use the following :

    - - + +

    And then, use the above DSLContext to render pretty-printed SQL:

    - + A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] WHERE AUTHOR.ID = ? -- [...] @@ -6102,7 +6102,7 @@ public final void bind(BindContext context) throws DataAccessException {

    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:

    - + extends AbstractField {} public abstract class CustomCondition extends AbstractCondition {} public abstract class CustomTable> extends TableImpl {} @@ -6111,7 +6111,7 @@ public abstract class CustomRecord> extends TableRecord

    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 and methods, as discussed before:

    - + 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 showing how to create a field multiplying another field by 2

    - + IDx2 = new CustomField(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(" * ?"); @@ -6148,10 +6148,10 @@ final Field IDx2 = new CustomField(BOOK.ID.getName(), BOOK.ID. @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(DSL.val(2)); } @@ -6164,7 +6164,7 @@ final Field IDx2 = new CustomField(BOOK.ID.getName(), BOOK.ID. // Use the above field in a SQL statement: create.select(IDx2).from(BOOK);]]>
    - +
    Plain SQL QueryParts @@ -6178,7 +6178,7 @@ create.select(IDx2).from(BOOK);]]>

    The above distinction is best explained using an example:

    - +
    - +
    SQL building in Scala

    jOOQ-Scala is a maven module used for leveraging some advanced Scala features for those users that wish to use jOOQ with Scala.

    - +

    Using Scala's implicit defs to allow for operator overloading

    The most obvious Scala feature to use in jOOQ are implicit defs for implicit conversions in order to enhance the type with SQL-esque operators. @@ -6235,7 +6235,7 @@ create.attach(select);]]>

    The following depicts a trait which wraps all fields:

    - + The following depicts a trait which wraps numeric fields:

    - + An example query using such overloaded operators would then look like this:

    - +

    In a previous section of the manual, we've seen how jOOQ can be used to that can be executed with any API including JDBC or ... jOOQ. This section of the manual deals with various means of actually executing SQL with jOOQ.

    - +

    SQL execution with JDBC

    JDBC calls executable objects "". It distinguishes between three types of statements: @@ -6375,7 +6375,7 @@ fetch]]>

    Today, the JDBC API may look weird to users being used to object-oriented design. While statements hide a lot of SQL dialect-specific implementation details quite well, they assume a lot of knowledge about the internal state of a statement. For instance, you can use the method, to add a the prepared statement being created to an "internal list" of batch statements. Instead of returning a new type, this method forces user to reflect on the prepared statement's internal state or "mode".

    - +

    jOOQ is wrapping JDBC

    These things are abstracted away by jOOQ, which exposes such concepts in a more object-oriented way. For more details about jOOQ's batch query execution, see the manual's section about . @@ -6397,7 +6397,7 @@ fetch]]>

  • Both APIs return the number of affected records in non-result queries. JDBC: , jOOQ:
  • Both APIs return a scrollable result set type from result queries. JDBC: , jOOQ:
  • - +

    Differences to JDBC

    Some of the most important differences between JDBC and jOOQ are listed here: @@ -6412,14 +6412,14 @@ fetch]]>

    - +
    Query vs. ResultQuery

    Unlike JDBC, jOOQ has a lot of knowledge about a SQL query's structure and internals (see the manual's section about ). Hence, jOOQ distinguishes between these two fundamental types of queries. While every can be executed, only can return results (see the manual's section about to learn more about fetching results). With plain SQL, the distinction can be made clear most easily:

    - + result = resultQuery.fetch();]]>
  • : Some databases allow for returning many result sets from a single query. JDBC can handle this but it's very verbose. A list of results should be returned instead.
  • : Some queries take too long to execute to wait for their results. You should be able to spawn query execution in a separate process.
  • - +

    Convenience and how ResultQuery, Result, and Record share API

    The term "fetch" is always reused in jOOQ when you can fetch data from the database. An provides many overloaded means of fetching data:

    - +

    Various modes of fetching

    These modes of fetching are also documented in subsequent sections of the manual

    - + fetch(); @@ -6484,7 +6484,7 @@ List> fetchMany(); // Execute a ResultQuery with jOOQ, but return a JDBC ResultSet, not a jOOQ object ResultSet fetchResultSet();]]> - +

    Fetch convenience

    These means of fetching are also available from and APIs @@ -6530,11 +6530,11 @@ ResultSet fetchResultSet();]]>

    These means of fetching are also available from and APIs

    - + Map fetchMap(Field key); Map fetchMap(Field key, Field value); @@ -6571,7 +6571,7 @@ ResultSet fetchResultSet();]]>

    jOOQ understands that SQL is much more expressive than Java, when it comes to the declarative typing of . As a declarative language, SQL allows for creating ad-hoc row value expressions (records with indexed columns, or tuples) and records (records with named columns). In Java, this is not possible to the same extent. Yet, still, sometimes you wish to use strongly typed records, when you know that you're selecting only from a single table

    - +

    Fetching strongly or weakly typed records

    When fetching data only from a single table, the type is known to jOOQ if you use jOOQ's to generate for your database tables. In order to fetch such strongly typed records, you will have to use the : @@ -6583,7 +6583,7 @@ BookRecord book = create.selectFrom(BOOK).where(BOOK.ID.equal(1)).fetchOne(); // Typesafe field access is now possible: 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:

    @@ -6629,7 +6629,7 @@ System.out.println("Published in: " + book.getPublishedIn());]]>

    By default, jOOQ returns an object, which is essentially a of . Often, you will find yourself wanting to transform this result object into a type that corresponds more to your specific needs. Or you just want to list all values of one specific column. Here are some examples to illustrate those use cases:

    - + titles1 = create.select().from(BOOK).fetch().getValues(BOOK.TITLE); List titles2 = create.select().from(BOOK).fetch(BOOK.TITLE); @@ -6664,7 +6664,7 @@ Map> group4 = create.selectFrom(BOOK).fetchGroups(BO

    In a more functional operating mode, you might want to write callbacks that receive records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + () {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -6699,7 +6699,7 @@ create.selectFrom(BOOK)

    In a more functional operating mode, you might want to write callbacks that map records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + ids = create.selectFrom(BOOK) @@ -6711,12 +6711,12 @@ create.selectFrom(BOOK) return book.getId(); } }); - + // Or more concisely create.selectFrom(BOOK) .orderBy(BOOK.ID) .fetch(new RecordMapper() {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -6738,7 +6738,7 @@ create.selectFrom(BOOK)

    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.

    - +

    Using JPA-annotated POJOs

    jOOQ tries to find JPA annotations on your POJO types. If it finds any, they are used as the primary source for mapping meta-information. Only the annotation is used and understood by jOOQ. An example: @@ -6748,7 +6748,7 @@ create.selectFrom(BOOK) public class MyBook { @Column(name = "ID") public int myId; - + @Column(name = "TITLE") public String myTitle; } @@ -6757,16 +6757,16 @@ public class MyBook { MyBook myBook = create.select().from(BOOK).fetchAny().into(MyBook.class); List myBooks = create.select().from(BOOK).fetch().into(MyBook.class); List myBooks = create.select().from(BOOK).fetchInto(MyBook.class);]]> - +

    Just as with any other JPA implementation, you can put the annotation on any class member, including attributes, setters and getters. Please refer to the Javadoc for more details.

    - +

    Using simple POJOs

    If jOOQ does not find any JPA-annotations, columns are mapped to the "best-matching" constructor, attribute or setter. An example illustrates this:

    - + myBooks = create.select().from(BOOK).fetchInto(MyBook1.class);]]><

    Please refer to the Javadoc for more details.

    - +

    Using "immutable" POJOs

    If jOOQ does not find any default constructor, columns are mapped to the "best-matching" constructor. This allows for using "immutable" POJOs with jOOQ. An example illustrates this:

    - + myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchInto( public class MyBook3 { public final String title; public final int id; - + @ConstructorProperties({ "title", "id"}) public MyBook2(String title, int id) { this.title = title; @@ -6821,7 +6821,7 @@ MyBook3 myBook = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchA List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetch().into(MyBook3.class); List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchInto(MyBook3.class); ]]> - +

    Please refer to the Javadoc for more details.

    @@ -6830,12 +6830,12 @@ List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchI

    jOOQ also allows for fetching data into abstract classes or interfaces, or in other words, "proxyable" types. This means that jOOQ will return a wrapped in a implementing your custom type. An example of this is given here:

    - + - +

    Note: Because of your manual setting of ID = 10, jOOQ's store() method will asume that you want to insert a new record. See the manual's section about for more details on this.

    - +

    Interaction with DAOs

    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: @@ -6902,7 +6902,7 @@ bookDao.update(book); // Delete it again bookDao.delete(book);]]> - +

    More complex data structures

    jOOQ currently doesn't support more complex data structures, the way Hibernate/JPA attempt to map relational data onto POJOs. While future developments in this direction are not excluded, jOOQ claims that generic mapping strategies lead to an enormous additional complexity that only serves very few use cases. You are likely to find a solution using any of jOOQ's various , with only little boiler-plate code on the client side. @@ -6916,7 +6916,7 @@ bookDao.delete(book);]]>

    Unlike JDBC's , jOOQ's does not represent an open database cursor with various fetch modes and scroll modes, that needs to be closed after usage. jOOQ's results are simple in-memory Java objects, containing all of the result values. If your result sets are large, or if you have a lot of network latency, you may wish to fetch records one-by-one, or in small chunks. jOOQ supports a type for that purpose. In order to obtain such a reference, use the method. An example is given here:

    - + cursor = null; @@ -6926,7 +6926,7 @@ try { // Cursor has similar methods as Iterator while (cursor.hasNext()) { BookRecord book = cursor.fetchOne(); - + Util.doThingsWithBook(book); } } @@ -6941,7 +6941,7 @@ finally {

    As a holds an internal reference to an open , it may need to be closed at the end of iteration. If a cursor is completely scrolled through, it will conveniently close the underlying ResultSet. However, you should not rely on that.

    - +

    Cursors ship with all the other fetch features

    Like or , gives access to all of the other fetch features that we've seen so far, i.e. @@ -6983,7 +6983,7 @@ finally {

    The correct (and verbose) way to do this with JDBC is as follows:

    - +

    As previously discussed in the chapter about , jOOQ does not rely on an internal state of any JDBC object, which is "externalised" by Javadoc. Instead, it has a straight-forward API allowing you to do the above in a one-liner:

    - + > results = create.fetchMany("sp_help 'author'");]]> @@ -7024,22 +7024,22 @@ List> results = create.fetchMany("sp_help 'author'");]]>
    Later fetching

    Using Java 8 CompletableFutures

    - +

    Java 8 has introduced the new type, which allows for functional composition of asynchronous execution units. When applying this to SQL and jOOQ, you might be writing code as follows:

    - + + .supplyAsync(() -> DSL.using(configuration) .insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .values(3, "Hitchcock") .execute() ) - + // This will supply an AuthorRecord value for the newly inserted author .handleAsync((rows, throwable) -> DSL.using(configuration) @@ -7052,30 +7052,30 @@ CompletableFuture record.changed(true); return record.insert(); }) - + // This will supply an int value indicating the number of deleted rows - .handleAsync((rows, throwable) -> + .handleAsync((rows, throwable) -> DSL.using(configuration) .delete(AUTHOR) .where(AUTHOR.ID.eq(3)) .execute() ) .join();]]> - +

    The above example will execute four actions one after the other, but asynchronously in the JDK's default or common . -

    - +

    +

    For more information, please refer to the Javadoc and official documentation. -

    - +

    +

    Using deprecated API

    - +

    Some queries take very long to execute, yet they are not crucial for the continuation of the main program. For instance, you could be generating a complicated report in a Swing application, and while this report is being calculated in your database, you want to display a background progress bar, allowing the user to pursue some other work. This can be achived simply with jOOQ, by creating a , a type that extends . An example is given here:

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(); @@ -7091,7 +7091,7 @@ Result result = future.get();]]>

    Note, that instead of letting jOOQ spawn a new thread, you can also provide jOOQ with your own :

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(service);]]>
    @@ -7103,7 +7103,7 @@ FutureResult future = create.selectFrom(BOOK).where(... complex pred

    When interacting with legacy applications, you may prefer to have jOOQ return a , rather than jOOQ's own types. This can be done simply, in two ways:

    - + cursor = create.fetchLazy(rs);]]>

    You can also tighten the interaction with jOOQ's data type system and features, by passing the record type to the above fetch methods:

    - + result = create.fetch (rs, Integer.class, String.class); Cursor result = create.fetchLazy(rs, Integer.class, String.class); @@ -7165,7 +7165,7 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Apart from a few extra features (), jOOQ only supports basic types as supported by the JDBC API. In your application, you may choose to transform these data types into your own ones, without writing too much boiler-plate code. This can be done using jOOQ's types. A converter essentially allows for two-way conversion between two Java data types <T> and <U>. By convention, the <T> type corresponds to the type in your database whereas the <U> type corresponds to your own user type. The Converter API is given here:

    - + extends Serializable { /** @@ -7192,12 +7192,12 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Such a converter can be used in many parts of the jOOQ API. Some examples have been illustrated in the manual's section about .

    - +

    A Converter for GregorianCalendar

    Here is a some more elaborate example involving a Converter for :

    - + { @@ -7228,12 +7228,12 @@ public class CalendarConverter implements Converter dates1 = create.selectFrom(BOOK).fetch().getValues(BOOK.PUBLISHING_DATE, new CalendarConverter()); List dates2 = create.selectFrom(BOOK).fetch(BOOK.PUBLISHING_DATE, new CalendarConverter()); ]]> - +

    Enum Converters

    jOOQ ships with a built-in default , that you can use to map VARCHAR values to enum literals or NUMBER values to enum ordinals (both modes are supported). Let's say, you want to map a YES / NO / MAYBE column to a custom Enum:

    - + - +

    Using Converters in generated source code

    jOOQ also allows for generated source code to reference your own custom converters, in order to permanently replace a <T> type by your own, custom <U> type. See the manual's section about for details. @@ -7295,20 +7295,20 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE) .join(AUTHOR).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) .intern(BOOK.AUTHOR_ID) .fetch();]]> - +

    You can specify as many fields as you want for interning. The above has the following effect:

    - +
    • If the interned Field is of type , then is called upon each string
    • If the interned Field is of any other type, then the call is ignored
    - +

    Future versions of jOOQ will implement interning of data for non-String data types by collecting values in , removing duplicate instances.

    - +

    Note, that jOOQ will not use interned data for identity comparisons: string1 == string2. Interning is used only to reduce the memory footprint of objects.

    @@ -7316,7 +7316,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)
    - +
    Static statements vs. Prepared Statements @@ -7326,7 +7326,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)

    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:

    - + @@ -7355,7 +7355,7 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    Whichever aproach is more optimal for you cannot be decided by jOOQ. In most cases, prepared statements are probably better. But you always have the option of forcing jOOQ to render inlined bind values.

    - +

    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 @@ -7369,15 +7369,15 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    As previously discussed in the chapter about , reusing PreparedStatements is handled a bit differently in jOOQ from how it is handled in JDBC

    - +

    Keeping open PreparedStatements with JDBC

    With JDBC, you can easily reuse a by not closing it between subsequent executions. An example is given here:

    - + The above technique can be quite useful when you want to reuse expensive database resources. This can be the case when your statement is executed very frequently and your database would take non-negligible time to soft-parse the prepared statement and generate a new statement / cursor resource.

    - +

    Keeping open PreparedStatements with jOOQ

    This is also modeled in jOOQ. However, the difference to JDBC is that closing a statement is the default action, whereas keeping it open has to be configured explicitly. This is better than JDBC, because the default action should be the one that is used most often. Keeping open statements is rarely done in average applications. Here's an example of how to keep open PreparedStatements with jOOQ:

    - + query = create.selectOne().keepStatement(true); @@ -7507,18 +7507,18 @@ create.batch(create.insertInto(AUTHOR, ID, FIRST_NAME, LAST_NAME ).values((Inte

    Instead of actually phrasing a select statement, you can also use the convenience methods:

    - + - +

    Inlining sequence references in SQL

    You can inline sequence references in jOOQ SQL statements. The following are examples of how to do that:

    - + The general distinction between (stored) procedures and (stored) functions can be summarised like this:

    - +

    Procedures

    • Are called using JDBC CallableStatement
    • Have no return value
    • Usually support OUT parameters
    - +

    Functions

    • Can be used in SQL statements
    • Have a return value
    • Usually don't support OUT parameters
    - +

    Exceptions to these rules

    • DB2, H2, and HSQLDB don't allow for JDBC escape syntax when calling functions. Functions must be used in a SELECT statement
    • @@ -7578,19 +7578,19 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

      To simplify things a little bit, jOOQ handles both procedures and functions the same way, using a more general type.

      - +

      Using jOOQ for standalone calls to stored procedures and functions

      If you're using jOOQ's , it will generate objects for you. Let's consider the following example:

      - +

      The generated artefacts can then be used as follows:

      - + - +

      But you can also call the procedure using a generated convenience method in a global Routines class:

      @@ -7617,7 +7617,7 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]>

      For more details about for procedures, see the manual's section about .

      - +

      Inlining stored function references in SQL

      Unlike procedures, functions can be inlined in SQL statements to generate or , if you're using . Assume you have a function like this: @@ -7625,11 +7625,11 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]> - +

      The generated artefacts can then be used as follows:

      - + - +

      For more info about inlining stored function references in SQL statements, please refer to the manual's section about .

      @@ -7669,7 +7669,7 @@ create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]>

      Oracle UDTs can have object-oriented structures including member functions and procedures. With Oracle, you can do things like this:

      - + {"name":"field-n","type":"type-n"}], "records":[[value-1-1,value-1-2,...,value-1-n], [value-2-1,value-2-2,...,value-2-n]]} - +

      Note: This format has changed in jOOQ 2.6.0

      @@ -7994,12 +7994,12 @@ Query query = error.query();]]>

      CRUD always uses the same patterns, regardless of the nature of underlying tables. This again, leads to a lot of boilerplate code, if you have to issue your statements yourself. Like Hibernate / JPA and other ORMs, jOOQ facilitates CRUD using a specific API involving types.

      - +

      Primary keys and updatability

      In normalised databases, every table has a primary key by which a tuple/record within that table can be uniquely identified. In simple cases, this is a (possibly auto-generated) number called ID. But in many cases, primary keys include several non-numeric columns. An important feature of such keys is the fact that in most databases, they are enforced using an index that allows for very fast random access to the table. A typical way to access / modify / delete a book is this:

      - + - +

      Normalised databases assume that a primary key is unique "forever", i.e. that a key, once inserted into a table, will never be changed or re-inserted after deletion. In order to use jOOQ's operations correctly, you should design your database accordingly.

      @@ -8020,7 +8020,7 @@ DELETE FROM BOOK WHERE ID = 5;]]>

      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:

      - + - +

      See the manual's section about for some more insight on "attached" objects.

      - +

      Storing

      Storing a record will perform an or an . In general, new records are always inserted, whereas records loaded from the database are always updated. This is best visualised in code: @@ -8059,7 +8059,7 @@ BookRecord book2 = create.fetchOne(BOOK, BOOK.ID.equal(id)); // Update the record: UPDATE BOOK SET TITLE = 'Animal Farm' WHERE ID = [id] book2.setTitle("Animal Farm"); book2.store();]]> - +

      Some remarks about storing:

      @@ -8069,18 +8069,18 @@ book2.store();]]>
    • When loading records from , jOOQ will assume the record is a new record. It will hence attempt to INSERT it.
    • When you activate , storing a record may fail, if the underlying database record has been changed in the mean time.
    - +

    Deleting

    Deleting a record will remove it from the database. Here's how you delete records:

    - + - +

    Refreshing

    Refreshing a record from the database means that jOOQ will issue a to refresh all record values that are not the primary key. This is particularly useful when you use jOOQ's feature, in case a modified record is "stale" and cannot be stored to the database, because the underlying database record has changed in the mean time. @@ -8099,7 +8099,7 @@ book.refresh();]]>

    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 :

    - + The "original" value, i.e. the value as it was originally fetched from the database or null, if the record was never in the database
  • The "changed" flag, indicating if the value was ever changed through the Record API.
  • - +

    The purpose of the above information is for jOOQ's to know, which values need to be stored to the database, and which values have been left untouched.

    @@ -8134,19 +8134,19 @@ for (BookRecord book : create.fetch(BOOK, BOOK.PUBLISHED_IN.equal(1948))) {

    Many databases support the concept of IDENTITY values, or key values. This is reflected by JDBC's method. jOOQ abstracts using this method as many databases and JDBC drivers behave differently with respect to generated keys. Let's assume the following SQL Server BOOK table:

    - +

    If you're using jOOQ's , the above table will generate a with an IDENTITY column. This information is used by jOOQ internally, to update IDs after calling :

    - +

    and contain foreign key navigation methods. These navigation methods allow for "navigating" inbound or outbound foreign key references by executing an appropriate query. An example is given here:

    - + books = author.fetchChildren(FK_BOOK_AUTHOR);]]>

    Tables without a PRIMARY KEY are considered non-updatable by jOOQ, as jOOQ has no way of uniquely identifying such a record within the database. If you're using jOOQ's , such tables will generate classes, instead of classes. When you fetch from such a table, the returned records will not allow for calling any of the methods.

    - +

    Note, that some databases use internal rowid or object-id values to identify such records. jOOQ does not support these vendor-specific record meta-data.

    @@ -8276,7 +8276,7 @@ Result books = author.fetchChildren(FK_BOOK_AUTHOR);]]>
    - +

    Optimised optimistic locking using TIMESTAMP fields

    If you're using jOOQ's , you can take indicate TIMESTAMP or UPDATE COUNTER fields for every generated table in the . Let's say we have this table:

    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:

    - +

    As before, without the added TIMESTAMP column, optimistic locking is transparent to the API.

    - +

    Optimised optimistic locking using VERSION fields

    Instead of using TIMESTAMPs, you may also use numeric VERSION fields, containing version numbers that are incremented by jOOQ upon store() calls. @@ -8345,7 +8345,7 @@ book2.store();]]>

    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:

    - + books = create.fetch(BOOK); @@ -8370,7 +8370,7 @@ create.batchStore(books);]]>

    If you're using jOOQ's , you can configure it to generate and DAOs for you. jOOQ then generates one DAO per , i.e. per table with a single-column primary key. Generated DAOs implement a common jOOQ type called . This type contains the following methods:

    - + corresponds to the DAO's related table //

    corresponds to the DAO's related generated POJO type // corresponds to the DAO's related table's primary key type. @@ -8381,23 +8381,23 @@ public interface DAO, P, T> { void insert(P object) throws DataAccessException; void insert(P... objects) throws DataAccessException; void insert(Collection

    objects) throws DataAccessException; - + // These methods allow for updating POJOs based on their primary key void update(P object) throws DataAccessException; void update(P... objects) throws DataAccessException; void update(Collection

    objects) throws DataAccessException; - + // These methods allow for deleting POJOs based on their primary key void delete(P... objects) throws DataAccessException; void delete(Collection

    objects) throws DataAccessException; void deleteById(T... ids) throws DataAccessException; void deleteById(Collection ids) throws DataAccessException; - + // These methods allow for checking record existence boolean exists(P object) throws DataAccessException; boolean existsById(T id) throws DataAccessException; long count() throws DataAccessException; - + // These methods allow for retrieving POJOs by primary key or by some other field List

    findAll() throws DataAccessException; P findById(T id) throws DataAccessException; @@ -8426,7 +8426,7 @@ public class BookDao extends DAOImpl {

    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:

    - +

    With jOOQ, it's simple. All of jOOQ's exceptions are "system exceptions", hence they are all unchecked.

    - +

    jOOQ's DataAccessException

    jOOQ uses its own to wrap any underlying that might have occurred. Note that all methods in jOOQ that may cause such a DataAccessException document this both in the Javadoc as well as in their method signature. @@ -8475,7 +8475,7 @@ bookDao.delete(book);]]>

  • InvalidResultException: An operation was performed expecting only one result, but several results were returned.
  • MappingException: Something went wrong when loading a record from a or when mapping a record into a POJO
  • - +

    Override jOOQ's exception handling

    The following section about documents means of overriding jOOQ's exception handling, if you wish to deal separately with some types of constraint violations, or if you raise business errors from your database, etc. @@ -8507,11 +8507,11 @@ public class StatisticsListener extends DefaultExecuteListener { public void start(ExecuteContext ctx) { synchronized (STATISTICS) { Integer count = STATISTICS.get(ctx.type()); - + if (count == null) { count = 0; } - + STATISTICS.put(ctx.type(), count + 1); } } @@ -8554,7 +8554,7 @@ for (ExecuteType type : ExecuteType.values()) {

    Please read the for more details

    - +

    Writing a custom ExecuteListener for logging

    The following depicts an example of a custom ExecuteListener, which pretty-prints all queries being executed by jOOQ to stdout: @@ -8577,7 +8577,7 @@ public class PrettyPrinter extends DefaultExecuteListener { // Create a new DSLContext for logging rendering purposes // This DSLContext doesn't need a connection, only the SQLDialect... DSLContext create = DSL.using(ctx.configuration().dialect(), - + // ... and the flag for pretty-printing new Settings().withRenderFormatted(true)); @@ -8585,12 +8585,12 @@ public class PrettyPrinter extends DefaultExecuteListener { if (ctx.query() != null) { System.out.println(create.renderInlined(ctx.query())); } - + // If we're executing a routine else if (ctx.routine() != null) { System.out.println(create.renderInlined(ctx.routine())); } - + // If we're executing anything else (e.g. plain SQL) else if (!StringUtils.isBlank(ctx.sql())) { System.out.println(ctx.sql()); @@ -8618,7 +8618,7 @@ public class PrettyPrinter extends DefaultExecuteListener {

    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:

    - + @@ -8636,7 +8636,7 @@ public class PrettyPrinter extends DefaultExecuteListener {

    With the above configuration, let's fetch some data with jOOQ

    - + @@ -8685,7 +8685,7 @@ Finishing : Total: 4.814ms, +3.375ms
  • 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
  • - +

    Optimise wisely

    Don't be put off by the above paragraphs. You should optimise wisely, i.e. only in places where you really need very high throughput to your database. jOOQ's overhead compared to plain JDBC is typically less than 1ms per query. @@ -8742,7 +8742,7 @@ Finishing : Total: 4.814ms, +3.375ms

    You need to tell jOOQ some things about your database connection. Here's an example of how to do it for an Oracle database

    - + @@ -8751,7 +8751,7 @@ Finishing : Total: 4.814ms, +3.375ms jdbc:oracle:thin:@[your jdbc connection parameters] [your database user] [your database password] - + user[db-user] @@ -8828,13 +8828,13 @@ Finishing : Total: 4.814ms, +3.375ms

    Code generation works by calling this class with the above property file as argument.

    - + org.jooq.util.GenerationTool /jooq-config.xml

    Be sure that these elements are located on the classpath:

    - +
    • The XML configuration file
    • jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar
    • @@ -8859,7 +8859,7 @@ Finishing : Total: 4.814ms, +3.375ms
    • this example uses jOOQ's log4j support by adding log4j.xml and log4j.jar to the project classpath.
    • the actual jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar artefacts may contain version numbers in the file names.
    - +
    Eclipse configuration
    @@ -9129,7 +9129,7 @@ public class AsInDatabaseStrategy extends DefaultGeneratorStrategy { optimistic locking (A Java regular expression. Use the pipe to separate several expressions). See UpdatableRecord.store() and UpdatableRecord.delete() for details --> REC_TIMESTAMP - + @@ -9233,18 +9233,18 @@ public class AsInDatabaseStrategy extends DefaultGeneratorStrategy { false - + true ]]>
    @@ -9253,7 +9253,7 @@ public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {

    Some of the above properties depend on other properties to work correctly. For instance, when generating immutable pojos, pojos must be generated. jOOQ will enforce such properties even if you tell it otherwise. Here is a list of property interdependencies:

    - +
    • When daos = true, then jOOQ will set relations = true
    • When daos = true, then jOOQ will set records = true
    • @@ -9276,12 +9276,12 @@ public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {
    • Tables.java: This file contains all table objects in the form of static member references to the actual singleton object
    • UDTs.java: This file contains all UDT objects in the form of static member references to the actual singleton object
    - +

    Referencing global artefacts

    When referencing global artefacts from your client application, you would typically static import them as such:

    - + @@ -9303,7 +9303,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate a implementation that looks like this:

    - + { // The singleton instance @@ -9319,7 +9319,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE) public Book as(java.lang.String alias) { return new Book(alias); } - + // [...] }]]> @@ -9336,7 +9336,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)
  • instanceFields: This flag controls the "static" keyword on table columns, as well as aliasing convenience
  • records: The generated record type is referenced from tables allowing for type-safe single-table record fetching
  • - +

    Flags controlling table generation

    Table generation cannot be deactivated @@ -9350,7 +9350,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate an implementation that looks like this:

    - + - +

    Flags influencing generated records

    These flags from the influence generated records: @@ -9406,7 +9406,7 @@ implements IBook {

  • interfaces: If interfaces are generated, records will implement them
  • jpaAnnotations: JPA annotations are used on generated records
  • - +

    Flags controlling record generation

    Record generation can be deactivated using the records flag @@ -9420,7 +9420,7 @@ implements IBook {

    Every table in your database will generate a POJO implementation that looks like this:

    - + - +

    Flags influencing generated POJOs

    These flags from the influence generated POJOs: @@ -9469,7 +9469,7 @@ public class Book implements java.io.Serializable

  • jpaAnnotations: JPA annotations are used on generated records
  • validationAnnotations: JSR-303 validation annotations are used on generated records
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the pojos flag @@ -9483,16 +9483,16 @@ public class Book implements java.io.Serializable

    Every table in your database will generate an interface that looks like this:

    - + - +

    Flags influencing generated interfaces

    These flags from the influence generated interfaces: @@ -9501,7 +9501,7 @@ public class Book implements java.io.Serializable

  • dateAsTimestamp: This influences all relevant getters and setters
  • unsignedTypes: This influences all relevant getters and setters
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the interfaces flag @@ -9516,7 +9516,7 @@ public class Book implements java.io.Serializable

    Every table in your database will generate a implementation that looks like this:

    - + { // Generated constructors @@ -9540,10 +9540,10 @@ public class Book implements java.io.Serializable public List fetchByAuthorId(Integer... values) { return fetch(BOOK.AUTHOR_ID, values); } - + // [...] }]]> - +

    Flags controlling DAO generation

    DAO generation can be activated using the daos flag @@ -9557,13 +9557,13 @@ public class Book implements java.io.Serializable

    Every sequence in your database will generate a implementation that looks like this:

    - + S_AUTHOR_ID = new SequenceImpl("S_AUTHOR_ID", TEST, SQLDataType.INTEGER); }]]> - +

    Flags controlling sequence generation

    Sequence generation cannot be deactivated @@ -9601,7 +9601,7 @@ public class Book implements java.io.Serializable public BigDecimal getResult() { return getValue(RESULT); } - + // [...] }]]> @@ -9623,7 +9623,7 @@ public class Book implements java.io.Serializable

    Every UDT in your database will generate a implementation that looks like this:

    - + { // The singleton UDT instance @@ -9636,10 +9636,10 @@ public class Book implements java.io.Serializable createField("CITY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); public static final UDTField COUNTRY = createField("COUNTRY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); - + // [...] }]]> - +

    Besides the implementation, a implementation is also generated

    @@ -9654,7 +9654,7 @@ public class Book implements java.io.Serializable public String getCity() {...} public void setCountry(String value) {...} public String getCountry() {...} - + // [...] }]]> @@ -9738,23 +9738,23 @@ create.selectFrom(AUTHOR) ]]>
    - +
    Code generation for large schemas

    Databases can become very large in real-world applications. This is not a problem for jOOQ's code generator, but it can be for the Java compiler. jOOQ generates some classes for . These classes can hit two sorts of limits of the compiler / JVM:

    - +
    • Methods (including static / instance initialisers) are allowed to contain only 64kb of bytecode.
    • Classes are allowed to contain at most 64k of constant literals
    - +

    While there exist workarounds for the above two limitations (delegating initialisations to nested classes, inheriting constant literals from implemented interfaces), the preferred approach is either one of these:

    - +
    • Distribute your database objects in several schemas. That is probably a good idea anyway for such large databases
    • to exclude excess database objects
    • @@ -9837,11 +9837,11 @@ create.selectFrom(AUTHOR)

      When writing unit tests for your data access layer, you have probably used some generic mocking tool offered by popular providers like Mockito, jmock, mockrunner, or even DBUnit. With jOOQ, you can take advantage of the built-in JDBC mock API that allows you to emulate a simple database on the JDBC level for precisely those SQL/JDBC use cases supported by jOOQ.

      - +

      - Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider. + Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider.

      - +

      Mocking the JDBC API

      JDBC is a very complex API. It takes a lot of time to write a useful and correct mock implementation, implementing at least these interfaces: @@ -9854,16 +9854,16 @@ create.selectFrom(AUTHOR)

    - +

    Optionally, you may even want to implement interfaces, such as , , , and many others. In addition to the above, you might need to find a way to simultaneously support incompatible JDBC minor versions, such as 4.0, 4.1

    - +

    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 :

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    As you can see, the configuration setup is simple. Now, the MockDataProvider acts as your single point of contact with JDBC / jOOQ. It unifies any of these execution modes, transparently:

    - +
    • Statements without results
    • Statements without results but with generated keys
    • @@ -9886,16 +9886,16 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
    • Batch statements with single queries and multiple bind value sets
    • Batch statements with multiple queries and no bind values
    - +

    The above are the execution modes supported by jOOQ. Whether you're using any of jOOQ's various fetching modes (e.g. , , , ) is irrelevant, as those modes are all built on top of the standard JDBC API.

    - +

    Implementing MockDataProvider

    Now, here's how to implement MockDataProvider:

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc // 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 String sql = ctx.sql(); - + // Exceptions are propagated through the JDBC and jOOQ APIs if (sql.toUpperCase().startsWith("DROP")) { throw new SQLException("Statement not supported: " + sql); } - + // You decide, whether any given statement returns results, and how many else if (sql.toUpperCase().startsWith("SELECT")) { - + // Always return one author record Result result = create.newResult(AUTHOR); result.add(create.newRecord(AUTHOR)); @@ -9923,12 +9923,12 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc result.get(0).setValue(AUTHOR.LAST_NAME, "Orwell"); mock[0] = new MockResult(1, result); } - + // You can detect batch statements easily else if (ctx.batch()) { // [...] } - + return mock; } }]]> @@ -9940,17 +9940,17 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • : The number of affected rows
  • : The result set
  • - +

    You should return as many MockResult objects as there were query executions (in ) or results (in ). Instead of an awkward JDBC ResultSet, however, you can construct a "friendlier" with your own record types. The jOOQ mock API will use meta data provided with this Result in order to create the necessary JDBC

    - +

    See the for a list of rules that you should follow.

    - +
    jOOQ Console @@ -9996,7 +9996,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • Sybase Adaptive Server Enterprise 15.5
  • Sybase SQL Anywhere 12
  • - +

    For an up-to-date list of currently supported RDBMS, please refer to http://www.jooq.org/legal/licensing/#databases.

    @@ -10017,7 +10017,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc This chapter should document the most important notes about SQL, JDBC and jOOQ data types.

    - +
    BLOBs and CLOBs @@ -10027,7 +10027,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    - +
    Unsigned integer types @@ -10051,7 +10051,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
    - +
    INTERVAL data types @@ -10062,11 +10062,11 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • YEAR TO MONTH: This interval type models a number of months and years
  • DAY TO SECOND: This interval type models a number of days, hours, minutes, seconds and milliseconds
  • - +

    Both interval types ship with a variant of subtypes, such as DAY TO HOUR, HOUR TO SECOND, etc. jOOQ models these types as Java objects extending : (where Number.intValue() corresponds to the absolute number of months) and (where Number.intValue() corresponds to the absolute number of milliseconds)

    - +

    Interval arithmetic

    In addition to the documented previously, interval arithmetic is also supported by jOOQ. Essentially, the following operations are supported: @@ -10081,7 +10081,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    - +
    XML data types @@ -10090,7 +10090,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    - +
    Geospacial data types @@ -10100,7 +10100,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    - +
    CURSOR data types @@ -10109,22 +10109,22 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    > cursor;]]> - +

    In fact, such a cursor will be fetched immediately by jOOQ and wrapped in an object.

    - +
    ARRAY and TABLE data types

    The SQL standard specifies ARRAY data types, that can be mapped to Java arrays as such:

    - + intArray;]]> - +

    The above array type is supported by these SQL dialects:

    @@ -10133,7 +10133,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • HSQLDB
  • Postgres
  • - +

    Oracle typed arrays

    Oracle has strongly-typed arrays and table types (as opposed to the previously seen anonymously typed arrays). These arrays are wrapped by types. @@ -10151,7 +10151,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    - +
    Quality Assurance @@ -10163,16 +10163,16 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • To add lots of type-safety to your inline SQL
  • To increase productivity when writing inline SQL using your favourite IDE's autocompletion capabilities
  • - +

    With jOOQ being in the core of your application, you want to be sure that you can trust jOOQ. That is why jOOQ is heavily unit and integration tested with a strong focus on integration tests:

    - +

    Unit tests

    Unit tests are performed against dummy JDBC interfaces using http://jmock.org/. These tests verify that various implementations render correct SQL and bind variables correctly.

    - +

    Integration tests

    This is the most important part of the jOOQ test suites. Some 1500 queries are currently run against a standard integration test database. Both the test database and the queries are translated into every one of the 14 supported SQL dialects to ensure that regressions are unlikely to be introduced into the code base. @@ -10183,17 +10183,17 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    jOOQ integration tests run the weirdest and most unrealistic queries. As a side-effect of these extensive integration test suites, many corner-case bugs for JDBC drivers and/or open source databases have been discovered, feature requests submitted through jOOQ and reported mainly to CUBRID, Derby, H2, HSQLDB.

    - +

    Code generation tests

    For every one of the 14 supported integration test databases, source code is generated and the tiniest differences in generated source code can be discovered. In case of compilation errors in generated source code, new test tables/views/columns are added to avoid regressions in this field.

    - +

    API Usability tests and proofs of concept

    jOOQ is used in jOOQ-meta as a proof of concept. This includes complex queries such as the following Postgres query

    - + These rather complex queries show that the jOOQ API is fit for advanced SQL use-cases, compared to the rather simple, often unrealistic queries in the integration test suite.

    - +

    Clean API and implementation. Code is kept DRY

    As a general rule of thumb throughout the jOOQ code, everything is kept DRY. Some examples: @@ -10259,19 +10259,19 @@ for (Record record : create.select(

    - +
    Migrating to jOOQ 3.0

    This section is for all users of jOOQ 2.x who wish to upgrade to the next major release. In the next sub-sections, the most important changes are explained. Some code hints are also added to help you fix compilation errors.

    - +

    Type-safe row value expressions

    Support for has been added in jOOQ 2.6. In jOOQ 3.0, many API parts were thoroughly (but often incompatibly) changed, in order to provide you with even more type-safety.

    - +

    Here are some affected API parts:

    @@ -10281,11 +10281,11 @@ for (Record record : create.select(
  • IN predicates and comparison predicates taking subselects changed incompatibly
  • INSERT and MERGE statements now take typesafe VALUES() clauses
  • - +

    Some hints related to row value expressions:

    - + record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result> result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch(); @@ -10293,31 +10293,31 @@ Result> result = create.select(BOOK.TITLE, BOOK.ID).fro // But Record2 extends Record. You don't have to use the additional typesafety: Record record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch();]]> - +

    SelectQuery and SelectXXXStep are now generic

    In order to support type-safe row value expressions and type-safe Record[N] types, SelectQuery is now generic: SelectQuery<R>

    - +

    SimpleSelectQuery and SimpleSelectXXXStep API were removed

    The duplication of the SELECT API is no longer useful, now that SelectQuery and SelectXXXStep are generic.

    - +

    Factory was split into DSL (query building) and DSLContext (query execution)

    The pre-existing Factory class has been split into two parts:

    - +
    1. 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
    2. 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 renamed to DSLContext. An example:

    - + - +

    Quantified comparison predicates

    Field.equalAny(...) and similar methods have been removed in favour of Field.equal(any(...)). This greatly simplified the Field API. An example:

    - + > subselect = any(select(BOOK.ID).from(BOOK)); Condition condition = BOOK.ID.equal(subselect);]]> - +

    FieldProvider

    The FieldProvider marker interface was removed. Its methods still exist on FieldProvider subtypes. Note, they have changed names from getField() to field() and from getIndex() to indexOf()

    - +

    GroupField

    GroupField has been introduced as a DSL marker interface to denote fields that can be passed to GROUP BY clauses. This includes all org.jooq.Field types. However, fields obtained from ROLLUP(), CUBE(), and GROUPING SETS() functions no longer implement Field. Instead, they only implement GroupField. An example:

    - + field1a = Factory.rollup(...); // OK Field field2a = Factory.one(); // OK @@ -10363,19 +10363,19 @@ GroupField field1b = DSL.rollup(...); // OK Field field1c = DSL.rollup(...); // Compilation error GroupField field2b = DSL.one(); // OK Field field2c = DSL.one(); // OK]]> - +

    NULL predicate

    Beware! Previously, Field.equal(null) was translated internally to an IS NULL predicate. This is no longer the case. Binding Java "null" to a comparison predicate will result in a regular comparison predicate (which never returns true). This was changed for several reasons:

    - +
    • To most users, this was a surprising "feature".
    • Other predicates didn't behave in such a way, e.g. the IN predicate, the BETWEEN predicate, or the LIKE predicate.
    • Variable binding behaved unpredictably, as IS NULL predicates don't bind any variables.
    • The generated SQL depended on the possible combinations of bind values, which creates unnecessary hard-parses every time a new unique SQL statement is rendered.
    - +

    Here is an example how to check if a field has a given value, without applying SQL's ternary NULL logic:

    @@ -10388,7 +10388,7 @@ Condition condition1 = BOOK.TITLE.equal(possiblyNull); // jOOQ 3.0 Condition condition2 = BOOK.TITLE.equal(possiblyNull).or(BOOK.TITLE.isNull().and(val(possiblyNull).isNull())); Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    Configuration

    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 @@ -10402,7 +10402,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> In order to resolve confusion that used to arise because of different lifecycle durations, these types are now no longer formally connected through inheritance.

    - +

    ConnectionProvider

    In order to allow for simpler connection / data source management, jOOQ externalised connection handling in a new ConnectionProvider type. The previous two connection modes are maintained backwards-compatibly (JDBC standalone connection mode, pooled DataSource mode). Other connection modes can be injected using: @@ -10412,24 +10412,24 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    These are some side-effects of the above change

    - +
    • 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. This resolves many class loader issues that were encountered before. It also helps listener implementations control their lifecycles themselves.

    - +

    Data type API

    The data type API has been changed drastically in order to enable some new DataType-related features. These changes include: @@ -10439,16 +10439,16 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]>[SQLDialect]DataType and SQLDataType no longer implement DataType. They're mere constant containers

  • Various minor API changes have been done.
  • - +

    Object renames

    These objects have been moved / renamed:

    - +
    • jOOU: a library used to represent unsigned integer types was moved from org.jooq.util.unsigned to org.jooq.util.types (which already contained INTERVAL data types)
    - +

    Feature removals

    Here are some minor features that have been removed in jOOQ 3.0 @@ -10543,7 +10543,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> --> diff --git a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.1.xml b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.1.xml index 1bdcd3e77d..263c4dbe1d 100644 --- a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.1.xml +++ b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.1.xml @@ -86,7 +86,7 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ's reason for being - compared to SQL / JDBC

    So why not just use SQL? @@ -109,30 +109,30 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ is different

    SQL was never meant to be abstracted. To be confined in the narrow boundaries of heavy mappers, hiding the beauty and simplicity of relational data. SQL was never meant to be object-oriented. SQL was never meant to be anything other than... SQL!

    - + - +
    Getting started with jOOQ @@ -291,12 +291,12 @@ and Maintenance Agreement for more details: http://www.jooq.org/licensing

    This section helps you correctly interpret this manual in the context of jOOQ.

    - +

    Code blocks

    The following are code blocks:

    - + @@ -306,7 +306,7 @@ org.jooq.property=value]]>

    These are useful to provide examples in code. Often, with jOOQ, it is even more useful to compare SQL code with its corresponding Java/jOOQ code. When this is done, the blocks are aligned side-by-side, with SQL usually being on the left, and an equivalent jOOQ DSL query in Java usually being on the right:

    - +

    The contents of code blocks follow conventions, too. If nothing else is mentioned next to any given code block, then the following can be assumed:

    - - + +

    Your naming may differ, of course. For instance, you could name the "create" instance "db", instead.

    - +

    Execution

    - +

    When you're coding PL/SQL, T-SQL or some other procedural SQL language, SQL statements are always executed immediately at the semi-colon. This is not the case in jOOQ, because as an internal DSL, jOOQ can never be sure that your statement is complete until you call fetch() or execute(). The manual tries to apply fetch() and execute() as thoroughly as possible. If not, it is implied:

    @@ -365,7 +365,7 @@ create.update(T).set(T.V, 1).execute();]]>

    jOOQ allows to override runtime behaviour using . If nothing is specified, the default runtime settings are assumed.

    - +

    Sample database

    jOOQ query examples run against the sample database. See the manual's section about to learn more about the sample database. @@ -400,7 +400,7 @@ CREATE TABLE book ( title VARCHAR2(400) NOT NULL, published_in NUMBER(7) NOT NULL, language_id NUMBER(7) NOT NULL, - + CONSTRAINT fk_book_author FOREIGN KEY (author_id) REFERENCES author(id), CONSTRAINT fk_book_language FOREIGN KEY (language_id) REFERENCES language(id) ); @@ -413,7 +413,7 @@ CREATE TABLE book_to_book_store ( name VARCHAR2(400) NOT NULL, book_id INTEGER NOT NULL, stock INTEGER, - + PRIMARY KEY(name, book_id), CONSTRAINT fk_b2bs_book_store FOREIGN KEY (name) REFERENCES book_store (name) ON DELETE CASCADE, CONSTRAINT fk_b2bs_book FOREIGN KEY (book_id) REFERENCES book (id) ON DELETE CASCADE @@ -424,7 +424,7 @@ CREATE TABLE book_to_book_store (

    In addition to the above, you may assume the following sample data:

    - + Effectively, jOOQ was originally designed to replace any other database abstraction framework short of the ones handling connection pooling and transaction management (see also the )

    - +

    Use jOOQ the way you prefer

    ... but open source is community-driven. And the community has shown various ways of using jOOQ that diverge from its original intent. Some use cases encountered are: @@ -483,7 +483,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]>Using jOOQ for SQL building and Spring Data for SQL execution

  • Using jOOQ without the to build the basis of a framework for dynamic SQL execution.
  • - +

    The following sections explain about various use cases for using jOOQ in your application.

    @@ -496,7 +496,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]> This is the most simple of all use cases, allowing for construction of valid SQL for any database. In this use case, you will not use and probably not even . Instead, you'll use to wrap strings, literals and other user-defined objects into an object-oriented, type-safe AST modelling your SQL statements. An example is given here:

    - + - +

    The SQL string built with the jOOQ query DSL can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools (note that since jOOQ uses PreparedStatement by default, this will generate a bind variable for "1948". ).

    @@ -533,7 +533,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID)) .where(BOOK.PUBLISHED_IN.equal(1948)) .getSQL();]]> - +

    The SQL string that you can generate as such can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools.

    @@ -553,7 +553,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    Instead of any tool mentioned in the previous chapters, you can also use jOOQ directly to execute your jOOQ-generated SQL statements. This will add a lot of convenience on top of the previously discussed API for typesafe SQL construction, when you can re-use the information from generated classes to fetch records and custom data types. An example is given here:

    - + > result = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) @@ -607,10 +607,10 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { // Skip previously distinguished authors if ((int) author.getDistinguished() == 1) continue; - + // Check if the author has written more than 5 books if (author.fetchChildren(Keys.FK_BOOK_AUTHOR).size() > 5) { - + // Mark the author as a "distinguished" author author.setDistinguished(1); author.store(); @@ -627,7 +627,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {
    - +
    jOOQ for PROs @@ -666,7 +666,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { This manual section is intended for new users, to help them get a running application with jOOQ, quickly.

    - +
    Step 1: Preparation @@ -675,7 +675,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { If you haven't already downloaded it, download jOOQ:
    http://www.jooq.org/download

    - +

    Alternatively, you can create a Maven dependency to download jOOQ artefacts:

    @@ -709,14 +709,14 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    - +
    Step 2: Your database

    We're going to create a database called "guestbook" and a corresponding "posts" table. Connect to MySQL via your command line client and type the following:

    - + CREATE DATABASE guestbook; CREATE TABLE `posts` ( @@ -728,7 +728,7 @@ CREATE TABLE `posts` ( );
    - +
    Step 3: Code generation @@ -740,7 +740,7 @@ CREATE TABLE `posts` (

    The easiest way to generate a schema is to copy the jOOQ jar files (there should be 3) and the MySQL Connector jar file to a temporary directory. Then, create a guestbook.xml that looks like this:

    - + @@ -794,7 +794,7 @@ CREATE TABLE `posts` (

    generator.target.directory - the directory to output to.

    - +

    Once you have the JAR files and library.xml in your temp directory, type this on a Windows machine:

    @@ -814,12 +814,12 @@ CREATE TABLE `posts` (

    There are two things to note:

    - +
    1. The prefix slash before the /library.xml. Even though it's in our working directory, we need to prepend a slash, as the configuration file is loaded from the classpath.
    2. The "trailing" period in the classpath: .. We need this because we want the current directory on the classpath in order to find the above /library.xml file at the root of your classpath.
    - +

    Replace the filenames with your actual filenames. In this example, jOOQ {jooq-version} is being used. If everything has worked, you should see this in your console output:

    @@ -882,14 +882,14 @@ Nov 1, 2011 7:25:08 PM org.jooq.impl.JooqLogger info INFO: GENERATION FINISHED! : Total: 791.688ms, +9.143ms
    - +
    Step 4: Connect to your database

    Let's just write a vanilla main class in the project containing the generated classes:

    - +
    - +
    Step 5: Querying

    Let's add a simple query constructed with jOOQ's query DSL:

    - + result = create.select().from(POSTS).fetch();]]> @@ -945,7 +945,7 @@ Result result = create.select().from(POSTS).fetch();]]>

    - +
    Step 6: Iterating @@ -964,7 +964,7 @@ Result result = create.select().from(POSTS).fetch();]]>

    The full program should now look like this:

    - +
    - +
    Step 7: Explore! @@ -1060,15 +1060,15 @@ public class Main {
  • Spring TX as the transaction management library.
  • jOOQ as the and library.
  • - +

    The complete example can also be downloaded from GitHub. Another, excellent tutorial by Petri Kainulainen can be found here.

    - +

    The following steps show how to integrate the libraries.

    - +

    Add the required Maven dependencies

    For this example, we'll create the following Maven dependencies @@ -1147,7 +1147,7 @@ public class Main {

    The above dependencies are configured together using a Spring Beans configuration:

    - + - + - + @@ -1210,7 +1210,7 @@ public class Main { - + ]]> @@ -1261,7 +1261,7 @@ public class QueryTest {

    The following example shows how you can use Spring's TransactionManager to explicitly handle transactions:

    - +
    - +
    jOOQ and Scala @@ -1376,7 +1376,7 @@ public class TransactionTest {
  • Optioanl ";" at the end of a Scala statement
  • Type inference using "var" and "val" keywords
  • - +

    But jOOQ also leverages other useful Scala features, such as

    @@ -1384,15 +1384,15 @@ public class TransactionTest {
  • implicit defs for operator overloading
  • Scala Macros (soon to come)
  • - +

    All of the above heavily improve jOOQ's querying DSL API experience for Scala developers.

    - +

    A short example jOOQ application in Scala might look like this:

    - +
    - +
    jOOQ and NoSQL @@ -1457,7 +1457,7 @@ object Test { //

    - +
    Dependencies @@ -1475,7 +1475,7 @@ object Test { //
    - +
    Build your own @@ -1504,7 +1504,7 @@ object Test { //
    - +
    jOOQ and backwards-compatibility @@ -1516,7 +1516,7 @@ object Test { //
  • If a minor release includes backwards-compatible, API-relevant new features, [Y] is incremented by one and [Z] is reset to zero.
  • If a major release includes backwards-incompatible, API-relevant new features, [X] is incremented by one and [Y], [Z] are reset to zero.
  • - +

    jOOQ's understanding of backwards-compatibility

    Backwards-compatibility is important to jOOQ. You've chosen jOOQ as a strategic SQL engine and you don't want your SQL to break. That is why there is at most one major release per year, which changes only those parts of jOOQ's API and functionality, which were agreed upon on the user group. During the year, only minor releases are shipped, adding new features in a backwards-compatible way @@ -1529,11 +1529,11 @@ object Test { //

  • Overloading methods for convenience
  • Changing the type hierarchy of interfaces
  • - +

    It becomes obvious that it would be impossible to add new language elements (e.g. new , new ) to the API without breaking any client code that actually implements those interfaces. Hence, the following rule should be observed:

    - +

    jOOQ's DSL interfaces should not be implemented by client code! Extend only those extension points that are explicitly documented as "extendable" (e.g. )

    @@ -1558,7 +1558,7 @@ object Test { // - +
    The query DSL type @@ -1588,7 +1588,7 @@ object Test { // // ... which is in fact the same as: DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    DSL subclasses @@ -1607,7 +1607,7 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME));
    - + @@ -1616,14 +1616,14 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    The DSLContext class

    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.

    - +

    Fluent creation of a DSLContext object

    The DSLContext object can be created fluently from the : @@ -1638,7 +1638,7 @@ DSLContext create = DSL.using(connection, dialect);]]>

    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

    A Configuration can be supplied with these objects: @@ -1657,7 +1657,7 @@ DSLContext create = DSL.using(connection, dialect);]]> - +

    Wrapping a Configuration object, a DSLContext can construct , for later . An example is given here:

    @@ -1698,7 +1698,7 @@ DSL.using(connection, dialect) CONNECT BY clause to the query */ -@Support({ SQLDialect.CUBRID, SQLDialect.}) +@Support({ SQLDialect.CUBRID, SQLDialect.ORACLE }) SelectConnectByConditionStep connectBy(Condition condition);]]>

    @@ -1720,7 +1720,7 @@ SelectSelectStep select(Field... fields);]]>

    Nevertheless, the IS DISTINCT FROM predicate is supported by jOOQ in all dialects, as its semantics can be expressed with an equivalent . For more details, see the manual's section about the .

    - +

    jOOQ and the Oracle SQL dialect

    Oracle SQL is much more expressive than many other SQL dialects. It features many unique keywords, clauses and functions that are out of scope for the SQL standard. Some examples for this are @@ -1744,13 +1744,13 @@ SelectSelectStep select(Field... fields);]]>

    In jOOQ 3.1, the notion of a SQLDialect.family() was introduced, in order to group several similar into a common family. An example for this is SQL Server, which is supported by jOOQ in various versions:

    - +
    • : The "version-less" SQL Server version. This always maps to the latest supported version of SQL Server
    • : The SQL Server version 2012
    • : The SQL Server version 2008
    - +

    In the above list, SQLSERVER is both a dialect and a family of three dialects. This distinction is used internally by jOOQ to distinguish whether to use the clause (SQL Server 2012), or whether to emulate it using ROW_NUMBER() OVER() (SQL Server 2008).

    @@ -1767,7 +1767,7 @@ SelectSelectStep select(Field... fields);]]>

    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.

    - +

    Interact with JDBC DataSources

    If you're in a J2EE or Spring context, however, you may wish to use a instead. Connections obtained from such a DataSource will be closed after query execution by jOOQ. The semantics of such a close operation should be the returning of the connection into a connection pool, not the actual closing of the underlying connection. Typically, this makes sense in an environment using distributed JTA transactions. An example of using DataSources with jOOQ can be seen in the tutorial section about . @@ -1775,17 +1775,17 @@ SelectSelectStep select(Field... fields);]]>

    Note, in this case, jOOQ will internally use a , which you can reference directly if you prefer that.

    - +

    Inject custom behaviour

    If your specific environment works differently from any of the above approaches, you can inject your own custom implementation of a ConnectionProvider into jOOQ. This is the API contract you have to fulfil:

    - + @@ -1795,19 +1795,19 @@ 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...

    - +
    - +

    Here is an example of how to use the custom data API. Let's assume that you have written an , that prevents INSERT statements, when a given flag is set to true:

    @@ -1817,10 +1817,10 @@ public class NoInsertListener extends DefaultExecuteListener { @Override public void start(ExecuteContext ctx) { - + // This listener is active only, when your custom flag is set to true 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) { throw new DataAccessException("No INSERT statements allowed"); @@ -1831,11 +1831,11 @@ public class NoInsertListener extends DefaultExecuteListener {

    See the manual's section about to learn more about how to implement an ExecuteListener.

    - +

    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:

    - + ExecuteListeners are a useful tool to...

    - +
    • implement custom logging
    • apply triggers written in Java
    • collect query execution statistics
    • integrate with the
    - +

    ExecuteListeners are hooked into your by returning them from an :

    @@ -1894,7 +1894,7 @@ configuration.set( new DefaultExecuteListenerProvider(new PerformanceLoggingListener()), new DefaultExecuteListenerProvider(new NoInsertListener()) );]]>
    - +

    See the manual's section about to see examples of such listener implementations.

    @@ -1941,7 +1941,7 @@ DSLContext create = DSL.using(connection, dialect, settings);]]>

    - +
    Runtime schema and table mapping @@ -1949,7 +1949,7 @@ DSLContext create = DSL.using(connection, dialect, settings);]]>

    You may wish to design your database in a way that you have several instances of your schema. This is useful when you want to cleanly separate data belonging to several customers / organisation units / branches / users and put each of those entities' data in a separate database or schema.

    - +

    In our AUTHOR example this would mean that you provide a book reference database to several companies, such as My Book World and Books R Us. In that case, you'll probably have a schema setup like this:

    @@ -1979,7 +1979,7 @@ create.selectFrom(AUTHOR).fetch();

    The query executed with a Configuration equipped with the above mapping will in fact produce this SQL statement:

    - + SELECT * FROM MY_BOOK_WORLD.AUTHOR

    Even if AUTHOR was generated from DEV. @@ -2054,7 +2054,7 @@ create.selectFrom(AUTHOR).fetch();

    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

    @@ -2088,7 +2088,7 @@ create.selectFrom(AUTHOR).fetch();

    Here is an example to illustrate what that means:

    - + 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) @@ -2159,7 +2159,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); @@ -2186,7 +2186,7 @@ query.addJoin(BOOK, BOOK.AUTHOR_ID.equal(AUTHOR.ID));]]>

    Note, that for historic reasons, the DSL API mixes mutable and immutable behaviour with respect to the internal representation of the being constructed. While creating , (such as functions) assumes immutable behaviour, creating does not. In other words, the following can be said:

    - + select2 = create.selectOne();]]>

    jOOQ does not explicitly support the asterisk operator in projections. However, you can omit the projection as in these examples:

    - +

    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:

    - + select(Collection> fields); public static SelectSelectStep select(Field... fields); @@ -2362,14 +2362,14 @@ public static SelectSelectStep> select(Field SelectSelectStep> select(Field field1, Field field2); public static SelectSelectStep> select(Field field1, Field field2, Field field3); // [...]]]> - +

    Since the generic R type is bound to some , the associated T type information can be used in various other contexts, e.g. the . Such a SELECT statement can be assigned typesafely:

    > s1 = create.select(BOOK.ID, BOOK.TITLE); Select> s2 = create.select(BOOK.ID, trim(BOOK.TITLE));]]> - +

    For more information about typesafe record types with degree up to {max-row-degree}, see the manual's section about .

    @@ -2394,7 +2394,7 @@ create.selectOne().from(BOOK.as("b"), AUTHOR.as("a"));]]>

    Read more about aliasing in the manual's section about .

    - +

    More advanced table expressions

    Apart from simple tables, you can pass any arbitrary to the jOOQ FROM clause. This may include in Oracle: @@ -2663,12 +2663,12 @@ ORDER BY 1]]> Note that this syntax is also supported in the CUBRID database and might be emulated in other dialects supporting common table expressions in the future.

    - +

    ORDER SIBLINGS

    The Oracle database allows for specifying a SIBLINGS keyword in the . Instead of ordering the overall result, this will only order siblings among each other, keeping the hierarchy intact. An example is given here:

    - + - +
    @@ -2706,7 +2706,7 @@ GROUP BY AUTHOR_ID]]> Note, as defined in the SQL standard, when grouping, you may no longer project any columns that are not a formal part of the GROUP BY clause, or .

    - +

    MySQL's deviation from the SQL standard

    MySQL has a peculiar way of not adhering to this standard behaviour. This is documented in the MySQL manual. In short, with MySQL, you can also project any other field that is not part of the GROUP BY clause. The projected values will just be arbitrary values from within the group. You cannot rely on any ordering. For example: @@ -2735,7 +2735,7 @@ GROUP BY ()]]> - +

    ROLLUP(), CUBE() and GROUPING SETS()

    Some databases support the SQL standard grouping functions and some extensions thereof. See the manual's section about for more details. @@ -2754,7 +2754,7 @@ GROUP BY ()]]>= 2]]>= 2]]> @@ -2889,8 +2889,8 @@ ORDER BY CASE TITLE

    The SQL standard defines that a "query expression" can be ordered, and that query expressions can contain , whose subqueries cannot be ordered. While this is defined as such in the SQL standard, many databases allowing for the non-standard in one way or another, do not adhere to this part of the SQL standard. Hence, jOOQ allows for ordering all SELECT statements, regardless whether they are constructed as a part of a UNION or not. Corner-cases are handled internally by jOOQ, by introducing synthetic subselects to adhere to the correct syntax, where this is needed.

    - - + +

    Oracle's ORDER SIBLINGS BY clause

    jOOQ also supports Oracle's SIBLINGS keyword to be used with ORDER BY clauses for @@ -2939,7 +2939,7 @@ SELECT TOP 1 * FROM BOOK

    Things get a little more tricky in those databases that have no native idiom for OFFSET pagination (actual queries may vary):

    - + 1]]>

    As you can see, jOOQ will take care of the incredibly painful ROW_NUMBER() OVER() (or ROWNUM for Oracle) filtering in subselects for you, you'll just have to write limit(1).offset(2) in any dialect.

    - +

    Side-note: If you're interested in understanding why we chose ROWNUM for Oracle, please refer to this very interesting benchmark, comparing the different approaches of doing pagination in Oracle: http://www.inf.unideb.hu/~gabora/pagination/results.html.

    @@ -3085,7 +3085,7 @@ SELECT * FROM author ORDER BY id DESC;]]>

    SQL allows to perform set operations as understood in standard set theory on result sets. These operations include unions, intersections, subtractions. For two subselects to be combinable by such a set operator, each subselect must return a of the same degree and type.

    - +

    UNION and UNION ALL

    These operators combine two results into one. While UNION removes all duplicate records resulting from this combination, UNION ALL leaves subselect results as they are. Typically, you should prefer UNION ALL over UNION, if you don't really need to remove duplicates. The following example shows how to use such a UNION operation in jOOQ. @@ -3097,12 +3097,12 @@ UNION ALL SELECT * FROM BOOK WHERE ID = 5]]> - +

    INTERSECT [ ALL ] and EXCEPT [ ALL ]

    INTERSECT is the operation that produces only those values that are returned by both subselects. EXCEPT is the operation that returns only those values that are returned exclusively in the first subselect. Both operators will remove duplicates from their results. The SQL standard allows to specify the ALL keyword for both of these operators as well, but this is hardly supported in any database. jOOQ does not support INTERSECT ALL, EXEPT ALL operations either.

    - +

    jOOQ's set operators and how they're different from standard SQL

    As previously mentioned in the manual's section about the , jOOQ has slightly changed the semantics of these set operators. While in SQL, a subselect may not contain any or (unless you wrap the subselect into a ), jOOQ allows you to do so. In order to select both the youngest and the oldest author from the database, you can issue the following statement with jOOQ (rendered to the MySQL dialect): @@ -3118,12 +3118,12 @@ UNION .union( create.selectFrom(AUTHOR) .orderBy(AUTHOR.DATE_OF_BIRTH.desc()).limit(1));]]> - +

    Projection typesafety for degrees between 1 and {max-row-degree}

    Two subselects that are combined by a set operator are required to be of the same degree and, in most databases, also of the same type. jOOQ 3.0's introduction of helps compile-checking these constraints:

    - + > s1 = select(BOOK.ID, BOOK.TITLE).from(BOOK); Select> s2 = selectOne(); @@ -3157,7 +3157,7 @@ s1.union(s4); // OK. The two Record[N] types match]]>

    Note that you can pass any string in the .hint() clause. If you use that clause, the passed string will always be put in between the SELECT [DISTINCT] keywords and the actual projection list. This can be useful in other databases too, such as MySQL, for instance:

    - +
    - +
    Lexical and logical SELECT clause order

    SQL has a lexical and a logical order of SELECT clauses. The lexical order of SELECT clauses is inspired by the English language. As SQL statements are commands for the database, it is natural to express a statement in an imperative tense, such as "SELECT this and that!".

    - +

    Logical SELECT clause order

    The logical order of SELECT clauses, however, does not correspond to the syntax. In fact, the logical order is this:

    - +
    • : First, all data sources are defined and joined
    • : Then, data is filtered as early as possible
    • @@ -3192,11 +3192,11 @@ FROM table1
    • : Then, a paging view is created for the ordered tuples
    • : Finally, pessimistic locking is applied
    - +

    The SQL Server documentation also explains this, with slightly different clauses:

    - +
    • FROM
    • ON
    • @@ -3210,16 +3210,16 @@ FROM table1
    • ORDER BY
    • TOP
    - +

    As can be seen, databases have to logically reorder a SQL statement in order to determine the best execution plan.

    - +

    Alternative syntaxes: LINQ, SLICK

    Some "higher-level" abstractions, such as C#'s LINQ or Scala's SLICK try to inverse the lexical order of SELECT clauses to what appears to be closer to the logical order. The obvious advantage of moving the SELECT clause to the end is the fact that the projection type, which is the record type returned by the SELECT statement can be re-used more easily in the target environment of the internal domain specific language.

    - +

    A LINQ example:

    @@ -3232,11 +3232,11 @@ Where p.UnitsInStock <= p.ReorderLevel AndAlso Not p.Discontinued // SELECT clause Select p]]> - +

    A SLICK example:

    - + create.insertInto(AUTHOR, .set(AUTHOR.ID, 101) .set(AUTHOR.FIRST_NAME, "Alfred") .set(AUTHOR.LAST_NAME, "Döblin"); - +

    As you can see, this syntax is a bit more verbose, but also more readable, as every field can be matched with its value. Internally, the two syntaxes are strictly equivalent.

    @@ -3332,7 +3332,7 @@ SELECT 101, 'Alfred', 'Döblin' FROM DUAL;create.insertInto(AUTHOR,

    The MySQL database supports a very convenient way to INSERT or UPDATE a record. This is a non-standard extension to the SQL syntax, which is supported by jOOQ and emulated in other RDBMS, where this is possible (i.e. if they support the SQL standard ). Here is an example how to use the ON DUPLICATE KEY UPDATE clause:

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, update the author's name create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -3341,11 +3341,11 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .set(AUTHOR.LAST_NAME, "Koontz");

    The synthetic ON DUPLICATE KEY IGNORE clause

    - +

    The MySQL database also supports an INSERT IGNORE INTO clause. This is supported by jOOQ using the more convenient SQL syntax variant of ON DUPLICATE KEY IGNORE, which can be equally emulated in other databases using a :

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, ignore the INSERT statement create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -3381,11 +3381,11 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    The INSERT SELECT statement

    - +

    In some occasions, you may prefer the INSERT SELECT syntax, for instance, when you copy records from one table to another:

    - + create.insertInto(AUTHOR_ARCHIVE) .select(create.selectFrom(AUTHOR).where(AUTHOR.DECEASED.isTrue()));
    @@ -3432,7 +3432,7 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    jOOQ supports formal in various contexts, among which the UPDATE statement. Only one row value expression can be updated at a time. Here's an example:

    - + UPDATE AUTHOR SET (FIRST_NAME, LAST_NAME) = @@ -3466,12 +3466,12 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    The above row value expressions usages are completely typesafe.

    - +

    UPDATE .. RETURNING

    The Firebird and Postgres databases support a RETURNING clause on their UPDATE statements, similar as the RETURNING clause in . This is useful to fetch trigger-generated values in one go. An example is given here:

    - + create.

    The H2 database ships with a somewhat less powerful but a little more intuitive syntax for its own version of the MERGE statement. An example more or less equivalent to the previous one can be seen here:

    - + -- Check if there is already an author called 'Hitchcock' -- If there is, rename him to John. If there isn't add him. @@ -3556,7 +3556,7 @@ VALUES ('John', 'Hitchcock')create.mergeInto(AUTHOR, This syntax can be fully emulated by jOOQ for all other databases that support the SQL standard MERGE statement. For more information about the H2 MERGE syntax, see the documentation here:
    http://www.h2database.com/html/grammar.html#merge

    - +

    Typesafety of VALUES() for degrees up to {max-row-degree}

    Much like the , the MERGE statement's VALUES() clause provides typesafety for degrees up to {max-row-degree}, in both the standard syntax variant as well as the H2 variant. @@ -3577,7 +3577,7 @@ VALUES ('John', 'Hitchcock')create.mergeInto(AUTHOR, TRUNCATE TABLE AUTHOR;create.truncate(AUTHOR).execute(); - +

    TRUNCATE is not supported by Ingres and SQLite. jOOQ will execute a DELETE FROM AUTHOR statement instead.

    @@ -3601,7 +3601,7 @@ VALUES ('John', 'Hitchcock')
    create.mergeInto(AUTHOR,

    Most of the times, when thinking about a you're probably thinking about an actual table in your database schema. If you're using jOOQ's , you will have all tables from your database schema available to you as type safe Java objects. You can then use these tables in SQL , or in other , just like any other table expression. An example is given here:

    - + - +

    The above example shows how AUTHOR and BOOK tables are joined in a . It also shows how you can access by dereferencing the relevant Java attributes of their tables.

    @@ -3648,11 +3648,11 @@ create.select() .where(a.YEAR_OF_BIRTH.greaterThan(1920) .and(a.FIRST_NAME.equal("Paulo"))) .orderBy(b.TITLE);]]>
    - +

    As you can see in the above example, calling as() on generated tables returns an object of the same type as the table. This means that the resulting object can be used to dereference fields from the aliased table. This is quite powerful in terms of having your Java compiler check the syntax of your SQL statements. If you remove a column from a table, dereferencing that column from that table alias will cause compilation errors.

    - +

    Dereferencing columns from other table expressions

    Only few table expressions provide the SQL syntax typesafety as shown above, where generated tables are used. Most tables, however, expose their fields through field() methods: @@ -3664,12 +3664,12 @@ Table a = AUTHOR.as("a"); // Get fields from a: Field id = a.field("ID"); Field firstName = a.field("FIRST_NAME");]]> - +

    Derived column lists

    The SQL standard specifies how a table can be renamed / aliased in one go along with its columns. It references the term "derived column list" for the following syntax (as supported by Postgres, for instance):

    - + In jOOQ, you would simply specify a varargs list of column aliases as such:

    - + The that can be used in are the most powerful and best supported means of creating new in SQL. Informally, the following can be said:

    - + A(colA1, ..., colAn) "join" B(colB1, ..., colBm) "produces" C(colA1, ..., colAn, colB1, ..., colBm)

    @@ -3742,7 +3742,7 @@ create.select().from(values(

    jOOQ supports all of these JOIN types (except semi-join and anti-join) directly on any :

    - + table) @@ -3780,7 +3780,7 @@ Table naturalRightOuterJoin(TableLike)]]>

    Some databases allow for expressing in-memory temporary tables using a VALUES() constructor. This constructor usually works the same way as the VALUES() clause known from the or from the . With jOOQ, you can also use the VALUES() table constructor, to create tables that can be used in a :

    - + Note, that it is usually quite useful to provide column aliases ("derived column lists") along with the table alias for the VALUES() constructor.

    - +

    The above statement is emulated by jOOQ for those databases that do not support the VALUES() constructor, natively (actual emulations may vary):

    - + A can appear almost anywhere a can. Such a "nested SELECT" is often called a "derived table". Apart from many convenience methods accepting objects directly, a SELECT statement can always be transformed into a object using the asTable() method.

    - +

    Example: Scalar subquery

    - + SELECT * FROM BOOK @@ -3893,11 +3893,11 @@ create.select(AUTHOR.ID, books)

    If you are closely coupling your application to an Oracle database, you can take advantage of some Oracle-specific features, such as the PIVOT clause, used for statistical analyses. The formal syntax definition is as follows:

    - + -- SELECT .. FROM table PIVOT (aggregateFunction [, aggregateFunction] FOR column IN (expression [, expression])) -- WHERE .. - +

    The PIVOT clause is available from the type, as pivoting is done directly on a table. Currently, only Oracle's PIVOT clause is supported. Support for SQL Server's slightly different PIVOT clause will be added later. Also, jOOQ may emulate PIVOT for other dialects in the future.

    @@ -3960,7 +3960,7 @@ WHERE NOT EXISTS (

    The SQL standard specifies how SQL databases should implement ARRAY and TABLE types, as well as CURSOR types. Put simply, a CURSOR is a pointer to any materialised . Depending on the cursor's features, this table expression can be scrolled through in both directions, records can be locked, updated, removed, inserted, etc. Often, CURSOR types contain s, whereas ARRAY and TABLE types contain simple scalar values, although that is not a requirement

    - +

    ARRAY types in SQL are similar to Java's array types. They contain a "component type" or "element type" and a "dimension". This sort of ARRAY type is implemented in H2, HSQLDB and Postgres and supported by jOOQ as such. Oracle uses strongly-typed arrays, which means that an ARRAY type (VARRAY or TABLE type) has a name and possibly a maximum capacity associated with it.

    @@ -4041,12 +4041,12 @@ DSL.using(SQLDialect.SYBASE ).selectOne().getSQL();]]>

    Column expressions can be used in various SQL clauses in order to refer to one or several columns. This chapter explains how to form various types of column expressions with jOOQ. A particular type of column expression is given in the section about , where an expression may have a degree of more than one.

    - +

    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:

    - + field1 = BOOK.TITLE; @@ -4099,7 +4099,7 @@ ORDER BY BOOK.TITLE]]>
    Just like , columns can be renamed using aliases. Here is an example:

    - + SELECT FIRST_NAME || ' ' || LAST_NAME author, COUNT(*) books FROM AUTHOR JOIN BOOK ON AUTHOR.ID = AUTHOR_ID @@ -4108,18 +4108,18 @@ GROUP BY FIRST_NAME, LAST_NAME;

    Here is how it's done with jOOQ:

    - + Record record = create.select( concat(AUTHOR.FIRST_NAME, val(" "), AUTHOR.LAST_NAME).as("author"), count().as("books")) .from(AUTHOR) .join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID)) .groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME).fetchAny(); - +

    When you alias Fields like above, you can access those Fields' values using the alias name:

    - + System.out.println("Author : " + record.getValue("author")); System.out.println("Books : " + record.getValue("books"));
    @@ -4133,7 +4133,7 @@ System.out.println("Books : " + record.getValue("books"));

    Sometimes, this automatic mapping might not be what you needed, or jOOQ cannot know the type of a field. In those cases you would write SQL type CAST like this:

    - + -- Let's say, your Postgres column LAST_NAME was VARCHAR(30) -- Then you could do this: SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL @@ -4141,27 +4141,27 @@ SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL

    in jOOQ, you can write something like that:

    - + create.select(TAuthor.LAST_NAME.cast(PostgresDataType.TEXT));

    The same thing can be achieved by casting a Field directly to String.class, as TEXT is the default data type in Postgres to map to Java's String

    - + create.select(TAuthor.LAST_NAME.cast(String.class)); - +

    The complete CAST API in consists of these three methods:

    - + { // Cast this field to the type of another field Field cast(Field field); - + // Cast this field to a given DataType Field cast(DataType type); - + // Cast this field to the default DataType for a given Class Field cast(Class type); } @@ -4183,14 +4183,14 @@ public class DSL {

    A slightly different use case than are data type coercions, which are not rendered through to generated SQL. Sometimes, you may want to pretend that a numeric value is really treated as a string value, for instance when binding a numeric :

    - + field1 = val(1).coerce(String.class); Field field2 = val("1").coerce(Integer.class);]]>

    In the above example, field1 will be treated by jOOQ as a Field<String>, binding the numeric literal 1 as a VARCHAR value. The same applies to field2, whose string literal "1" will be bound as an INTEGER value.

    - +

    This technique is better than performing unsafe or rawtype casting in Java, if you cannot access the "right" field type from any given expression.

    @@ -4210,13 +4210,13 @@ Field field2 = val("1").coerce(Integer.class);]]>

    In order to express a SQL query like this one:

    - + SELECT ((1 + 2) * (5 - 3) / 2) % 10 FROM DUAL - +

    You can write something like this in jOOQ:

    - + create.select(val(1).add(2).mul(val(5).sub(3)).div(2).mod(10);

    Datetime arithmetic expressions

    @@ -4237,14 +4237,14 @@ Field field2 = val("1").coerce(Integer.class);]]>
    - +
    String concatenation

    The SQL standard defines the concatenation operator to be an infix operator, similar to the ones we've seen in the chapter about . This operator looks like this: ||. Some other dialects do not support this operator, but expect a concat() function, instead. jOOQ renders the right operator / function, depending on your :

    - + SELECT 'A' || 'B' || 'C' FROM DUAL -- Or in MySQL: @@ -4271,13 +4271,13 @@ create.select(concat("A", "B", "C"));
  • NVL: Get the first non-null value among two arguments.
  • NVL2: Get the second argument if the first is null, or the third argument, otherwise.
  • - +

    Please refer to the for more details.

    - +
    Numeric functions @@ -4287,7 +4287,7 @@ create.select(concat("A", "B", "C"));

    This is a list of numeric functions supported by jOOQ's :

    - + - +

    Please refer to the for more details.

    @@ -4343,13 +4343,13 @@ create.select(concat("A", "B", "C"));
  • SHL: Shift bits to the left
  • SHR: Shift bits to the right
  • - +

    Some background about bitwise operation emulation

    As stated before, not all databases support all of these bitwise operations. jOOQ emulates them wherever this is possible. More details can be seen in this blog post:
    http://blog.jooq.org/2011/10/30/the-comprehensive-sql-bitwise-operations-compatibility-list/

    - +
    @@ -4362,7 +4362,7 @@ create.select(concat("A", "B", "C"));

    This is a list of numeric functions supported by jOOQ's :

    - + - +

    Please refer to the for more details.

    - +

    Regular expressions, REGEXP, REGEXP_LIKE, etc.

    Various databases have some means of searching through columns using regular expressions if the does not provide sufficient pattern matching power. While there are many different functions and operators in the various databases, jOOQ settled for the SQL:2008 standard REGEX_LIKE operator. Being an operator (and not a function), you should use the corresponding method on :

    - +

    @@ -4408,7 +4408,7 @@ create.select(concat("A", "B", "C"));

    This is a list of date and time functions supported by jOOQ's :

    - + - +

    Intervals in jOOQ

    jOOQ fills a gap opened by JDBC, which neglects an important SQL data type as defined by the SQL standards: INTERVAL types. See the manual's section about for more details. @@ -4563,7 +4563,7 @@ GROUP BY AUTHOR_IDcreate.select(listAgg(BOOK.TITLE, ", ") WindowOverStep rank(); WindowOverStep denseRank(); WindowOverStep percentRank(); - + // Windowing functions WindowIgnoreNullsStep firstValue(Field field); WindowIgnoreNullsStep lastValue(Field field) @@ -4579,7 +4579,7 @@ GROUP BY AUTHOR_IDcreate.select(listAgg(BOOK.TITLE, ", ") // Statistical functions WindowOverStep cumeDist(); WindowOverStep ntile(int number);]]> - +

    SQL distinguishes between various window function types (e.g. "ranking functions"). Depending on the function, SQL expects mandatory PARTITION BY or ORDER BY clauses within the OVER() clause. jOOQ does not enforce those rules for two reasons:

    @@ -4594,14 +4594,14 @@ GROUP BY AUTHOR_IDcreate.select(listAgg(BOOK.TITLE, ", ")

    Here are some simple examples of window functions with jOOQ:

    - + -- Sample uses of ROW_NUMBER() ROW_NUMBER() OVER() ROW_NUMBER() OVER(PARTITION BY 1) ROW_NUMBER() OVER(ORDER BY BOOK.ID) ROW_NUMBER() OVER(PARTITION BY BOOK.AUTHOR_ID ORDER BY BOOK.ID) - + -- Sample uses of FIRST_VALUE FIRST_VALUE(BOOK.ID) OVER() FIRST_VALUE(BOOK.ID IGNORE NULLS) OVER() @@ -4611,14 +4611,14 @@ rowNumber().over() rowNumber().over().partitionByOne() rowNumber().over().partitionBy(BOOK.AUTHOR_ID) rowNumber().over().partitionBy(BOOK.AUTHOR_ID).orderBy(BOOK.ID) - + // Sample uses of firstValue() firstValue(BOOK.ID).over() firstValue(BOOK.ID).ignoreNulls().over() firstValue(BOOK.ID).respectNulls().over()
    - +

    An advanced window function example

    Window functions can be used for things like calculating a "running total". The following example fetches transactions and the running total for every transaction going back to the beginning of the transaction table (ordered by booked_at). Window functions are accessible from the previously seen type using the over() method: @@ -4643,7 +4643,7 @@ firstValue(BOOK.ID).respectNulls().over()

    In the previous chapter about , we have seen the concept of "ordered-set aggregate functions", such as Oracle's LISTAGG(). These functions have a window function / analytical function variant, as well. For example:

    - + SELECT LISTAGG(TITLE, ', ') WITHIN GROUP (ORDER BY TITLE) @@ -4723,7 +4723,7 @@ ORDER BY 1 NULLS LAST, 2 NULLS LAST

    In English, the ROLLUP() grouping function provides N+1 groupings, when N is the number of arguments to the ROLLUP() function. Each grouping has an additional group field from the ROLLUP() argument field list. The results of the second query might look something like this:

    - + GROUPING SETS() and other grouping functions:
    http://msdn.microsoft.com/en-us/library/bb510427(v=sql.105)

    - +

    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:

    - + ... fields); GroupField cube(Field... fields); @@ -4825,7 +4825,7 @@ Field groupingId(Field...);]]>

    MySQL and CUBRID don't know any grouping functions, but they support a WITH ROLLUP clause, that is equivalent to simple ROLLUP() grouping functions. jOOQ emulates ROLLUP() in MySQL and CUBRID, by rendering this WITH ROLLUP clause. The following two statements mean the same:

    - + Some databases support user-defined functions, which can be embedded in any SQL statement, if you're using jOOQ's . Let's say you have the following simple function in Oracle SQL:

    - + The above function will be made available from a generated class. You can use it like any other :

    - + - +

    Note that user-defined functions returning or data types can also be used wherever can be used, if they are

    @@ -4875,7 +4875,7 @@ END echo;

    Some databases support user-defined aggregate functions, which can then be used along with or as . An example for such a database is Oracle. With Oracle, you can define the following OBJECT type (the example was taken from the Oracle 11g documentation):

    - +

    jOOQ's will detect such aggregate functions and generate them differently from regular . They implement the type, as mentioned in the manual's section about . Here's how you can use the SECOND_MAX() aggregate function with jOOQ:

    - + - +
    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:

    - + Row1 row(T1 t1) { ... } public static Row2 row(T1 t1, T2 t2) { ... } @@ -5099,12 +5099,12 @@ public static RowN row(Object... values) { ... }]]>

    See the relevant sections for more details about how to use row value expressions in predicates.

    - +

    Using row value expressions in UPDATE statements

    The also supports a variant where row value expressions are updated, rather than single columns. See the relevant section for more details

    - +

    Higher-degree row value expressions

    jOOQ chose to explicitly support degrees up to {max-row-degree} to match Scala's typesafe tuple, function and product support. Unlike Scala, however, jOOQ also supports higher degrees without the additional typesafety. @@ -5128,7 +5128,7 @@ public static RowN row(Object... values) { ... }]]>

  • The of a
  • The 's ON clause
  • - +

    Boolean types in SQL

    Before SQL:1999, boolean types did not really exist in SQL. They were modelled by 0 and 1 numeric/char values. With SQL:1999, true booleans were introduced and are now supported by most databases. In short, these are possible boolean values: @@ -5222,7 +5222,7 @@ Condition combined2 = combined1.andNot(c); // The left-hand side of the AND NOT

    Here are all boolean operators on the interface:

    - + < to test for being strictly less
  • <= to test for being less or equal
  • - +

    Unfortunately, Java does not support operator overloading, hence these operators are also implemented as methods in jOOQ, like any other SQL syntax elements. The relevant parts of the interface are these:

    - + ); // = (some column expression) eq or equal(Select>); // = (some scalar SELECT statement) @@ -5283,12 +5283,12 @@ ge or greaterOrEqual(Select>); // >= (some scalar SELECT st

    Note that every operator is represented by two methods. A verbose one (such as equal()) and a two-character one (such as eq()). Both methods are the same. You may choose either one, depending on your taste. The manual will always use the more verbose one.

    - +

    jOOQ's convenience methods using comparison operators

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using comparison predicates:

    - +

    All variants of the that we've seen in the previous chapter also work for . If your database does not support row value expression comparison predicates, jOOQ emulates them the way they are defined in the SQL standard:

    - + (X, Y))]]>

    jOOQ supports all of the above row value expression comparison predicates, both with and at the right-hand side:

    - +
    - +
    Quantified comparison predicate @@ -5399,7 +5399,7 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    It is interesting to note that the SQL standard defines the in terms of the ANY-quantified predicate. The following two expressions are equivalent:

    - + @@ -5409,14 +5409,14 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    - +
    NULL predicate

    In SQL, you cannot compare NULL with any value using , as the result would yield NULL again, which is neither TRUE nor FALSE (see also the manual's section about ). In order to test a for NULL, use the NULL predicate as such:

    - + The SQL standard contains a nice truth table for the above rules:

    - + +-----------------------+-----------+---------------+---------------+-------------------+ | Expression | R IS NULL | R IS NOT NULL | NOT R IS NULL | NOT R IS NOT NULL | +-----------------------+-----------+---------------+---------------+-------------------+ @@ -5466,11 +5466,11 @@ NOT((A, B) IS NOT NULL)]]>
    In jOOQ, you would simply use the isNull() and isNotNull() methods on row value expressions. Again, as with the , the row value expression NULL predicate is emulated by jOOQ, if your database does not natively support it:

    - +
    - +
    DISTINCT predicate @@ -5496,7 +5496,7 @@ BOOK.TITLE.isNotDistinctFrom(BOOK.SUB_TITLE)]]>

    If your database does not natively support the DISTINCT predicate, jOOQ emulates it with an equivalent , modelling the above truth table:

    - + The BETWEEN predicate can be seen as syntactic sugar for a pair of . According to the SQL standard, the following two predicates are equivalent:

    - + = [B] AND [A] <= [C]]]> @@ -5542,7 +5542,7 @@ BOOK.PUBLISHED_IN.notBetween(1920).and(1940)]]>

    The SQL standard defines the SYMMETRIC keyword to be used along with BETWEEN to indicate that you do not care which bound of the range is larger than the other. A database system should simply swap range bounds, in case the first bound is greater than the second one. jOOQ supports this keyword as well, emulating it if necessary.

    - +

    The emulation is done trivially:

    - + @@ -5566,24 +5566,24 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The SQL BETWEEN predicate also works well for . Much like the , it is defined in terms of a pair of regular :

    - + = [B] AND [A] <= [C] ([A] >= [B] AND [A] <= [C]) OR ([A] >= [C] AND [A] <= [B])]]> - +

    The above can be factored out according to the rules listed in the manual's section about .

    - +

    jOOQ supports the BETWEEN [SYMMETRIC] predicate and emulates it in all SQL dialects where necessary. An example is given here:

    - +
    - +
    LIKE predicate @@ -5603,7 +5603,7 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]> TITLE NOT LIKE '%abc%']]> - +

    Escaping operands with the LIKE predicate

    Often, your pattern may contain any of the wildcard characters "_" and "%", in case of which you may want to escape them. jOOQ does not automatically escape patterns in like() and notLike() methods. Instead, you can explicitly define an escape character as such: @@ -5621,12 +5621,12 @@ BOOK.TITLE.notLike("%The !%-Sign Book%", '!')]]>

    Please refer to your database manual for more details about escaping patterns with the LIKE predicate.

    - +

    jOOQ's convenience methods using the LIKE predicate

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using the LIKE predicate. Typical operations are "contains predicates", "starts with predicates", "ends with predicates", etc. Here is the full convenience API wrapping LIKE predicates:

    - + >) // Construct a NOT IN predicate from a subse

    A sample IN predicate might look like this:

    - + - +

    NOT IN and NULL values

    Beware that you should probably not have any NULL values in the right hand side of a NOT IN predicate, as the whole expression would evaluate to NULL, which is rarely desired. This can be shown informally using the following reasoning:

    - + -- The following conditional expressions are formally or informally equivalent A NOT IN (B, C) A != ANY(B, C) @@ -5714,10 +5714,10 @@ NULL -- [ANY] AND NULL yields NULL

    jOOQ supports the IN predicate. Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value. An example is given here:

    - +
    - +
    EXISTS predicate @@ -5729,7 +5729,7 @@ NULL -- [ANY] AND NULL yields NULL
  • From a using
  • From a using , and from other clauses
  • - +

    An example of an EXISTS predicate can be seen here:

    @@ -5747,7 +5747,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

    - +

    Performance of IN vs. EXISTS

    In theory, the two types of predicates can perform equally well. If your database system ships with a sophisticated cost-based optimiser, it will be able to transform one predicate into the other, if you have all necessary constraints set (e.g. referential constraints, not null constraints). However, in reality, performance between the two might differ substantially. An interesting blog post investigating this topic on the MySQL database can be seen here:
    @@ -5755,7 +5755,7 @@ notExists(create.selectOne().from(BOOK)

    - +
    OVERLAPS predicate @@ -5793,7 +5793,7 @@ row(Date.valueOf('2010-01-01'), new DayToSecond(2)).overlaps(Date.valueOf('2010-

    Unlike the standard (or any database implementing the standard), jOOQ also supports the OVERLAPS predicate for comparing arbitrary . For instance, (1, 3) OVERLAPS (2, 4) will yield true in jOOQ. This is emulated as such

    - +
    - +
    Dynamic SQL

    In most cases, , , and as introduced in the previous chapters will be embedded into different SQL statement clauses as if the statement were a static SQL statement (e.g. in a view or stored procedure):

    - + - +

    It is, however, interesting to think of all of the above expressions as what they are: expressions. And as such, nothing keeps users from extracting expressions and referencing them from outside the statement. The following statement is exactly equivalent:

    @@ -5836,26 +5836,26 @@ create.select(select) .groupBy(groupBy) .orderBy() .fetch();]]> - +

    Each individual expression, and collection of expressions can be seen as an independent entity that can be

    - +
    1. Constructed dynamically
    2. Reused across queries
    - +

    Dynamic construction is particularly useful in the case of the , for dynamic predicate building. For instance:

    - +

    The dynamic SQL building power may be one of the biggest advantages of using a runtime query model like the one offered by jOOQ. Queries can be created dynamically, of arbitrary complexity. In the above example, we've just constructed a dynamic . The same can be done for any other clauses, including dynamic as needed.

    @@ -5891,7 +5891,7 @@ create.select()
  • - +

    You'll probably find other examples. If verbosity scares you off, don't worry. The verbose use-cases for jOOQ are rather rare, and when they come up, you do have an option. Just write SQL the way you're used to!

    @@ -5921,7 +5921,7 @@ Condition condition(String sql, Object... bindings); // Construct a condition taking other jOOQ object arguments // Example: condition("a = {0}", val(1)); 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 DSL:

    @@ -5979,7 +5979,7 @@ Result fetch(String sql, QueryPart... parts);]]>

    Apart from the general factory methods, plain SQL is also available in various other contexts. For instance, when adding a .where("a = b") clause to a query. Hence, there exist several convenience methods where plain SQL can be inserted usefully. This is an example displaying all various use-cases in one single query:

    - + LAST_NAME = create.field("a.LAST_NAME"); @@ -6038,7 +6038,7 @@ create.select(LAST_NAME, COUNT1, COUNT2) On a JDBC level, you can also reuse the SQL string and prepared statement object instead of constructing it again, as you can bind new values to the prepared statement. jOOQ currently does not cache prepared statements, internally. - +

    The following sections explain how you can introduce bind values in jOOQ, and how you can control the way they are rendered and bound to SQL.

    @@ -6051,7 +6051,7 @@ create.select(LAST_NAME, COUNT1, COUNT2)

    JDBC only knows indexed bind values. A typical example for using bind values with JDBC is this:

    - + With dynamic SQL, keeping track of the number of question marks and their corresponding index may turn out to be hard. jOOQ abstracts this and lets you provide the bind value right where it is needed. A trivial example is this:

    - + 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

    Should you decide to run the above query outside of jOOQ, using your own , you can do so as follows:

    - + select = create.select().from(BOOK).where(BOOK.ID.equal(5)).and(BOOK.TITLE.equal("Animal Farm")); // Render the SQL statement: @@ -6202,7 +6202,7 @@ create.select()

    Special care needs to be taken when using . While jOOQ's API allows you to specify bind values for use with plain SQL, you're not forced to do that. For instance, both of the following queries will lead to the same, valid result:

    - +

    A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] FROM AUTHOR JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID @@ -6345,15 +6345,15 @@ public final void toSQL(RenderContext context) {

    As mentioned in the previous chapter about , there are some elements in the that are used for formatting / pretty-printing rendered SQL. In order to obtain pretty-printed SQL, just use the following :

    - - + +

    And then, use the above DSLContext to render pretty-printed SQL:

    - + A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] WHERE AUTHOR.ID = ? -- [...] @@ -6441,7 +6441,7 @@ public final void bind(BindContext context) throws DataAccessException {

    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:

    - + extends AbstractField {} public abstract class CustomCondition extends AbstractCondition {} public abstract class CustomTable> extends TableImpl {} @@ -6450,7 +6450,7 @@ public abstract class CustomRecord> extends TableRecord

    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 and methods, as discussed before:

    - + 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 showing how to create a field multiplying another field by 2

    - + IDx2 = new CustomField(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(" * ?"); @@ -6487,10 +6487,10 @@ final Field IDx2 = new CustomField(BOOK.ID.getName(), BOOK.ID. @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(DSL.val(2)); } @@ -6503,7 +6503,7 @@ final Field IDx2 = new CustomField(BOOK.ID.getName(), BOOK.ID. // Use the above field in a SQL statement: create.select(IDx2).from(BOOK);]]>
    - +
    Plain SQL QueryParts @@ -6517,7 +6517,7 @@ create.select(IDx2).from(BOOK);]]>

    The above distinction is best explained using an example:

    - +
    - +
    SQL building in Scala

    jOOQ-Scala is a maven module used for leveraging some advanced Scala features for those users that wish to use jOOQ with Scala.

    - +

    Using Scala's implicit defs to allow for operator overloading

    The most obvious Scala feature to use in jOOQ are implicit defs for implicit conversions in order to enhance the type with SQL-esque operators. @@ -6574,7 +6574,7 @@ create.attach(select);]]>

    The following depicts a trait which wraps all fields:

    - + The following depicts a trait which wraps numeric fields:

    - + An example query using such overloaded operators would then look like this:

    - +

    In a previous section of the manual, we've seen how jOOQ can be used to that can be executed with any API including JDBC or ... jOOQ. This section of the manual deals with various means of actually executing SQL with jOOQ.

    - +

    SQL execution with JDBC

    JDBC calls executable objects "". It distinguishes between three types of statements: @@ -6714,7 +6714,7 @@ fetch]]>

    Today, the JDBC API may look weird to users being used to object-oriented design. While statements hide a lot of SQL dialect-specific implementation details quite well, they assume a lot of knowledge about the internal state of a statement. For instance, you can use the method, to add a the prepared statement being created to an "internal list" of batch statements. Instead of returning a new type, this method forces user to reflect on the prepared statement's internal state or "mode".

    - +

    jOOQ is wrapping JDBC

    These things are abstracted away by jOOQ, which exposes such concepts in a more object-oriented way. For more details about jOOQ's batch query execution, see the manual's section about . @@ -6736,7 +6736,7 @@ fetch]]>

  • Both APIs return the number of affected records in non-result queries. JDBC: , jOOQ:
  • Both APIs return a scrollable result set type from result queries. JDBC: , jOOQ:
  • - +

    Differences to JDBC

    Some of the most important differences between JDBC and jOOQ are listed here: @@ -6752,14 +6752,14 @@ fetch]]>

    - +
    Query vs. ResultQuery

    Unlike JDBC, jOOQ has a lot of knowledge about a SQL query's structure and internals (see the manual's section about ). Hence, jOOQ distinguishes between these two fundamental types of queries. While every can be executed, only can return results (see the manual's section about to learn more about fetching results). With plain SQL, the distinction can be made clear most easily:

    - + result = resultQuery.fetch();]]>
  • : Some databases allow for returning many result sets from a single query. JDBC can handle this but it's very verbose. A list of results should be returned instead.
  • : Some queries take too long to execute to wait for their results. You should be able to spawn query execution in a separate process.
  • - +

    Convenience and how ResultQuery, Result, and Record share API

    The term "fetch" is always reused in jOOQ when you can fetch data from the database. An provides many overloaded means of fetching data:

    - +

    Various modes of fetching

    These modes of fetching are also documented in subsequent sections of the manual

    - + fetch(); @@ -6824,7 +6824,7 @@ List> fetchMany(); // Execute a ResultQuery with jOOQ, but return a JDBC ResultSet, not a jOOQ object ResultSet fetchResultSet();]]> - +

    Fetch convenience

    These means of fetching are also available from and APIs @@ -6870,11 +6870,11 @@ ResultSet fetchResultSet();]]>

    These means of fetching are also available from and APIs

    - + Map fetchMap(Field key); Map fetchMap(Field key, Field value); @@ -6911,7 +6911,7 @@ ResultSet fetchResultSet();]]>

    jOOQ understands that SQL is much more expressive than Java, when it comes to the declarative typing of . As a declarative language, SQL allows for creating ad-hoc row value expressions (records with indexed columns, or tuples) and records (records with named columns). In Java, this is not possible to the same extent. Yet, still, sometimes you wish to use strongly typed records, when you know that you're selecting only from a single table

    - +

    Fetching strongly or weakly typed records

    When fetching data only from a single table, the type is known to jOOQ if you use jOOQ's to generate for your database tables. In order to fetch such strongly typed records, you will have to use the : @@ -6923,7 +6923,7 @@ BookRecord book = create.selectFrom(BOOK).where(BOOK.ID.equal(1)).fetchOne(); // Typesafe field access is now possible: 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:

    @@ -6969,7 +6969,7 @@ System.out.println("Published in: " + book.getPublishedIn());]]>

    By default, jOOQ returns an object, which is essentially a of . Often, you will find yourself wanting to transform this result object into a type that corresponds more to your specific needs. Or you just want to list all values of one specific column. Here are some examples to illustrate those use cases:

    - + titles1 = create.select().from(BOOK).fetch().getValues(BOOK.TITLE); List titles2 = create.select().from(BOOK).fetch(BOOK.TITLE); @@ -7004,7 +7004,7 @@ Map> group4 = create.selectFrom(BOOK).fetchGroups(BO

    In a more functional operating mode, you might want to write callbacks that receive records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + () {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -7039,7 +7039,7 @@ create.selectFrom(BOOK)

    In a more functional operating mode, you might want to write callbacks that map records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + ids = create.selectFrom(BOOK) @@ -7051,12 +7051,12 @@ create.selectFrom(BOOK) return book.getId(); } }); - + // Or more concisely create.selectFrom(BOOK) .orderBy(BOOK.ID) .fetch(new RecordMapper() {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -7082,7 +7082,7 @@ create.selectFrom(BOOK)

    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. See the manual's section about to see how to modify jOOQ's standard POJO mapping behaviour.

    - +

    Using JPA-annotated POJOs

    jOOQ tries to find JPA annotations on your POJO types. If it finds any, they are used as the primary source for mapping meta-information. Only the annotation is used and understood by jOOQ. An example: @@ -7092,7 +7092,7 @@ create.selectFrom(BOOK) public class MyBook { @Column(name = "ID") public int myId; - + @Column(name = "TITLE") public String myTitle; } @@ -7101,16 +7101,16 @@ public class MyBook { MyBook myBook = create.select().from(BOOK).fetchAny().into(MyBook.class); List myBooks = create.select().from(BOOK).fetch().into(MyBook.class); List myBooks = create.select().from(BOOK).fetchInto(MyBook.class);]]> - +

    Just as with any other JPA implementation, you can put the annotation on any class member, including attributes, setters and getters. Please refer to the Javadoc for more details.

    - +

    Using simple POJOs

    If jOOQ does not find any JPA-annotations, columns are mapped to the "best-matching" constructor, attribute or setter. An example illustrates this:

    - + myBooks = create.select().from(BOOK).fetchInto(MyBook1.class);]]><

    Please refer to the Javadoc for more details.

    - +

    Using "immutable" POJOs

    If jOOQ does not find any default constructor, columns are mapped to the "best-matching" constructor. This allows for using "immutable" POJOs with jOOQ. An example illustrates this:

    - + myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchInto( public class MyBook3 { public final String title; public final int id; - + @ConstructorProperties({ "title", "id"}) public MyBook2(String title, int id) { this.title = title; @@ -7165,7 +7165,7 @@ MyBook3 myBook = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchA List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetch().into(MyBook3.class); List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchInto(MyBook3.class); ]]> - +

    Please refer to the Javadoc for more details.

    @@ -7174,12 +7174,12 @@ List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchI

    jOOQ also allows for fetching data into abstract classes or interfaces, or in other words, "proxyable" types. This means that jOOQ will return a wrapped in a implementing your custom type. An example of this is given here:

    - + - +

    Note: Because of your manual setting of ID = 10, jOOQ's store() method will asume that you want to insert a new record. See the manual's section about for more details on this.

    - +

    Interaction with DAOs

    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: @@ -7246,21 +7246,21 @@ bookDao.update(book); // Delete it again bookDao.delete(book);]]> - +

    More complex data structures

    jOOQ currently doesn't support more complex data structures, the way Hibernate/JPA attempt to map relational data onto POJOs. While future developments in this direction are not excluded, jOOQ claims that generic mapping strategies lead to an enormous additional complexity that only serves very few use cases. You are likely to find a solution using any of jOOQ's various , with only little boiler-plate code on the client side.

    - +
    POJOs with RecordMappers

    In the previous sections we have seen how to create types to map jOOQ records onto arbitrary objects. We have also seen how jOOQ provides default algorithms to map jOOQ records onto . Your own custom domain model might be much more complex, but you want to avoid looking up the most appropriate RecordMapper every time you need one. For this, you can provide jOOQ's with your own implementation of the interface. An example is given here:

    - + } } } - + // Books might be joined with their authors, create a 1:1 mapping if (type == Book.class) { return new BookMapper(); @@ -7297,7 +7297,7 @@ bookDao.delete(book);]]>

    The above is a very simple example showing that you will have complete flexibility in how to override jOOQ's record to POJO mapping mechanisms.

    - +

    If you're looking into a generic, third-party mapping utility, have a look at ModelMapper, or Orika Mapper, which can both be easily integrated with jOOQ.

    @@ -7310,7 +7310,7 @@ bookDao.delete(book);]]>

    Unlike JDBC's , jOOQ's does not represent an open database cursor with various fetch modes and scroll modes, that needs to be closed after usage. jOOQ's results are simple in-memory Java objects, containing all of the result values. If your result sets are large, or if you have a lot of network latency, you may wish to fetch records one-by-one, or in small chunks. jOOQ supports a type for that purpose. In order to obtain such a reference, use the method. An example is given here:

    - + cursor = null; @@ -7320,7 +7320,7 @@ try { // Cursor has similar methods as Iterator while (cursor.hasNext()) { BookRecord book = cursor.fetchOne(); - + Util.doThingsWithBook(book); } } @@ -7335,7 +7335,7 @@ finally {

    As a holds an internal reference to an open , it may need to be closed at the end of iteration. If a cursor is completely scrolled through, it will conveniently close the underlying ResultSet. However, you should not rely on that.

    - +

    Cursors ship with all the other fetch features

    Like or , gives access to all of the other fetch features that we've seen so far, i.e. @@ -7377,7 +7377,7 @@ finally {

    The correct (and verbose) way to do this with JDBC is as follows:

    - +

    As previously discussed in the chapter about , jOOQ does not rely on an internal state of any JDBC object, which is "externalised" by Javadoc. Instead, it has a straight-forward API allowing you to do the above in a one-liner:

    - + > results = create.fetchMany("sp_help 'author'");]]> @@ -7418,22 +7418,22 @@ List> results = create.fetchMany("sp_help 'author'");]]>
    Later fetching

    Using Java 8 CompletableFutures

    - +

    Java 8 has introduced the new type, which allows for functional composition of asynchronous execution units. When applying this to SQL and jOOQ, you might be writing code as follows:

    - + + .supplyAsync(() -> DSL.using(configuration) .insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .values(3, "Hitchcock") .execute() ) - + // This will supply an AuthorRecord value for the newly inserted author .handleAsync((rows, throwable) -> DSL.using(configuration) @@ -7446,30 +7446,30 @@ CompletableFuture record.changed(true); return record.insert(); }) - + // This will supply an int value indicating the number of deleted rows - .handleAsync((rows, throwable) -> + .handleAsync((rows, throwable) -> DSL.using(configuration) .delete(AUTHOR) .where(AUTHOR.ID.eq(3)) .execute() ) .join();]]> - +

    The above example will execute four actions one after the other, but asynchronously in the JDK's default or common . -

    - +

    +

    For more information, please refer to the Javadoc and official documentation. -

    - +

    +

    Using deprecated API

    - +

    Some queries take very long to execute, yet they are not crucial for the continuation of the main program. For instance, you could be generating a complicated report in a Swing application, and while this report is being calculated in your database, you want to display a background progress bar, allowing the user to pursue some other work. This can be achived simply with jOOQ, by creating a , a type that extends . An example is given here:

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(); @@ -7485,7 +7485,7 @@ Result result = future.get();]]>

    Note, that instead of letting jOOQ spawn a new thread, you can also provide jOOQ with your own :

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(service);]]>
    @@ -7497,7 +7497,7 @@ FutureResult future = create.selectFrom(BOOK).where(... complex pred

    When interacting with legacy applications, you may prefer to have jOOQ return a , rather than jOOQ's own types. This can be done simply, in two ways:

    - + cursor = create.fetchLazy(rs);]]>

    You can also tighten the interaction with jOOQ's data type system and features, by passing the record type to the above fetch methods:

    - + result = create.fetch (rs, Integer.class, String.class); Cursor result = create.fetchLazy(rs, Integer.class, String.class); @@ -7559,7 +7559,7 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Apart from a few extra features (), jOOQ only supports basic types as supported by the JDBC API. In your application, you may choose to transform these data types into your own ones, without writing too much boiler-plate code. This can be done using jOOQ's types. A converter essentially allows for two-way conversion between two Java data types <T> and <U>. By convention, the <T> type corresponds to the type in your database whereas the <U> type corresponds to your own user type. The Converter API is given here:

    - + extends Serializable { /** @@ -7586,12 +7586,12 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Such a converter can be used in many parts of the jOOQ API. Some examples have been illustrated in the manual's section about .

    - +

    A Converter for GregorianCalendar

    Here is a some more elaborate example involving a Converter for :

    - + { @@ -7622,12 +7622,12 @@ public class CalendarConverter implements Converter dates1 = create.selectFrom(BOOK).fetch().getValues(BOOK.PUBLISHING_DATE, new CalendarConverter()); List dates2 = create.selectFrom(BOOK).fetch(BOOK.PUBLISHING_DATE, new CalendarConverter()); ]]> - +

    Enum Converters

    jOOQ ships with a built-in default , that you can use to map VARCHAR values to enum literals or NUMBER values to enum ordinals (both modes are supported). Let's say, you want to map a YES / NO / MAYBE column to a custom Enum:

    - + - +

    Using Converters in generated source code

    jOOQ also allows for generated source code to reference your own custom converters, in order to permanently replace a <T> type by your own, custom <U> type. See the manual's section about for details. @@ -7689,20 +7689,20 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE) .join(AUTHOR).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) .intern(BOOK.AUTHOR_ID) .fetch();]]> - +

    You can specify as many fields as you want for interning. The above has the following effect:

    - +
    • If the interned Field is of type , then is called upon each string
    • If the interned Field is of any other type, then the call is ignored
    - +

    Future versions of jOOQ will implement interning of data for non-String data types by collecting values in , removing duplicate instances.

    - +

    Note, that jOOQ will not use interned data for identity comparisons: string1 == string2. Interning is used only to reduce the memory footprint of objects.

    @@ -7710,7 +7710,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)
    - +
    Static statements vs. Prepared Statements @@ -7720,7 +7720,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)

    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:

    - + @@ -7749,7 +7749,7 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    Whichever aproach is more optimal for you cannot be decided by jOOQ. In most cases, prepared statements are probably better. But you always have the option of forcing jOOQ to render inlined bind values.

    - +

    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 @@ -7763,15 +7763,15 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    As previously discussed in the chapter about , reusing PreparedStatements is handled a bit differently in jOOQ from how it is handled in JDBC

    - +

    Keeping open PreparedStatements with JDBC

    With JDBC, you can easily reuse a by not closing it between subsequent executions. An example is given here:

    - + The above technique can be quite useful when you want to reuse expensive database resources. This can be the case when your statement is executed very frequently and your database would take non-negligible time to soft-parse the prepared statement and generate a new statement / cursor resource.

    - +

    Keeping open PreparedStatements with jOOQ

    This is also modeled in jOOQ. However, the difference to JDBC is that closing a statement is the default action, whereas keeping it open has to be configured explicitly. This is better than JDBC, because the default action should be the one that is used most often. Keeping open statements is rarely done in average applications. Here's an example of how to keep open PreparedStatements with jOOQ:

    - + query = create.selectOne().keepStatement(true); @@ -7814,7 +7814,7 @@ finally {

    JDBC knows a couple of execution flags and modes, which can be set through the jOOQ API as well. jOOQ essentially supports these flags and execution modes:

    - + extends Query { // [...] @@ -7841,25 +7841,25 @@ finally { // The maximum number of rows to be fetched by JDBC // ----------------------------------------------------------- ResultQuery maxRows(int rows); - + }]]>

    Using ResultSet concurrency with ExecuteListeners

    An example of why you might want to manually set a ResultSet's concurrency flag to something non-default is given here:

    - + - +

    In the above example, your custom is triggered before jOOQ loads a new Record from the JDBC ResultSet. With the concurrency being set to ResultSet.CONCUR_UPDATABLE, you can now modify the database cursor through the standard JDBC ResultSet API.

    @@ -7977,18 +7977,18 @@ create.batch(create.insertInto(AUTHOR, ID, FIRST_NAME, LAST_NAME ).values((Inte

    Instead of actually phrasing a select statement, you can also use the convenience methods:

    - + - +

    Inlining sequence references in SQL

    You can inline sequence references in jOOQ SQL statements. The following are examples of how to do that:

    - + The general distinction between (stored) procedures and (stored) functions can be summarised like this:

    - +

    Procedures

    • Are called using JDBC CallableStatement
    • Have no return value
    • Usually support OUT parameters
    - +

    Functions

    • Can be used in SQL statements
    • Have a return value
    • Usually don't support OUT parameters
    - +

    Exceptions to these rules

    • DB2, H2, and HSQLDB don't allow for JDBC escape syntax when calling functions. Functions must be used in a SELECT statement
    • @@ -8048,19 +8048,19 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

      To simplify things a little bit, jOOQ handles both procedures and functions the same way, using a more general type.

      - +

      Using jOOQ for standalone calls to stored procedures and functions

      If you're using jOOQ's , it will generate objects for you. Let's consider the following example:

      - +

      The generated artefacts can then be used as follows:

      - + - +

      But you can also call the procedure using a generated convenience method in a global Routines class:

      @@ -8087,7 +8087,7 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]>

      For more details about for procedures, see the manual's section about .

      - +

      Inlining stored function references in SQL

      Unlike procedures, functions can be inlined in SQL statements to generate or , if you're using . Assume you have a function like this: @@ -8095,11 +8095,11 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]> - +

      The generated artefacts can then be used as follows:

      - + - +

      For more info about inlining stored function references in SQL statements, please refer to the manual's section about .

      @@ -8139,7 +8139,7 @@ create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]>

      Oracle UDTs can have object-oriented structures including member functions and procedures. With Oracle, you can do things like this:

      - + {"name":"field-n","type":"type-n"}], "records":[[value-1-1,value-1-2,...,value-1-n], [value-2-1,value-2-2,...,value-2-n]]} - +

      Note: This format has changed in jOOQ 2.6.0

      @@ -8464,12 +8464,12 @@ Query query = error.query();]]>

      CRUD always uses the same patterns, regardless of the nature of underlying tables. This again, leads to a lot of boilerplate code, if you have to issue your statements yourself. Like Hibernate / JPA and other ORMs, jOOQ facilitates CRUD using a specific API involving types.

      - +

      Primary keys and updatability

      In normalised databases, every table has a primary key by which a tuple/record within that table can be uniquely identified. In simple cases, this is a (possibly auto-generated) number called ID. But in many cases, primary keys include several non-numeric columns. An important feature of such keys is the fact that in most databases, they are enforced using an index that allows for very fast random access to the table. A typical way to access / modify / delete a book is this:

      - + - +

      Normalised databases assume that a primary key is unique "forever", i.e. that a key, once inserted into a table, will never be changed or re-inserted after deletion. In order to use jOOQ's operations correctly, you should design your database accordingly.

      @@ -8490,7 +8490,7 @@ DELETE FROM BOOK WHERE ID = 5;]]>

      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:

      - + - +

      See the manual's section about for some more insight on "attached" objects.

      - +

      Storing

      Storing a record will perform an or an . In general, new records are always inserted, whereas records loaded from the database are always updated. This is best visualised in code: @@ -8529,7 +8529,7 @@ BookRecord book2 = create.fetchOne(BOOK, BOOK.ID.equal(id)); // Update the record: UPDATE BOOK SET TITLE = 'Animal Farm' WHERE ID = [id] book2.setTitle("Animal Farm"); book2.store();]]> - +

      Some remarks about storing:

      @@ -8539,18 +8539,18 @@ book2.store();]]>
    • When loading records from , jOOQ will assume the record is a new record. It will hence attempt to INSERT it.
    • When you activate , storing a record may fail, if the underlying database record has been changed in the mean time.
    - +

    Deleting

    Deleting a record will remove it from the database. Here's how you delete records:

    - + - +

    Refreshing

    Refreshing a record from the database means that jOOQ will issue a to refresh all record values that are not the primary key. This is particularly useful when you use jOOQ's feature, in case a modified record is "stale" and cannot be stored to the database, because the underlying database record has changed in the mean time. @@ -8569,7 +8569,7 @@ book.refresh();]]>

    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 :

    - + The "original" value, i.e. the value as it was originally fetched from the database or null, if the record was never in the database
  • The "changed" flag, indicating if the value was ever changed through the Record API.
  • - +

    The purpose of the above information is for jOOQ's to know, which values need to be stored to the database, and which values have been left untouched.

    @@ -8604,19 +8604,19 @@ for (BookRecord book : create.fetch(BOOK, BOOK.PUBLISHED_IN.equal(1948))) {

    Many databases support the concept of IDENTITY values, or key values. This is reflected by JDBC's method. jOOQ abstracts using this method as many databases and JDBC drivers behave differently with respect to generated keys. Let's assume the following SQL Server BOOK table:

    - +

    If you're using jOOQ's , the above table will generate a with an IDENTITY column. This information is used by jOOQ internally, to update IDs after calling :

    - +

    and contain foreign key navigation methods. These navigation methods allow for "navigating" inbound or outbound foreign key references by executing an appropriate query. An example is given here:

    - + books = author.fetchChildren(FK_BOOK_AUTHOR);]]>

    Tables without a PRIMARY KEY are considered non-updatable by jOOQ, as jOOQ has no way of uniquely identifying such a record within the database. If you're using jOOQ's , such tables will generate classes, instead of classes. When you fetch from such a table, the returned records will not allow for calling any of the methods.

    - +

    Note, that some databases use internal rowid or object-id values to identify such records. jOOQ does not support these vendor-specific record meta-data.

    @@ -8746,7 +8746,7 @@ Result books = author.fetchChildren(FK_BOOK_AUTHOR);]]>
    - +

    Optimised optimistic locking using TIMESTAMP fields

    If you're using jOOQ's , you can take indicate TIMESTAMP or UPDATE COUNTER fields for every generated table in the . Let's say we have this table:

    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:

    - +

    As before, without the added TIMESTAMP column, optimistic locking is transparent to the API.

    - +

    Optimised optimistic locking using VERSION fields

    Instead of using TIMESTAMPs, you may also use numeric VERSION fields, containing version numbers that are incremented by jOOQ upon store() calls. @@ -8815,7 +8815,7 @@ book2.store();]]>

    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:

    - + books = create.fetch(BOOK); @@ -8840,7 +8840,7 @@ create.batchStore(books);]]>

    If you're using jOOQ's , you can configure it to generate and DAOs for you. jOOQ then generates one DAO per , i.e. per table with a single-column primary key. Generated DAOs implement a common jOOQ type called . This type contains the following methods:

    - + corresponds to the DAO's related table //

    corresponds to the DAO's related generated POJO type // corresponds to the DAO's related table's primary key type. @@ -8851,23 +8851,23 @@ public interface DAO, P, T> { void insert(P object) throws DataAccessException; void insert(P... objects) throws DataAccessException; void insert(Collection

    objects) throws DataAccessException; - + // These methods allow for updating POJOs based on their primary key void update(P object) throws DataAccessException; void update(P... objects) throws DataAccessException; void update(Collection

    objects) throws DataAccessException; - + // These methods allow for deleting POJOs based on their primary key void delete(P... objects) throws DataAccessException; void delete(Collection

    objects) throws DataAccessException; void deleteById(T... ids) throws DataAccessException; void deleteById(Collection ids) throws DataAccessException; - + // These methods allow for checking record existence boolean exists(P object) throws DataAccessException; boolean existsById(T id) throws DataAccessException; long count() throws DataAccessException; - + // These methods allow for retrieving POJOs by primary key or by some other field List

    findAll() throws DataAccessException; P findById(T id) throws DataAccessException; @@ -8896,7 +8896,7 @@ public class BookDao extends DAOImpl {

    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:

    - +

    With jOOQ, it's simple. All of jOOQ's exceptions are "system exceptions", hence they are all unchecked.

    - +

    jOOQ's DataAccessException

    jOOQ uses its own to wrap any underlying that might have occurred. Note that all methods in jOOQ that may cause such a DataAccessException document this both in the Javadoc as well as in their method signature. @@ -8945,7 +8945,7 @@ bookDao.delete(book);]]>

  • InvalidResultException: An operation was performed expecting only one result, but several results were returned.
  • MappingException: Something went wrong when loading a record from a or when mapping a record into a POJO
  • - +

    Override jOOQ's exception handling

    The following section about documents means of overriding jOOQ's exception handling, if you wish to deal separately with some types of constraint violations, or if you raise business errors from your database, etc. @@ -8977,11 +8977,11 @@ public class StatisticsListener extends DefaultExecuteListener { public void start(ExecuteContext ctx) { synchronized (STATISTICS) { Integer count = STATISTICS.get(ctx.type()); - + if (count == null) { count = 0; } - + STATISTICS.put(ctx.type(), count + 1); } } @@ -9024,7 +9024,7 @@ for (ExecuteType type : ExecuteType.values()) {

    Please read the for more details

    - +

    Writing a custom ExecuteListener for logging

    The following depicts an example of a custom ExecuteListener, which pretty-prints all queries being executed by jOOQ to stdout: @@ -9047,7 +9047,7 @@ public class PrettyPrinter extends DefaultExecuteListener { // Create a new DSLContext for logging rendering purposes // This DSLContext doesn't need a connection, only the SQLDialect... DSLContext create = DSL.using(ctx.configuration().dialect(), - + // ... and the flag for pretty-printing new Settings().withRenderFormatted(true)); @@ -9055,12 +9055,12 @@ public class PrettyPrinter extends DefaultExecuteListener { if (ctx.query() != null) { System.out.println(create.renderInlined(ctx.query())); } - + // If we're executing a routine else if (ctx.routine() != null) { System.out.println(create.renderInlined(ctx.routine())); } - + // If we're executing anything else (e.g. plain SQL) else if (!StringUtils.isBlank(ctx.sql())) { System.out.println(ctx.sql()); @@ -9088,7 +9088,7 @@ public class PrettyPrinter extends DefaultExecuteListener {

    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:

    - + @@ -9106,7 +9106,7 @@ public class PrettyPrinter extends DefaultExecuteListener {

    With the above configuration, let's fetch some data with jOOQ

    - + @@ -9155,7 +9155,7 @@ Finishing : Total: 4.814ms, +3.375ms
  • 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
  • - +

    Optimise wisely

    Don't be put off by the above paragraphs. You should optimise wisely, i.e. only in places where you really need very high throughput to your database. jOOQ's overhead compared to plain JDBC is typically less than 1ms per query. @@ -9212,7 +9212,7 @@ Finishing : Total: 4.814ms, +3.375ms

    You need to tell jOOQ some things about your database connection. Here's an example of how to do it for an Oracle database

    - + @@ -9221,7 +9221,7 @@ Finishing : Total: 4.814ms, +3.375ms jdbc:oracle:thin:@[your jdbc connection parameters] [your database user] [your database password] - + user[db-user] @@ -9298,13 +9298,13 @@ Finishing : Total: 4.814ms, +3.375ms

    Code generation works by calling this class with the above property file as argument.

    - + org.jooq.util.GenerationTool /jooq-config.xml

    Be sure that these elements are located on the classpath:

    - +
    • The XML configuration file
    • jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar
    • @@ -9329,7 +9329,7 @@ Finishing : Total: 4.814ms, +3.375ms
    • this example uses jOOQ's log4j support by adding log4j.xml and log4j.jar to the project classpath.
    • the actual jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar artefacts may contain version numbers in the file names.
    - +
    Eclipse configuration
    @@ -9603,7 +9603,7 @@ public class AsInDatabaseStrategy extends DefaultGeneratorStrategy { optimistic locking (A Java regular expression. Use the pipe to separate several expressions). See UpdatableRecord.store() and UpdatableRecord.delete() for details --> REC_TIMESTAMP - + @@ -9707,18 +9707,18 @@ public class AsInDatabaseStrategy extends DefaultGeneratorStrategy { false - + true ]]>
    @@ -9727,7 +9727,7 @@ public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {

    Some of the above properties depend on other properties to work correctly. For instance, when generating immutable pojos, pojos must be generated. jOOQ will enforce such properties even if you tell it otherwise. Here is a list of property interdependencies:

    - +
    • When daos = true, then jOOQ will set relations = true
    • When daos = true, then jOOQ will set records = true
    • @@ -9750,12 +9750,12 @@ public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {
    • Tables.java: This file contains all table objects in the form of static member references to the actual singleton object
    • UDTs.java: This file contains all UDT objects in the form of static member references to the actual singleton object
    - +

    Referencing global artefacts

    When referencing global artefacts from your client application, you would typically static import them as such:

    - + @@ -9777,7 +9777,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate a implementation that looks like this:

    - + { // The singleton instance @@ -9793,7 +9793,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE) public Book as(java.lang.String alias) { return new Book(alias); } - + // [...] }]]> @@ -9810,7 +9810,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)
  • instanceFields: This flag controls the "static" keyword on table columns, as well as aliasing convenience
  • records: The generated record type is referenced from tables allowing for type-safe single-table record fetching
  • - +

    Flags controlling table generation

    Table generation cannot be deactivated @@ -9824,7 +9824,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate an implementation that looks like this:

    - + - +

    Flags influencing generated records

    These flags from the influence generated records: @@ -9880,7 +9880,7 @@ implements IBook {

  • interfaces: If interfaces are generated, records will implement them
  • jpaAnnotations: JPA annotations are used on generated records
  • - +

    Flags controlling record generation

    Record generation can be deactivated using the records flag @@ -9894,7 +9894,7 @@ implements IBook {

    Every table in your database will generate a POJO implementation that looks like this:

    - + - +

    Flags influencing generated POJOs

    These flags from the influence generated POJOs: @@ -9943,7 +9943,7 @@ public class Book implements java.io.Serializable

  • jpaAnnotations: JPA annotations are used on generated records
  • validationAnnotations: JSR-303 validation annotations are used on generated records
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the pojos flag @@ -9957,16 +9957,16 @@ public class Book implements java.io.Serializable

    Every table in your database will generate an interface that looks like this:

    - + - +

    Flags influencing generated interfaces

    These flags from the influence generated interfaces: @@ -9975,7 +9975,7 @@ public class Book implements java.io.Serializable

  • dateAsTimestamp: This influences all relevant getters and setters
  • unsignedTypes: This influences all relevant getters and setters
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the interfaces flag @@ -9990,7 +9990,7 @@ public class Book implements java.io.Serializable

    Every table in your database will generate a implementation that looks like this:

    - + { // Generated constructors @@ -10014,10 +10014,10 @@ public class Book implements java.io.Serializable public List fetchByAuthorId(Integer... values) { return fetch(BOOK.AUTHOR_ID, values); } - + // [...] }]]> - +

    Flags controlling DAO generation

    DAO generation can be activated using the daos flag @@ -10031,13 +10031,13 @@ public class Book implements java.io.Serializable

    Every sequence in your database will generate a implementation that looks like this:

    - + S_AUTHOR_ID = new SequenceImpl("S_AUTHOR_ID", TEST, SQLDataType.INTEGER); }]]> - +

    Flags controlling sequence generation

    Sequence generation cannot be deactivated @@ -10075,7 +10075,7 @@ public class Book implements java.io.Serializable public BigDecimal getResult() { return getValue(RESULT); } - + // [...] }]]> @@ -10097,7 +10097,7 @@ public class Book implements java.io.Serializable

    Every UDT in your database will generate a implementation that looks like this:

    - + { // The singleton UDT instance @@ -10110,10 +10110,10 @@ public class Book implements java.io.Serializable createField("CITY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); public static final UDTField COUNTRY = createField("COUNTRY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); - + // [...] }]]> - +

    Besides the implementation, a implementation is also generated

    @@ -10128,7 +10128,7 @@ public class Book implements java.io.Serializable public String getCity() {...} public void setCountry(String value) {...} public String getCountry() {...} - + // [...] }]]> @@ -10243,23 +10243,23 @@ create.selectFrom(AUTHOR) ]]>
    - +
    Code generation for large schemas

    Databases can become very large in real-world applications. This is not a problem for jOOQ's code generator, but it can be for the Java compiler. jOOQ generates some classes for . These classes can hit two sorts of limits of the compiler / JVM:

    - +
    • Methods (including static / instance initialisers) are allowed to contain only 64kb of bytecode.
    • Classes are allowed to contain at most 64k of constant literals
    - +

    While there exist workarounds for the above two limitations (delegating initialisations to nested classes, inheriting constant literals from implemented interfaces), the preferred approach is either one of these:

    - +
    • Distribute your database objects in several schemas. That is probably a good idea anyway for such large databases
    • to exclude excess database objects
    • @@ -10342,11 +10342,11 @@ create.selectFrom(AUTHOR)

      When writing unit tests for your data access layer, you have probably used some generic mocking tool offered by popular providers like Mockito, jmock, mockrunner, or even DBUnit. With jOOQ, you can take advantage of the built-in JDBC mock API that allows you to emulate a simple database on the JDBC level for precisely those SQL/JDBC use cases supported by jOOQ.

      - +

      - Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider. + Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider.

      - +

      Mocking the JDBC API

      JDBC is a very complex API. It takes a lot of time to write a useful and correct mock implementation, implementing at least these interfaces: @@ -10359,16 +10359,16 @@ create.selectFrom(AUTHOR)

    - +

    Optionally, you may even want to implement interfaces, such as , , , and many others. In addition to the above, you might need to find a way to simultaneously support incompatible JDBC minor versions, such as 4.0, 4.1

    - +

    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 :

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    As you can see, the configuration setup is simple. Now, the MockDataProvider acts as your single point of contact with JDBC / jOOQ. It unifies any of these execution modes, transparently:

    - +
    • Statements without results
    • Statements without results but with generated keys
    • @@ -10391,16 +10391,16 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
    • Batch statements with single queries and multiple bind value sets
    • Batch statements with multiple queries and no bind values
    - +

    The above are the execution modes supported by jOOQ. Whether you're using any of jOOQ's various fetching modes (e.g. , , , ) is irrelevant, as those modes are all built on top of the standard JDBC API.

    - +

    Implementing MockDataProvider

    Now, here's how to implement MockDataProvider:

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc // 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 String sql = ctx.sql(); - + // Exceptions are propagated through the JDBC and jOOQ APIs if (sql.toUpperCase().startsWith("DROP")) { throw new SQLException("Statement not supported: " + sql); } - + // You decide, whether any given statement returns results, and how many else if (sql.toUpperCase().startsWith("SELECT")) { - + // Always return one author record Result result = create.newResult(AUTHOR); result.add(create.newRecord(AUTHOR)); @@ -10428,12 +10428,12 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc result.get(0).setValue(AUTHOR.LAST_NAME, "Orwell"); mock[0] = new MockResult(1, result); } - + // You can detect batch statements easily else if (ctx.batch()) { // [...] } - + return mock; } }]]> @@ -10445,17 +10445,17 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • : The number of affected rows
  • : The result set
  • - +

    You should return as many MockResult objects as there were query executions (in ) or results (in ). Instead of an awkward JDBC ResultSet, however, you can construct a "friendlier" with your own record types. The jOOQ mock API will use meta data provided with this Result in order to create the necessary JDBC

    - +

    See the for a list of rules that you should follow.

    - +
    jOOQ Console @@ -10501,7 +10501,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • Sybase Adaptive Server Enterprise 15.5
  • Sybase SQL Anywhere 12
  • - +

    For an up-to-date list of currently supported RDBMS, please refer to http://www.jooq.org/legal/licensing/#databases.

    @@ -10522,7 +10522,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc This chapter should document the most important notes about SQL, JDBC and jOOQ data types.

    - +
    BLOBs and CLOBs @@ -10532,7 +10532,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    - +
    Unsigned integer types @@ -10556,7 +10556,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
    - +
    INTERVAL data types @@ -10567,11 +10567,11 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • YEAR TO MONTH: This interval type models a number of months and years
  • DAY TO SECOND: This interval type models a number of days, hours, minutes, seconds and milliseconds
  • - +

    Both interval types ship with a variant of subtypes, such as DAY TO HOUR, HOUR TO SECOND, etc. jOOQ models these types as Java objects extending : (where Number.intValue() corresponds to the absolute number of months) and (where Number.intValue() corresponds to the absolute number of milliseconds)

    - +

    Interval arithmetic

    In addition to the documented previously, interval arithmetic is also supported by jOOQ. Essentially, the following operations are supported: @@ -10586,7 +10586,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    - +
    XML data types @@ -10595,7 +10595,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    - +
    Geospacial data types @@ -10605,7 +10605,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    - +
    CURSOR data types @@ -10614,22 +10614,22 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    > cursor;]]> - +

    In fact, such a cursor will be fetched immediately by jOOQ and wrapped in an object.

    - +
    ARRAY and TABLE data types

    The SQL standard specifies ARRAY data types, that can be mapped to Java arrays as such:

    - + intArray;]]> - +

    The above array type is supported by these SQL dialects:

    @@ -10638,7 +10638,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • HSQLDB
  • Postgres
  • - +

    Oracle typed arrays

    Oracle has strongly-typed arrays and table types (as opposed to the previously seen anonymously typed arrays). These arrays are wrapped by types. @@ -10654,12 +10654,12 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    jOOQ takes SQL as an external domain-specific language and maps it onto Java, creating an internal domain-specific language. Internal DSLs cannot 100% implement their external language counter parts, as they have to adhere to the syntax rules of their host or target language (i.e. Java). This section explains the various problems and workarounds encountered and implemented in jOOQ.

    - +

    SQL allows for "keywordless" syntax

    SQL syntax does not always need keywords to form expressions. The clause takes various argument assignments:

    - + UPDATE t SET a = 1, b = 2update(t).set(a, 1).set(b, 2) @@ -10675,12 +10675,12 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    In this case, ROW is an actual (optional) SQL keyword, implemented by at least PostgreSQL.

    - +

    SQL contains "composed" keywords

    As most languages, SQL does not attribute any meaning to whitespace. However, whitespace is important when forming "composed" keywords, i.e. SQL clauses composed of several keywords. jOOQ follows standard Java method naming conventions to map SQL keywords (case-insensitive) to Java methods (case-sensitive, camel-cased). Some examples:

    - + GROUP BY ORDER BY @@ -10692,7 +10692,7 @@ whenMatchedThenUpdate()

    Future versions of jOOQ may use all-uppercased method names in addition to the camel-cased ones (to prevent collisions with Java keywords):

    - + GROUP BY ORDER BY @@ -10721,7 +10721,7 @@ WHEN_MATCHED_THEN_UPDATE()

    The above example omits THEN and END keywords in Java. Future versions of jOOQ may comprise a more complete DSL, including such keywords again though, to provide a more 1:1 match for the SQL language.

    - +

    SQL contains "superfluous" syntactic elements

    Some SQL constructs are hard to map to Java, but they are also not really necessary. SQL often expects syntactic parentheses where they wouldn't really be needed, or where they feel slightly inconsistent with the rest of the SQL language. @@ -10756,7 +10756,7 @@ WHEN_MATCHED_THEN_UPDATE()

    jOOQ replaces those keywords by "synonyms":

    - + CASE .. ELSE PIVOT .. FOR .. IN ..decode() .. otherwise() @@ -10783,7 +10783,7 @@ pivot(..).on(..).in(..)

    Most SQL operators have to be mapped to descriptive method names in Java, as Java does not allow operator overloading:

    - + , != @@ -10810,7 +10810,7 @@ set(a, b)

    This is less of a syntactic SQL feature than a semantic one. In SQL, objects can be referenced before (i.e. "lexicographically before") they are declared. This is particularly true for

    - +

    A more sophisticated example are common table expressions (CTE), which are currently not supported by jOOQ:

    - + WITH t(a, b) AS ( SELECT 1, 2 FROM DUAL ) @@ -10832,7 +10832,7 @@ FROM t

    - +
    jOOQ's BNF pseudo-notation @@ -10841,7 +10841,7 @@ FROM t

    - +
    Quality Assurance @@ -10853,16 +10853,16 @@ FROM t
  • To add lots of type-safety to your inline SQL
  • To increase productivity when writing inline SQL using your favourite IDE's autocompletion capabilities
  • - +

    With jOOQ being in the core of your application, you want to be sure that you can trust jOOQ. That is why jOOQ is heavily unit and integration tested with a strong focus on integration tests:

    - +

    Unit tests

    Unit tests are performed against dummy JDBC interfaces using http://jmock.org/. These tests verify that various implementations render correct SQL and bind variables correctly.

    - +

    Integration tests

    This is the most important part of the jOOQ test suites. Some 1500 queries are currently run against a standard integration test database. Both the test database and the queries are translated into every one of the 14 supported SQL dialects to ensure that regressions are unlikely to be introduced into the code base. @@ -10873,17 +10873,17 @@ FROM t

    jOOQ integration tests run the weirdest and most unrealistic queries. As a side-effect of these extensive integration test suites, many corner-case bugs for JDBC drivers and/or open source databases have been discovered, feature requests submitted through jOOQ and reported mainly to CUBRID, Derby, H2, HSQLDB.

    - +

    Code generation tests

    For every one of the 14 supported integration test databases, source code is generated and the tiniest differences in generated source code can be discovered. In case of compilation errors in generated source code, new test tables/views/columns are added to avoid regressions in this field.

    - +

    API Usability tests and proofs of concept

    jOOQ is used in jOOQ-meta as a proof of concept. This includes complex queries such as the following Postgres query

    - + These rather complex queries show that the jOOQ API is fit for advanced SQL use-cases, compared to the rather simple, often unrealistic queries in the integration test suite.

    - +

    Clean API and implementation. Code is kept DRY

    As a general rule of thumb throughout the jOOQ code, everything is kept DRY. Some examples: @@ -10949,19 +10949,19 @@ for (Record record : create.select(

    - +
    Migrating to jOOQ 3.0

    This section is for all users of jOOQ 2.x who wish to upgrade to the next major release. In the next sub-sections, the most important changes are explained. Some code hints are also added to help you fix compilation errors.

    - +

    Type-safe row value expressions

    Support for has been added in jOOQ 2.6. In jOOQ 3.0, many API parts were thoroughly (but often incompatibly) changed, in order to provide you with even more type-safety.

    - +

    Here are some affected API parts:

    @@ -10971,11 +10971,11 @@ for (Record record : create.select(
  • IN predicates and comparison predicates taking subselects changed incompatibly
  • INSERT and MERGE statements now take typesafe VALUES() clauses
  • - +

    Some hints related to row value expressions:

    - + record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result> result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch(); @@ -10983,31 +10983,31 @@ Result> result = create.select(BOOK.TITLE, BOOK.ID).fro // But Record2 extends Record. You don't have to use the additional typesafety: Record record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch();]]> - +

    SelectQuery and SelectXXXStep are now generic

    In order to support type-safe row value expressions and type-safe Record[N] types, SelectQuery is now generic: SelectQuery<R>

    - +

    SimpleSelectQuery and SimpleSelectXXXStep API were removed

    The duplication of the SELECT API is no longer useful, now that SelectQuery and SelectXXXStep are generic.

    - +

    Factory was split into DSL (query building) and DSLContext (query execution)

    The pre-existing Factory class has been split into two parts:

    - +
    1. 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
    2. 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 renamed to DSLContext. An example:

    - + - +

    Quantified comparison predicates

    Field.equalAny(...) and similar methods have been removed in favour of Field.equal(any(...)). This greatly simplified the Field API. An example:

    - + > subselect = any(select(BOOK.ID).from(BOOK)); Condition condition = BOOK.ID.equal(subselect);]]> - +

    FieldProvider

    The FieldProvider marker interface was removed. Its methods still exist on FieldProvider subtypes. Note, they have changed names from getField() to field() and from getIndex() to indexOf()

    - +

    GroupField

    GroupField has been introduced as a DSL marker interface to denote fields that can be passed to GROUP BY clauses. This includes all org.jooq.Field types. However, fields obtained from ROLLUP(), CUBE(), and GROUPING SETS() functions no longer implement Field. Instead, they only implement GroupField. An example:

    - + field1a = Factory.rollup(...); // OK Field field2a = Factory.one(); // OK @@ -11053,19 +11053,19 @@ GroupField field1b = DSL.rollup(...); // OK Field field1c = DSL.rollup(...); // Compilation error GroupField field2b = DSL.one(); // OK Field field2c = DSL.one(); // OK]]> - +

    NULL predicate

    Beware! Previously, Field.equal(null) was translated internally to an IS NULL predicate. This is no longer the case. Binding Java "null" to a comparison predicate will result in a regular comparison predicate (which never returns true). This was changed for several reasons:

    - +
    • To most users, this was a surprising "feature".
    • Other predicates didn't behave in such a way, e.g. the IN predicate, the BETWEEN predicate, or the LIKE predicate.
    • Variable binding behaved unpredictably, as IS NULL predicates don't bind any variables.
    • The generated SQL depended on the possible combinations of bind values, which creates unnecessary hard-parses every time a new unique SQL statement is rendered.
    - +

    Here is an example how to check if a field has a given value, without applying SQL's ternary NULL logic:

    @@ -11078,7 +11078,7 @@ Condition condition1 = BOOK.TITLE.equal(possiblyNull); // jOOQ 3.0 Condition condition2 = BOOK.TITLE.equal(possiblyNull).or(BOOK.TITLE.isNull().and(val(possiblyNull).isNull())); Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    Configuration

    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 @@ -11092,7 +11092,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> In order to resolve confusion that used to arise because of different lifecycle durations, these types are now no longer formally connected through inheritance.

    - +

    ConnectionProvider

    In order to allow for simpler connection / data source management, jOOQ externalised connection handling in a new ConnectionProvider type. The previous two connection modes are maintained backwards-compatibly (JDBC standalone connection mode, pooled DataSource mode). Other connection modes can be injected using: @@ -11102,24 +11102,24 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    These are some side-effects of the above change

    - +
    • 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. This resolves many class loader issues that were encountered before. It also helps listener implementations control their lifecycles themselves.

    - +

    Data type API

    The data type API has been changed drastically in order to enable some new DataType-related features. These changes include: @@ -11129,16 +11129,16 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]>[SQLDialect]DataType and SQLDataType no longer implement DataType. They're mere constant containers

  • Various minor API changes have been done.
  • - +

    Object renames

    These objects have been moved / renamed:

    - +
    • jOOU: a library used to represent unsigned integer types was moved from org.jooq.util.unsigned to org.jooq.util.types (which already contained INTERVAL data types)
    - +

    Feature removals

    Here are some minor features that have been removed in jOOQ 3.0 @@ -11233,7 +11233,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> --> diff --git a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.2.xml b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.2.xml index 3ed062cdfe..2aefa29504 100644 --- a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.2.xml +++ b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.2.xml @@ -126,7 +126,7 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ's reason for being - compared to SQL / JDBC

    So why not just use SQL? @@ -149,14 +149,14 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ is different

    SQL was never meant to be abstracted. To be confined in the narrow boundaries of heavy mappers, hiding the beauty and simplicity of relational data. SQL was never meant to be object-oriented. SQL was never meant to be anything other than... SQL!

    - + - +
    Getting started with jOOQ @@ -337,12 +337,12 @@ limitations under the License.

    This section helps you correctly interpret this manual in the context of jOOQ.

    - +

    Code blocks

    The following are code blocks:

    - + @@ -358,7 +358,7 @@ org.jooq.property=value]]>

    These are useful to provide examples in code. Often, with jOOQ, it is even more useful to compare SQL code with its corresponding Java/jOOQ code. When this is done, the blocks are aligned side-by-side, with SQL usually being on the left, and an equivalent jOOQ DSL query in Java usually being on the right:

    - + @@ -370,17 +370,17 @@ create.selectOne()]]>

    The contents of code blocks follow conventions, too. If nothing else is mentioned next to any given code block, then the following can be assumed:

    - - + + - +

    Your naming may differ, of course. For instance, you could name the "create" instance "db", instead.

    - +

    Execution

    - +

    When you're coding PL/SQL, T-SQL or some other procedural SQL language, SQL statements are always executed immediately at the semi-colon. This is not the case in jOOQ, because as an internal DSL, jOOQ can never be sure that your statement is complete until you call fetch() or execute(). The manual tries to apply fetch() and execute() as thoroughly as possible. If not, it is implied:

    @@ -420,7 +420,7 @@ create.update(T).set(T.V, 1).execute();]]>

    jOOQ allows to override runtime behaviour using . If nothing is specified, the default runtime settings are assumed.

    - +

    Sample database

    jOOQ query examples run against the sample database. See the manual's section about to learn more about the sample database. @@ -455,7 +455,7 @@ CREATE TABLE book ( title VARCHAR2(400) NOT NULL, published_in NUMBER(7) NOT NULL, language_id NUMBER(7) NOT NULL, - + CONSTRAINT fk_book_author FOREIGN KEY (author_id) REFERENCES author(id), CONSTRAINT fk_book_language FOREIGN KEY (language_id) REFERENCES language(id) ); @@ -468,7 +468,7 @@ CREATE TABLE book_to_book_store ( name VARCHAR2(400) NOT NULL, book_id INTEGER NOT NULL, stock INTEGER, - + PRIMARY KEY(name, book_id), CONSTRAINT fk_b2bs_book_store FOREIGN KEY (name) REFERENCES book_store (name) ON DELETE CASCADE, CONSTRAINT fk_b2bs_book FOREIGN KEY (book_id) REFERENCES book (id) ON DELETE CASCADE @@ -479,7 +479,7 @@ CREATE TABLE book_to_book_store (

    In addition to the above, you may assume the following sample data:

    - + Effectively, jOOQ was originally designed to replace any other database abstraction framework short of the ones handling connection pooling and transaction management (see also the )

    - +

    Use jOOQ the way you prefer

    ... but open source is community-driven. And the community has shown various ways of using jOOQ that diverge from its original intent. Some use cases encountered are: @@ -538,7 +538,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]>Using jOOQ for SQL building and Spring Data for SQL execution

  • Using jOOQ without the to build the basis of a framework for dynamic SQL execution.
  • - +

    The following sections explain about various use cases for using jOOQ in your application.

    @@ -551,7 +551,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]> This is the most simple of all use cases, allowing for construction of valid SQL for any database. In this use case, you will not use and probably not even . Instead, you'll use to wrap strings, literals and other user-defined objects into an object-oriented, type-safe AST modelling your SQL statements. An example is given here:

    - + - +

    The SQL string built with the jOOQ query DSL can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools (note that since jOOQ uses PreparedStatement by default, this will generate a bind variable for "1948". ).

    @@ -588,7 +588,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID)) .where(BOOK.PUBLISHED_IN.equal(1948)) .getSQL();]]> - +

    The SQL string that you can generate as such can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools.

    @@ -608,7 +608,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    Instead of any tool mentioned in the previous chapters, you can also use jOOQ directly to execute your jOOQ-generated SQL statements. This will add a lot of convenience on top of the previously discussed API for typesafe SQL construction, when you can re-use the information from generated classes to fetch records and custom data types. An example is given here:

    - + > result = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) @@ -662,10 +662,10 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { // Skip previously distinguished authors if ((int) author.getDistinguished() == 1) continue; - + // Check if the author has written more than 5 books if (author.fetchChildren(Keys.FK_BOOK_AUTHOR).size() > 5) { - + // Mark the author as a "distinguished" author author.setDistinguished(1); author.store(); @@ -682,7 +682,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {
    - +
    jOOQ for PROs @@ -720,7 +720,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { This manual section is intended for new users, to help them get a running application with jOOQ, quickly.

    - +
    Step 1: Preparation @@ -729,7 +729,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { If you haven't already downloaded it, download jOOQ:
    http://www.jooq.org/download

    - +

    Alternatively, you can create a Maven dependency to download jOOQ artefacts:

    @@ -752,7 +752,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    Note that only the jOOQ Open Source Edition is available from Maven Central. If you're using the jOOQ Professional Edition or the jOOQ Enterprise Edition, you will have to manually install jOOQ in your local Nexus, or in your local Maven cache. For more information, please refer to the licensing pages.

    - +

    Please refer to the manual's section about to learn how to use jOOQ's code generator with Maven.

    @@ -767,14 +767,14 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    - +
    Step 2: Your database

    We're going to create a database called "library" and a corresponding "author" table. Connect to MySQL via your command line client and type the following:

    - + CREATE DATABASE `library`; USE `library`; @@ -788,7 +788,7 @@ CREATE TABLE `author` (
    - +
    Step 3: Code generation @@ -800,7 +800,7 @@ CREATE TABLE `author` (

    The easiest way to generate a schema is to copy the jOOQ jar files (there should be 3) and the MySQL Connector jar file to a temporary directory. Then, create a library.xml that looks like this:

    - + @@ -854,7 +854,7 @@ CREATE TABLE `author` (

    generator.target.directory - the directory to output to.

    - +

    Once you have the JAR files and library.xml in your temp directory, type this on a Windows machine:

    @@ -874,12 +874,12 @@ CREATE TABLE `author` (

    There are two things to note:

    - +
    1. The prefix slash before the /library.xml. Even though it's in our working directory, we need to prepend a slash, as the configuration file is loaded from the classpath.
    2. The "trailing" period in the classpath: .. We need this because we want the current directory on the classpath in order to find the above /library.xml file at the root of your classpath.
    - +

    Replace the filenames with your actual filenames. In this example, jOOQ {jooq-version} is being used. If everything has worked, you should see this in your console output:

    @@ -941,17 +941,17 @@ INFO: Packages fetched : 0 (0 included, 0 excluded) Nov 1, 2011 7:25:08 PM org.jooq.impl.JooqLogger info INFO: GENERATION FINISHED! : Total: 791.688ms, +9.143ms - +
    - +
    Step 4: Connect to your database

    Let's just write a vanilla main class in the project containing the generated classes:

    - +
    - +
    Step 5: Querying

    Let's add a simple query constructed with jOOQ's query DSL:

    - + result = create.select().from(AUTHOR).fetch();]]> @@ -1001,7 +1001,7 @@ Result result = create.select().from(AUTHOR).fetch();]]>

    - +
    Step 6: Iterating @@ -1020,7 +1020,7 @@ Result result = create.select().from(AUTHOR).fetch();]]>

    The full program should now look like this:

    - +
    - +
    Step 7: Explore! @@ -1109,15 +1109,15 @@ public class Main {
  • Spring TX as the transaction management library.
  • jOOQ as the and library.
  • - +

    The complete example can also be downloaded from GitHub. Another, excellent tutorial by Petri Kainulainen can be found here.

    - +

    The following steps show how to integrate the libraries.

    - +

    Add the required Maven dependencies

    For this example, we'll create the following Maven dependencies @@ -1196,7 +1196,7 @@ public class Main {

    The above dependencies are configured together using a Spring Beans configuration:

    - + - + - + @@ -1259,7 +1259,7 @@ public class Main { - + ]]> @@ -1310,7 +1310,7 @@ public class QueryTest {

    The following example shows how you can use Spring's TransactionManager to explicitly handle transactions:

    - +
    - +
    jOOQ and Scala @@ -1425,7 +1425,7 @@ public class TransactionTest {
  • Optioanl ";" at the end of a Scala statement
  • Type inference using "var" and "val" keywords
  • - +

    But jOOQ also leverages other useful Scala features, such as

    @@ -1433,15 +1433,15 @@ public class TransactionTest {
  • implicit defs for operator overloading
  • Scala Macros (soon to come)
  • - +

    All of the above heavily improve jOOQ's querying DSL API experience for Scala developers.

    - +

    A short example jOOQ application in Scala might look like this:

    - +
    - +
    jOOQ and NoSQL @@ -1506,7 +1506,7 @@ object Test { //

    - +
    Dependencies @@ -1524,7 +1524,7 @@ object Test { //
    - +
    Build your own @@ -1553,7 +1553,7 @@ object Test { //
    - +
    jOOQ and backwards-compatibility @@ -1565,7 +1565,7 @@ object Test { //
  • If a minor release includes backwards-compatible, API-relevant new features, [Y] is incremented by one and [Z] is reset to zero.
  • If a major release includes backwards-incompatible, API-relevant new features, [X] is incremented by one and [Y], [Z] are reset to zero.
  • - +

    jOOQ's understanding of backwards-compatibility

    Backwards-compatibility is important to jOOQ. You've chosen jOOQ as a strategic SQL engine and you don't want your SQL to break. That is why there is at most one major release per year, which changes only those parts of jOOQ's API and functionality, which were agreed upon on the user group. During the year, only minor releases are shipped, adding new features in a backwards-compatible way @@ -1578,15 +1578,15 @@ object Test { //

  • Overloading methods for convenience
  • Changing the type hierarchy of interfaces
  • - +

    It becomes obvious that it would be impossible to add new language elements (e.g. new , new ) to the API without breaking any client code that actually implements those interfaces. Hence, the following rule should be observed:

    - +

    jOOQ's DSL interfaces should not be implemented by client code! Extend only those extension points that are explicitly documented as "extendable" (e.g. )

    - +

    jOOQ-codegen and jOOQ-meta

    While a reasonable amount of care is spent to maintain these two modules under the rules of semantic versioning, it may well be that minor releases introduce backwards-incompatible changes. This will be announced in the respective release notes and should be the exception. @@ -1614,7 +1614,7 @@ object Test { // - +

    The query DSL type @@ -1645,7 +1645,7 @@ object Test { // // ... which is in fact the same as: DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    DSL subclasses @@ -1664,7 +1664,7 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME));
    - + @@ -1673,14 +1673,14 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    The DSLContext class

    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.

    - +

    Fluent creation of a DSLContext object

    The DSLContext object can be created fluently from the : @@ -1695,7 +1695,7 @@ DSLContext create = DSL.using(connection, dialect);]]>

    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

    A Configuration can be supplied with these objects: @@ -1714,7 +1714,7 @@ DSLContext create = DSL.using(connection, dialect);]]> - +

    Wrapping a Configuration object, a DSLContext can construct , for later . An example is given here:

    @@ -1756,7 +1756,7 @@ DSL.using(connection, dialect) CONNECT BY clause to the query */ -@Support({ SQLDialect.CUBRID, SQLDialect.}) +@Support({ SQLDialect.CUBRID, SQLDialect.ORACLE }) SelectConnectByConditionStep connectBy(Condition condition);]]>

    @@ -1778,7 +1778,7 @@ SelectSelectStep select(Field... fields);]]>

    Nevertheless, the IS DISTINCT FROM predicate is supported by jOOQ in all dialects, as its semantics can be expressed with an equivalent . For more details, see the manual's section about the .

    - +

    jOOQ and the Oracle SQL dialect

    Oracle SQL is much more expressive than many other SQL dialects. It features many unique keywords, clauses and functions that are out of scope for the SQL standard. Some examples for this are @@ -1802,13 +1802,13 @@ SelectSelectStep select(Field... fields);]]>

    In jOOQ 3.1, the notion of a SQLDialect.family() was introduced, in order to group several similar into a common family. An example for this is SQL Server, which is supported by jOOQ in various versions:

    - +
    • : The "version-less" SQL Server version. This always maps to the latest supported version of SQL Server
    • : The SQL Server version 2012
    • : The SQL Server version 2008
    - +

    In the above list, SQLSERVER is both a dialect and a family of three dialects. This distinction is used internally by jOOQ to distinguish whether to use the clause (SQL Server 2012), or whether to emulate it using ROW_NUMBER() OVER() (SQL Server 2008).

    @@ -1825,7 +1825,7 @@ SelectSelectStep select(Field... fields);]]>

    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.

    - +

    Interact with JDBC DataSources

    If you're in a J2EE or Spring context, however, you may wish to use a instead. Connections obtained from such a DataSource will be closed after query execution by jOOQ. The semantics of such a close operation should be the returning of the connection into a connection pool, not the actual closing of the underlying connection. Typically, this makes sense in an environment using distributed JTA transactions. An example of using DataSources with jOOQ can be seen in the tutorial section about . @@ -1833,17 +1833,17 @@ SelectSelectStep select(Field... fields);]]>

    Note, in this case, jOOQ will internally use a , which you can reference directly if you prefer that.

    - +

    Inject custom behaviour

    If your specific environment works differently from any of the above approaches, you can inject your own custom implementation of a ConnectionProvider into jOOQ. This is the API contract you have to fulfil:

    - + @@ -1853,19 +1853,19 @@ 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...

    - +
    - +

    Here is an example of how to use the custom data API. Let's assume that you have written an , that prevents INSERT statements, when a given flag is set to true:

    @@ -1875,10 +1875,10 @@ public class NoInsertListener extends DefaultExecuteListener { @Override public void start(ExecuteContext ctx) { - + // This listener is active only, when your custom flag is set to true 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) { throw new DataAccessException("No INSERT statements allowed"); @@ -1889,11 +1889,11 @@ public class NoInsertListener extends DefaultExecuteListener {

    See the manual's section about to learn more about how to implement an ExecuteListener.

    - +

    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:

    - + ExecuteListeners are a useful tool to...

    - +
    • implement custom logging
    • apply triggers written in Java
    • collect query execution statistics
    - +

    ExecuteListeners are hooked into your by returning them from an :

    @@ -1951,7 +1951,7 @@ configuration.set( new DefaultExecuteListenerProvider(new PerformanceLoggingListener()), new DefaultExecuteListenerProvider(new NoInsertListener()) );]]>
    - +

    See the manual's section about to see examples of such listener implementations.

    @@ -1998,7 +1998,7 @@ DSLContext create = DSL.using(connection, dialect, settings);]]>

    - +
    Runtime schema and table mapping @@ -2006,7 +2006,7 @@ DSLContext create = DSL.using(connection, dialect, settings);]]>

    You may wish to design your database in a way that you have several instances of your schema. This is useful when you want to cleanly separate data belonging to several customers / organisation units / branches / users and put each of those entities' data in a separate database or schema.

    - +

    In our AUTHOR example this would mean that you provide a book reference database to several companies, such as My Book World and Books R Us. In that case, you'll probably have a schema setup like this:

    @@ -2036,7 +2036,7 @@ create.selectFrom(AUTHOR).fetch();

    The query executed with a Configuration equipped with the above mapping will in fact produce this SQL statement:

    - + SELECT * FROM MY_BOOK_WORLD.AUTHOR

    Even if AUTHOR was generated from DEV. @@ -2111,7 +2111,7 @@ create.selectFrom(AUTHOR).fetch();

    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

    @@ -2145,7 +2145,7 @@ create.selectFrom(AUTHOR).fetch();

    Here is an example to illustrate what that means:

    - + 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) @@ -2217,7 +2217,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); @@ -2244,7 +2244,7 @@ query.addJoin(BOOK, BOOK.AUTHOR_ID.equal(AUTHOR.ID));]]>

    Note, that for historic reasons, the DSL API mixes mutable and immutable behaviour with respect to the internal representation of the being constructed. While creating , (such as functions) assumes immutable behaviour, creating does not. In other words, the following can be said:

    - + select2 = create.selectOne();]]>

    jOOQ does not explicitly support the asterisk operator in projections. However, you can omit the projection as in these examples:

    - +

    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:

    - + select(Collection> fields); public static SelectSelectStep select(Field... fields); @@ -2424,14 +2424,14 @@ public static SelectSelectStep> select(Field SelectSelectStep> select(Field field1, Field field2); public static SelectSelectStep> select(Field field1, Field field2, Field field3); // [...]]]> - +

    Since the generic R type is bound to some , the associated T type information can be used in various other contexts, e.g. the . Such a SELECT statement can be assigned typesafely:

    > s1 = create.select(BOOK.ID, BOOK.TITLE); Select> s2 = create.select(BOOK.ID, trim(BOOK.TITLE));]]> - +

    For more information about typesafe record types with degree up to {max-row-degree}, see the manual's section about .

    @@ -2457,7 +2457,7 @@ create.selectOne().from(BOOK.as("b"), AUTHOR.as("a"));]]>

    Read more about aliasing in the manual's section about .

    - +

    More advanced table expressions

    Apart from simple tables, you can pass any arbitrary to the jOOQ FROM clause. This may include in Oracle: @@ -2737,12 +2737,12 @@ ORDER BY 1]]>

    Note that this syntax is also supported in the CUBRID database and might be emulated in other dialects supporting common table expressions in the future.

    - +

    ORDER SIBLINGS

    The Oracle database allows for specifying a SIBLINGS keyword in the . Instead of ordering the overall result, this will only order siblings among each other, keeping the hierarchy intact. An example is given here:

    - + .startWith(DIRECTORY.PARENT_ID.isNull()) .orderSiblingsBy(1);]]> - +
    @@ -2782,7 +2782,7 @@ GROUP BY AUTHOR_ID]]>

    Note, as defined in the SQL standard, when grouping, you may no longer project any columns that are not a formal part of the GROUP BY clause, or .

    - +

    MySQL's deviation from the SQL standard

    MySQL has a peculiar way of not adhering to this standard behaviour. This is documented in the MySQL manual. In short, with MySQL, you can also project any other field that is not part of the GROUP BY clause. The projected values will just be arbitrary values from within the group. You cannot rely on any ordering. For example: @@ -2813,7 +2813,7 @@ GROUP BY ()]]> .from(BOOK) .groupBy();]]> - +

    ROLLUP(), CUBE() and GROUPING SETS()

    Some databases support the SQL standard grouping functions and some extensions thereof. See the manual's section about for more details. @@ -2833,7 +2833,7 @@ GROUP BY ()]]> FROM BOOK GROUP BY AUTHOR_ID HAVING COUNT(*) >= 2]]> - @@ -2972,8 +2972,8 @@ ORDER BY CASE TITLE

    The SQL standard defines that a "query expression" can be ordered, and that query expressions can contain , whose subqueries cannot be ordered. While this is defined as such in the SQL standard, many databases allowing for the non-standard in one way or another, do not adhere to this part of the SQL standard. Hence, jOOQ allows for ordering all SELECT statements, regardless whether they are constructed as a part of a UNION or not. Corner-cases are handled internally by jOOQ, by introducing synthetic subselects to adhere to the correct syntax, where this is needed.

    - - + +

    Oracle's ORDER SIBLINGS BY clause

    jOOQ also supports Oracle's SIBLINGS keyword to be used with ORDER BY clauses for @@ -3022,7 +3022,7 @@ SELECT TOP 1 * FROM BOOK

    Things get a little more tricky in those databases that have no native idiom for OFFSET pagination (actual queries may vary):

    - + 1]]>

    As you can see, jOOQ will take care of the incredibly painful ROW_NUMBER() OVER() (or ROWNUM for Oracle) filtering in subselects for you, you'll just have to write limit(1).offset(2) in any dialect.

    - +

    Side-note: If you're interested in understanding why we chose ROWNUM for Oracle, please refer to this very interesting benchmark, comparing the different approaches of doing pagination in Oracle: http://www.inf.unideb.hu/~gabora/pagination/results.html.

    @@ -3170,7 +3170,7 @@ SELECT * FROM author ORDER BY id DESC;]]>

    SQL allows to perform set operations as understood in standard set theory on result sets. These operations include unions, intersections, subtractions. For two subselects to be combinable by such a set operator, each subselect must return a of the same degree and type.

    - +

    UNION and UNION ALL

    These operators combine two results into one. While UNION removes all duplicate records resulting from this combination, UNION ALL leaves subselect results as they are. Typically, you should prefer UNION ALL over UNION, if you don't really need to remove duplicates. The following example shows how to use such a UNION operation in jOOQ. @@ -3183,12 +3183,12 @@ SELECT * FROM BOOK WHERE ID = 5]]> - +

    INTERSECT [ ALL ] and EXCEPT [ ALL ]

    INTERSECT is the operation that produces only those values that are returned by both subselects. EXCEPT is the operation that returns only those values that are returned exclusively in the first subselect. Both operators will remove duplicates from their results. The SQL standard allows to specify the ALL keyword for both of these operators as well, but this is hardly supported in any database. jOOQ does not support INTERSECT ALL, EXEPT ALL operations either.

    - +

    jOOQ's set operators and how they're different from standard SQL

    As previously mentioned in the manual's section about the , jOOQ has slightly changed the semantics of these set operators. While in SQL, a subselect may not contain any or (unless you wrap the subselect into a ), jOOQ allows you to do so. In order to select both the youngest and the oldest author from the database, you can issue the following statement with jOOQ (rendered to the MySQL dialect): @@ -3205,12 +3205,12 @@ UNION .union( create.selectFrom(AUTHOR) .orderBy(AUTHOR.DATE_OF_BIRTH.desc()).limit(1));]]> - +

    Projection typesafety for degrees between 1 and {max-row-degree}

    Two subselects that are combined by a set operator are required to be of the same degree and, in most databases, also of the same type. jOOQ 3.0's introduction of helps compile-checking these constraints:

    - + > s1 = select(BOOK.ID, BOOK.TITLE).from(BOOK); Select> s2 = selectOne(); @@ -3245,7 +3245,7 @@ s1.union(s4); // OK. The two Record[N] types match]]>

    Note that you can pass any string in the .hint() clause. If you use that clause, the passed string will always be put in between the SELECT [DISTINCT] keywords and the actual projection list. This can be useful in other databases too, such as MySQL, for instance:

    - +
    - +
    Lexical and logical SELECT clause order

    SQL has a lexical and a logical order of SELECT clauses. The lexical order of SELECT clauses is inspired by the English language. As SQL statements are commands for the database, it is natural to express a statement in an imperative tense, such as "SELECT this and that!".

    - +

    Logical SELECT clause order

    The logical order of SELECT clauses, however, does not correspond to the syntax. In fact, the logical order is this:

    - +
    • : First, all data sources are defined and joined
    • : Then, data is filtered as early as possible
    • @@ -3281,11 +3281,11 @@ FROM table1
    • : Then, a paging view is created for the ordered tuples
    • : Finally, pessimistic locking is applied
    - +

    The SQL Server documentation also explains this, with slightly different clauses:

    - +
    • FROM
    • ON
    • @@ -3299,16 +3299,16 @@ FROM table1
    • ORDER BY
    • TOP
    - +

    As can be seen, databases have to logically reorder a SQL statement in order to determine the best execution plan.

    - +

    Alternative syntaxes: LINQ, SLICK

    Some "higher-level" abstractions, such as C#'s LINQ or Scala's SLICK try to inverse the lexical order of SELECT clauses to what appears to be closer to the logical order. The obvious advantage of moving the SELECT clause to the end is the fact that the projection type, which is the record type returned by the SELECT statement can be re-used more easily in the target environment of the internal domain specific language.

    - +

    A LINQ example:

    @@ -3321,11 +3321,11 @@ Where p.UnitsInStock <= p.ReorderLevel AndAlso Not p.Discontinued // SELECT clause Select p]]> - +

    A SLICK example:

    - + .set(AUTHOR.ID, 101) .set(AUTHOR.FIRST_NAME, "Alfred") .set(AUTHOR.LAST_NAME, "Döblin"); - +

    As you can see, this syntax is a bit more verbose, but also more readable, as every field can be matched with its value. Internally, the two syntaxes are strictly equivalent.

    @@ -3424,7 +3424,7 @@ SELECT 101, 'Alfred', 'Döblin' FROM DUAL;

    The MySQL database supports a very convenient way to INSERT or UPDATE a record. This is a non-standard extension to the SQL syntax, which is supported by jOOQ and emulated in other RDBMS, where this is possible (i.e. if they support the SQL standard ). Here is an example how to use the ON DUPLICATE KEY UPDATE clause:

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, update the author's name create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -3433,11 +3433,11 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .set(AUTHOR.LAST_NAME, "Koontz");

    The synthetic ON DUPLICATE KEY IGNORE clause

    - +

    The MySQL database also supports an INSERT IGNORE INTO clause. This is supported by jOOQ using the more convenient SQL syntax variant of ON DUPLICATE KEY IGNORE, which can be equally emulated in other databases using a :

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, ignore the INSERT statement create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -3473,14 +3473,14 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    The INSERT SELECT statement

    - +

    In some occasions, you may prefer the INSERT SELECT syntax, for instance, when you copy records from one table to another:

    - + create.insertInto(AUTHOR_ARCHIVE) .select(create.selectFrom(AUTHOR).where(AUTHOR.DECEASED.isTrue())); - +
    @@ -3528,7 +3528,7 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    jOOQ supports formal in various contexts, among which the UPDATE statement. Only one row value expression can be updated at a time. Here's an example:

    - + UPDATE AUTHOR SET (FIRST_NAME, LAST_NAME) = @@ -3564,12 +3564,12 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    The above row value expressions usages are completely typesafe.

    - +

    UPDATE .. RETURNING

    The Firebird and Postgres databases support a RETURNING clause on their UPDATE statements, similar as the RETURNING clause in . This is useful to fetch trigger-generated values in one go. An example is given here:

    - +

    The H2 database ships with a somewhat less powerful but a little more intuitive syntax for its own version of the MERGE statement. An example more or less equivalent to the previous one can be seen here:

    - + -- Check if there is already an author called 'Hitchcock' -- If there is, rename him to John. If there isn't add him. @@ -3658,7 +3658,7 @@ VALUES ('John', 'Hitchcock') This syntax can be fully emulated by jOOQ for all other databases that support the SQL standard MERGE statement. For more information about the H2 MERGE syntax, see the documentation here:
    http://www.h2database.com/html/grammar.html#merge

    - +

    Typesafety of VALUES() for degrees up to {max-row-degree}

    Much like the , the MERGE statement's VALUES() clause provides typesafety for degrees up to {max-row-degree}, in both the standard syntax variant as well as the H2 variant. @@ -3680,7 +3680,7 @@ VALUES ('John', 'Hitchcock') TRUNCATE TABLE AUTHOR; create.truncate(AUTHOR).execute(); - +

    TRUNCATE is not supported by Ingres and SQLite. jOOQ will execute a DELETE FROM AUTHOR statement instead.

    @@ -3704,7 +3704,7 @@ VALUES ('John', 'Hitchcock')

    Most of the times, when thinking about a you're probably thinking about an actual table in your database schema. If you're using jOOQ's , you will have all tables from your database schema available to you as type safe Java objects. You can then use these tables in SQL , or in other , just like any other table expression. An example is given here:

    - + .from(AUTHOR) // Table expression AUTHOR .join(BOOK) // Table expression BOOK .on(AUTHOR.ID.equal(BOOK.AUTHOR_ID));]]> - +

    The above example shows how AUTHOR and BOOK tables are joined in a . It also shows how you can access by dereferencing the relevant Java attributes of their tables.

    @@ -3753,11 +3753,11 @@ create.select() .where(a.YEAR_OF_BIRTH.greaterThan(1920) .and(a.FIRST_NAME.equal("Paulo"))) .orderBy(b.TITLE);]]>
    - +

    As you can see in the above example, calling as() on generated tables returns an object of the same type as the table. This means that the resulting object can be used to dereference fields from the aliased table. This is quite powerful in terms of having your Java compiler check the syntax of your SQL statements. If you remove a column from a table, dereferencing that column from that table alias will cause compilation errors.

    - +

    Dereferencing columns from other table expressions

    Only few table expressions provide the SQL syntax typesafety as shown above, where generated tables are used. Most tables, however, expose their fields through field() methods: @@ -3769,12 +3769,12 @@ Table a = AUTHOR.as("a"); // Get fields from a: Field id = a.field("ID"); Field firstName = a.field("FIRST_NAME");]]> - +

    Derived column lists

    The SQL standard specifies how a table can be renamed / aliased in one go along with its columns. It references the term "derived column list" for the following syntax (as supported by Postgres, for instance):

    - + In jOOQ, you would simply specify a varargs list of column aliases as such:

    - + The that can be used in are the most powerful and best supported means of creating new in SQL. Informally, the following can be said:

    - + A(colA1, ..., colAn) "join" B(colB1, ..., colBm) "produces" C(colA1, ..., colAn, colB1, ..., colBm)

    @@ -3848,7 +3848,7 @@ create.select().from(values(

    jOOQ supports all of these JOIN types (except semi-join and anti-join) directly on any :

    - + table) @@ -3886,7 +3886,7 @@ Table naturalRightOuterJoin(TableLike)]]>

    Some databases allow for expressing in-memory temporary tables using a VALUES() constructor. This constructor usually works the same way as the VALUES() clause known from the or from the . With jOOQ, you can also use the VALUES() table constructor, to create tables that can be used in a :

    - + Note, that it is usually quite useful to provide column aliases ("derived column lists") along with the table alias for the VALUES() constructor.

    - +

    The above statement is emulated by jOOQ for those databases that do not support the VALUES() constructor, natively (actual emulations may vary):

    - + A can appear almost anywhere a can. Such a "nested SELECT" is often called a "derived table". Apart from many convenience methods accepting objects directly, a SELECT statement can always be transformed into a object using the asTable() method.

    - +

    Example: Scalar subquery

    - + SELECT * FROM BOOK @@ -4004,11 +4004,11 @@ create.select(AUTHOR.ID, books)

    If you are closely coupling your application to an Oracle database, you can take advantage of some Oracle-specific features, such as the PIVOT clause, used for statistical analyses. The formal syntax definition is as follows:

    - + -- SELECT .. FROM table PIVOT (aggregateFunction [, aggregateFunction] FOR column IN (expression [, expression])) -- WHERE .. - +

    The PIVOT clause is available from the type, as pivoting is done directly on a table. Currently, only Oracle's PIVOT clause is supported. Support for SQL Server's slightly different PIVOT clause will be added later. Also, jOOQ may emulate PIVOT for other dialects in the future.

    @@ -4071,7 +4071,7 @@ WHERE NOT EXISTS (

    The SQL standard specifies how SQL databases should implement ARRAY and TABLE types, as well as CURSOR types. Put simply, a CURSOR is a pointer to any materialised . Depending on the cursor's features, this table expression can be scrolled through in both directions, records can be locked, updated, removed, inserted, etc. Often, CURSOR types contain s, whereas ARRAY and TABLE types contain simple scalar values, although that is not a requirement

    - +

    ARRAY types in SQL are similar to Java's array types. They contain a "component type" or "element type" and a "dimension". This sort of ARRAY type is implemented in H2, HSQLDB and Postgres and supported by jOOQ as such. Oracle uses strongly-typed arrays, which means that an ARRAY type (VARRAY or TABLE type) has a name and possibly a maximum capacity associated with it.

    @@ -4154,12 +4154,12 @@ DSL.using(SQLDialect.SYBASE ).selectOne().getSQL();]]>

    Column expressions can be used in various SQL clauses in order to refer to one or several columns. This chapter explains how to form various types of column expressions with jOOQ. A particular type of column expression is given in the section about , where an expression may have a degree of more than one.

    - +

    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:

    - + field1 = BOOK.TITLE; @@ -4213,7 +4213,7 @@ ORDER BY BOOK.TITLE]]>

    Just like , columns can be renamed using aliases. Here is an example:

    - + SELECT FIRST_NAME || ' ' || LAST_NAME author, COUNT(*) books FROM AUTHOR JOIN BOOK ON AUTHOR.ID = AUTHOR_ID @@ -4222,21 +4222,21 @@ GROUP BY FIRST_NAME, LAST_NAME;

    Here is how it's done with jOOQ:

    - + Record record = create.select( concat(AUTHOR.FIRST_NAME, val(" "), AUTHOR.LAST_NAME).as("author"), count().as("books")) .from(AUTHOR) .join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID)) .groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME).fetchAny(); - +

    When you alias Fields like above, you can access those Fields' values using the alias name:

    - + System.out.println("Author : " + record.getValue("author")); System.out.println("Books : " + record.getValue("books")); - +
    @@ -4249,7 +4249,7 @@ System.out.println("Books : " + record.getValue("books"));

    Sometimes, this automatic mapping might not be what you needed, or jOOQ cannot know the type of a field. In those cases you would write SQL type CAST like this:

    - + -- Let's say, your Postgres column LAST_NAME was VARCHAR(30) -- Then you could do this: SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL @@ -4257,27 +4257,27 @@ SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL

    in jOOQ, you can write something like that:

    - + create.select(TAuthor.LAST_NAME.cast(PostgresDataType.TEXT));

    The same thing can be achieved by casting a Field directly to String.class, as TEXT is the default data type in Postgres to map to Java's String

    - + create.select(TAuthor.LAST_NAME.cast(String.class)); - +

    The complete CAST API in consists of these three methods:

    - + { // Cast this field to the type of another field Field cast(Field field); - + // Cast this field to a given DataType Field cast(DataType type); - + // Cast this field to the default DataType for a given Class Field cast(Class type); } @@ -4300,14 +4300,14 @@ public class DSL {

    A slightly different use case than are data type coercions, which are not rendered through to generated SQL. Sometimes, you may want to pretend that a numeric value is really treated as a string value, for instance when binding a numeric :

    - + field1 = val(1).coerce(String.class); Field field2 = val("1").coerce(Integer.class);]]>

    In the above example, field1 will be treated by jOOQ as a Field<String>, binding the numeric literal 1 as a VARCHAR value. The same applies to field2, whose string literal "1" will be bound as an INTEGER value.

    - +

    This technique is better than performing unsafe or rawtype casting in Java, if you cannot access the "right" field type from any given expression.

    @@ -4327,15 +4327,15 @@ Field field2 = val("1").coerce(Integer.class);]]>

    In order to express a SQL query like this one:

    - + SELECT ((1 + 2) * (5 - 3) / 2) % 10 FROM DUAL - +

    You can write something like this in jOOQ:

    - + create.select(val(1).add(2).mul(val(5).sub(3)).div(2).mod(10)); - +

    Operator precedence

    jOOQ does not know any operator precedence (see also ). All operations are evaluated from left to right, as with any object-oriented API. The two following expressions are the same: @@ -4363,14 +4363,14 @@ Field field2 = val("1").coerce(Integer.class);]]>

    - +
    String concatenation

    The SQL standard defines the concatenation operator to be an infix operator, similar to the ones we've seen in the chapter about . This operator looks like this: ||. Some other dialects do not support this operator, but expect a concat() function, instead. jOOQ renders the right operator / function, depending on your :

    - + SELECT 'A' || 'B' || 'C' FROM DUAL -- Or in MySQL: @@ -4398,13 +4398,13 @@ create.select(concat("A", "B", "C"));
  • NVL: Get the first non-null value among two arguments.
  • NVL2: Get the second argument if the first is null, or the third argument, otherwise.
  • - +

    Please refer to the for more details.

    - +
    Numeric functions @@ -4414,7 +4414,7 @@ create.select(concat("A", "B", "C"));

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ABS: Get the absolute value of a value.
    • ACOS: Get the arc cosine of a value.
    • @@ -4445,7 +4445,7 @@ create.select(concat("A", "B", "C"));
    • TANH: Get the hyperbolic tangent of a value.
    • TRUNC: Truncate the decimals off a given value.
    - +

    Please refer to the for more details.

    @@ -4470,13 +4470,13 @@ create.select(concat("A", "B", "C"));
  • SHL: Shift bits to the left
  • SHR: Shift bits to the right
  • - +

    Some background about bitwise operation emulation

    As stated before, not all databases support all of these bitwise operations. jOOQ emulates them wherever this is possible. More details can be seen in this blog post:
    http://blog.jooq.org/2011/10/30/the-comprehensive-sql-bitwise-operations-compatibility-list/

    - +
    @@ -4489,7 +4489,7 @@ create.select(concat("A", "B", "C"));

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ASCII: Get the ASCII code of a character.
    • BIT_LENGTH: Get the length of a string in bits.
    • @@ -4510,16 +4510,16 @@ create.select(concat("A", "B", "C"));
    • TRIM: Trim a string on both sides.
    • UPPER: Get a string in upper case letters.
    - +

    Please refer to the for more details.

    - +

    Regular expressions, REGEXP, REGEXP_LIKE, etc.

    Various databases have some means of searching through columns using regular expressions if the does not provide sufficient pattern matching power. While there are many different functions and operators in the various databases, jOOQ settled for the SQL:2008 standard REGEX_LIKE operator. Being an operator (and not a function), you should use the corresponding method on :

    - +

    @@ -4528,7 +4528,7 @@ create.select(concat("A", "B", "C")); - +

    Case sensitivity with strings @@ -4541,20 +4541,20 @@ create.select(concat("A", "B", "C"));

    For these ad-hoc ordering use-cases, most people resort to using LOWER() or UPPER() as follows:

    - + -- Case-insensitive filtering: -SELECT * FROM BOOK +SELECT * FROM BOOK WHERE upper(TITLE) = 'ANIMAL FARM' -- Case-insensitive ordering: -SELECT * +SELECT * FROM AUTHOR ORDER BY upper(FIRST_NAME), upper(LAST_NAME) // Case-insensitive filtering: create.selectFrom(BOOK) .where(upper(BOOK.TITLE).eq("ANIMAL FARM")).fetch(); - + // Case-insensitive ordering: create.selectFrom(AUTHOR) .orderBy(upper(AUTHOR.FIRST_NAME), upper(AUTHOR.LAST_NAME)) @@ -4571,7 +4571,7 @@ create.selectFrom(AUTHOR)

    This is a list of date and time functions supported by jOOQ's :

    - +
    • CURRENT_DATE: Get current date as a DATE object.
    • CURRENT_TIME: Get current time as a TIME object.
    • @@ -4581,7 +4581,7 @@ create.selectFrom(AUTHOR)
    • TIMESTAMP_ADD: Add a number of days or an interval to a timestamp.
    • TIMESTAMP_DIFF: Get the difference as an INTERVAL DAY TO SECOND between two dates.
    - +

    Intervals in jOOQ

    jOOQ fills a gap opened by JDBC, which neglects an important SQL data type as defined by the SQL standards: INTERVAL types. See the manual's section about for more details. @@ -4729,7 +4729,7 @@ GROUP BY AUTHOR_ID WindowOverStep rank(); WindowOverStep denseRank(); WindowOverStep percentRank(); - + // Windowing functions WindowIgnoreNullsStep firstValue(Field field); WindowIgnoreNullsStep lastValue(Field field) @@ -4745,7 +4745,7 @@ GROUP BY AUTHOR_ID // Statistical functions WindowOverStep cumeDist(); WindowOverStep ntile(int number);]]> - +

    SQL distinguishes between various window function types (e.g. "ranking functions"). Depending on the function, SQL expects mandatory PARTITION BY or ORDER BY clauses within the OVER() clause. jOOQ does not enforce those rules for two reasons:

    @@ -4760,14 +4760,14 @@ GROUP BY AUTHOR_ID

    Here are some simple examples of window functions with jOOQ:

    - + -- Sample uses of ROW_NUMBER() ROW_NUMBER() OVER() ROW_NUMBER() OVER(PARTITION BY 1) ROW_NUMBER() OVER(ORDER BY BOOK.ID) ROW_NUMBER() OVER(PARTITION BY BOOK.AUTHOR_ID ORDER BY BOOK.ID) - + -- Sample uses of FIRST_VALUE FIRST_VALUE(BOOK.ID) OVER() FIRST_VALUE(BOOK.ID IGNORE NULLS) OVER() @@ -4778,14 +4778,14 @@ rowNumber().over() rowNumber().over().partitionByOne() rowNumber().over().partitionBy(BOOK.AUTHOR_ID) rowNumber().over().partitionBy(BOOK.AUTHOR_ID).orderBy(BOOK.ID) - + // Sample uses of firstValue() firstValue(BOOK.ID).over() firstValue(BOOK.ID).ignoreNulls().over() firstValue(BOOK.ID).respectNulls().over()
    - +

    An advanced window function example

    Window functions can be used for things like calculating a "running total". The following example fetches transactions and the running total for every transaction going back to the beginning of the transaction table (ordered by booked_at). Window functions are accessible from the previously seen type using the over() method: @@ -4811,7 +4811,7 @@ firstValue(BOOK.ID).respectNulls().over()

    In the previous chapter about , we have seen the concept of "ordered-set aggregate functions", such as Oracle's LISTAGG(). These functions have a window function / analytical function variant, as well. For example:

    - + SELECT LISTAGG(TITLE, ', ') WITHIN GROUP (ORDER BY TITLE) @@ -4894,7 +4894,7 @@ ORDER BY 1 NULLS LAST, 2 NULLS LAST

    In English, the ROLLUP() grouping function provides N+1 groupings, when N is the number of arguments to the ROLLUP() function. Each grouping has an additional group field from the ROLLUP() argument field list. The results of the second query might look something like this:

    - + GROUPING SETS() and other grouping functions:
    http://msdn.microsoft.com/en-us/library/bb510427(v=sql.105)

    - +

    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:

    - + ... fields); GroupField cube(Field... fields); @@ -4997,7 +4997,7 @@ Field groupingId(Field...);]]>

    MySQL and CUBRID don't know any grouping functions, but they support a WITH ROLLUP clause, that is equivalent to simple ROLLUP() grouping functions. jOOQ emulates ROLLUP() in MySQL and CUBRID, by rendering this WITH ROLLUP clause. The following two statements mean the same:

    - + Some databases support user-defined functions, which can be embedded in any SQL statement, if you're using jOOQ's . Let's say you have the following simple function in Oracle SQL:

    - + The above function will be made available from a generated class. You can use it like any other :

    - + - +

    Note that user-defined functions returning or data types can also be used wherever can be used, if they are

    @@ -5049,7 +5049,7 @@ END echo;

    Some databases support user-defined aggregate functions, which can then be used along with or as . An example for such a database is Oracle. With Oracle, you can define the following OBJECT type (the example was taken from the Oracle 11g documentation):

    - +

    jOOQ's will detect such aggregate functions and generate them differently from regular . They implement the type, as mentioned in the manual's section about . Here's how you can use the SECOND_MAX() aggregate function with jOOQ:

    - +
    - +
    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:

    - + Row1 row(T1 t1) { ... } public static Row2 row(T1 t1, T2 t2) { ... } @@ -5276,12 +5276,12 @@ public static RowN row(Object... values) { ... }]]>

    See the relevant sections for more details about how to use row value expressions in predicates.

    - +

    Using row value expressions in UPDATE statements

    The also supports a variant where row value expressions are updated, rather than single columns. See the relevant section for more details

    - +

    Higher-degree row value expressions

    jOOQ chose to explicitly support degrees up to {max-row-degree} to match Scala's typesafe tuple, function and product support. Unlike Scala, however, jOOQ also supports higher degrees without the additional typesafety. @@ -5305,7 +5305,7 @@ public static RowN row(Object... values) { ... }]]>

  • The of a
  • The 's ON clause
  • - +

    Boolean types in SQL

    Before SQL:1999, boolean types did not really exist in SQL. They were modelled by 0 and 1 numeric/char values. With SQL:1999, true booleans were introduced and are now supported by most databases. In short, these are possible boolean values: @@ -5401,7 +5401,7 @@ Condition combined2 = combined1.andNot(c); // The left-hand side of the AND NOT

    Here are all boolean operators on the interface:

    - + < to test for being strictly less
  • <= to test for being less or equal
  • - +

    Unfortunately, Java does not support operator overloading, hence these operators are also implemented as methods in jOOQ, like any other SQL syntax elements. The relevant parts of the interface are these:

    - + ); // = (some column expression) eq or equal(Select>); // = (some scalar SELECT statement) @@ -5463,12 +5463,12 @@ ge or greaterOrEqual(Select>); // >= (some scalar SELECT st

    Note that every operator is represented by two methods. A verbose one (such as equal()) and a two-character one (such as eq()). Both methods are the same. You may choose either one, depending on your taste. The manual will always use the more verbose one.

    - +

    jOOQ's convenience methods using comparison operators

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using comparison predicates:

    - +
    - +
    Boolean operator precedence @@ -5495,7 +5495,7 @@ BOOK.TITLE.notEqualIgnoreCase("animal farm")]]>

    In SQL, the two expressions wouldn't be the same, as SQL natively knows operator precedence.

    - + A AND B OR C AND D OR E -- Precedence is applied (((A AND B) OR C) AND D) OR E -- Precedence is overridden @@ -5509,7 +5509,7 @@ BOOK.TITLE.notEqualIgnoreCase("animal farm")]]>

    All variants of the that we've seen in the previous chapter also work for . If your database does not support row value expression comparison predicates, jOOQ emulates them the way they are defined in the SQL standard:

    - + (X, Y))]]>

    jOOQ supports all of the above row value expression comparison predicates, both with and at the right-hand side:

    - +
    - +
    Quantified comparison predicate @@ -5606,7 +5606,7 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    It is interesting to note that the SQL standard defines the in terms of the ANY-quantified predicate. The following two expressions are equivalent:

    - + @@ -5617,14 +5617,14 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    - +
    NULL predicate

    In SQL, you cannot compare NULL with any value using , as the result would yield NULL again, which is neither TRUE nor FALSE (see also the manual's section about ). In order to test a for NULL, use the NULL predicate as such:

    - + @@ -5662,7 +5662,7 @@ NOT((A, B) IS NOT NULL)]]>

    The SQL standard contains a nice truth table for the above rules:

    - + +-----------------------+-----------+---------------+---------------+-------------------+ | Expression | R IS NULL | R IS NOT NULL | NOT R IS NULL | NOT R IS NOT NULL | +-----------------------+-----------+---------------+---------------+-------------------+ @@ -5676,13 +5676,13 @@ NOT((A, B) IS NOT NULL)]]>

    In jOOQ, you would simply use the isNull() and isNotNull() methods on row value expressions. Again, as with the , the row value expression NULL predicate is emulated by jOOQ, if your database does not natively support it:

    - +
    - +
    DISTINCT predicate @@ -5709,7 +5709,7 @@ BOOK.TITLE.isNotDistinctFrom(BOOK.SUB_TITLE)]]>

    If your database does not natively support the DISTINCT predicate, jOOQ emulates it with an equivalent , modelling the above truth table:

    - + The BETWEEN predicate can be seen as syntactic sugar for a pair of . According to the SQL standard, the following two predicates are equivalent:

    - + = [B] AND [A] <= [C]]]> @@ -5758,7 +5758,7 @@ BOOK.PUBLISHED_IN.notBetween(1920).and(1940)]]>

    The SQL standard defines the SYMMETRIC keyword to be used along with BETWEEN to indicate that you do not care which bound of the range is larger than the other. A database system should simply swap range bounds, in case the first bound is greater than the second one. jOOQ supports this keyword as well, emulating it if necessary.

    - + @@ -5769,7 +5769,7 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The emulation is done trivially:

    - + @@ -5784,27 +5784,27 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The SQL BETWEEN predicate also works well for . Much like the , it is defined in terms of a pair of regular :

    - + = [B] AND [A] <= [C] ([A] >= [B] AND [A] <= [C]) OR ([A] >= [C] AND [A] <= [B])]]> - +

    The above can be factored out according to the rules listed in the manual's section about .

    - +

    jOOQ supports the BETWEEN [SYMMETRIC] predicate and emulates it in all SQL dialects where necessary. An example is given here:

    - + - +
    - +
    LIKE predicate @@ -5825,7 +5825,7 @@ TITLE NOT LIKE '%abc%']]> - +

    Escaping operands with the LIKE predicate

    Often, your pattern may contain any of the wildcard characters "_" and "%", in case of which you may want to escape them. jOOQ does not automatically escape patterns in like() and notLike() methods. Instead, you can explicitly define an escape character as such: @@ -5844,12 +5844,12 @@ BOOK.TITLE.notLike("%The !%-Sign Book%", '!')]]>

    Please refer to your database manual for more details about escaping patterns with the LIKE predicate.

    - +

    jOOQ's convenience methods using the LIKE predicate

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using the LIKE predicate. Typical operations are "contains predicates", "starts with predicates", "ends with predicates", etc. Here is the full convenience API wrapping LIKE predicates:

    - + >) // Construct a NOT IN predicate from a subse

    A sample IN predicate might look like this:

    - + @@ -5902,12 +5902,12 @@ TITLE NOT IN ('Animal Farm', '1984')]]>
    BOOK.TITLE.notIn("Animal Farm", "1984")]]>
    - +

    NOT IN and NULL values

    Beware that you should probably not have any NULL values in the right hand side of a NOT IN predicate, as the whole expression would evaluate to NULL, which is rarely desired. This can be shown informally using the following reasoning:

    - + -- The following conditional expressions are formally or informally equivalent A NOT IN (B, C) A != ANY(B, C) @@ -5948,7 +5948,7 @@ NULL -- [ANY] AND NULL yields NULL -- Using a subselect (BOOK.ID, BOOK.TITLE) IN ( SELECT T.ID, T.TITLE - FROM T + FROM T )]]> - +

    In both cases, i.e. when using an IN list or when using a subselect, the type of the predicate is checked. Both sides of the predicate must be of equal degree and row type.

    - +

    - Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value. + Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value.

    - +
    EXISTS predicate @@ -5982,7 +5982,7 @@ row(BOOK.ID, BOOK.TITLE).in(
  • From a using
  • From a using , and from other clauses
  • - +

    An example of an EXISTS predicate can be seen here:

    @@ -6001,7 +6001,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

    - +

    Performance of IN vs. EXISTS

    In theory, the two types of predicates can perform equally well. If your database system ships with a sophisticated cost-based optimiser, it will be able to transform one predicate into the other, if you have all necessary constraints set (e.g. referential constraints, not null constraints). However, in reality, performance between the two might differ substantially. An interesting blog post investigating this topic on the MySQL database can be seen here:
    @@ -6009,7 +6009,7 @@ notExists(create.selectOne().from(BOOK)

    - +
    OVERLAPS predicate @@ -6047,7 +6047,7 @@ row(Date.valueOf('2010-01-01'), new DayToSecond(2)).overlaps(Date.valueOf('2010-

    Unlike the standard (or any database implementing the standard), jOOQ also supports the OVERLAPS predicate for comparing arbitrary . For instance, (1, 3) OVERLAPS (2, 4) will yield true in jOOQ. This is emulated as such

    - +
    - +
    Dynamic SQL

    In most cases, , , and as introduced in the previous chapters will be embedded into different SQL statement clauses as if the statement were a static SQL statement (e.g. in a view or stored procedure):

    - + - +

    It is, however, interesting to think of all of the above expressions as what they are: expressions. And as such, nothing keeps users from extracting expressions and referencing them from outside the statement. The following statement is exactly equivalent:

    @@ -6091,26 +6091,26 @@ create.select(select) .groupBy(groupBy) .orderBy() .fetch();]]> - +

    Each individual expression, and collection of expressions can be seen as an independent entity that can be

    - +
    1. Constructed dynamically
    2. Reused across queries
    - +

    Dynamic construction is particularly useful in the case of the , for dynamic predicate building. For instance:

    - +

    The dynamic SQL building power may be one of the biggest advantages of using a runtime query model like the one offered by jOOQ. Queries can be created dynamically, of arbitrary complexity. In the above example, we've just constructed a dynamic . The same can be done for any other clauses, including dynamic as needed.

    @@ -6146,7 +6146,7 @@ create.select()
  • - +

    You'll probably find other examples. If verbosity scares you off, don't worry. The verbose use-cases for jOOQ are rather rare, and when they come up, you do have an option. Just write SQL the way you're used to!

    @@ -6176,7 +6176,7 @@ Condition condition(String sql, Object... bindings); // Construct a condition taking other jOOQ object arguments // Example: condition("a = {0}", val(1)); 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 DSL:

    @@ -6234,7 +6234,7 @@ Result fetch(String sql, QueryPart... parts);]]>

    Apart from the general factory methods, plain SQL is also available in various other contexts. For instance, when adding a .where("a = b") clause to a query. Hence, there exist several convenience methods where plain SQL can be inserted usefully. This is an example displaying all various use-cases in one single query:

    - + LAST_NAME = create.field("a.LAST_NAME"); @@ -6293,7 +6293,7 @@ create.select(LAST_NAME, COUNT1, COUNT2) On a JDBC level, you can also reuse the SQL string and prepared statement object instead of constructing it again, as you can bind new values to the prepared statement. jOOQ currently does not cache prepared statements, internally. - +

    The following sections explain how you can introduce bind values in jOOQ, and how you can control the way they are rendered and bound to SQL.

    @@ -6306,7 +6306,7 @@ create.select(LAST_NAME, COUNT1, COUNT2)

    JDBC only knows indexed bind values. A typical example for using bind values with JDBC is this:

    - + With dynamic SQL, keeping track of the number of question marks and their corresponding index may turn out to be hard. jOOQ abstracts this and lets you provide the bind value right where it is needed. A trivial example is this:

    - + 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

    Should you decide to run the above query outside of jOOQ, using your own , you can do so as follows:

    - + select = create.select().from(BOOK).where(BOOK.ID.equal(5)).and(BOOK.TITLE.equal("Animal Farm")); // Render the SQL statement: @@ -6459,7 +6459,7 @@ create.select()

    Special care needs to be taken when using . While jOOQ's API allows you to specify bind values for use with plain SQL, you're not forced to do that. For instance, both of the following queries will lead to the same, valid result:

    - +

    A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] FROM AUTHOR JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID @@ -6602,15 +6602,15 @@ public final void toSQL(RenderContext context) {

    As mentioned in the previous chapter about , there are some elements in the that are used for formatting / pretty-printing rendered SQL. In order to obtain pretty-printed SQL, just use the following :

    - - + +

    And then, use the above DSLContext to render pretty-printed SQL:

    - + A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] WHERE AUTHOR.ID = ? -- [...] @@ -6699,7 +6699,7 @@ public final void bind(BindContext context) throws DataAccessException {

    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:

    - + extends AbstractField {} public abstract class CustomCondition extends AbstractCondition {} public abstract class CustomTable> extends TableImpl {} @@ -6708,7 +6708,7 @@ public abstract class CustomRecord> extends TableRecord

    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 and methods, as discussed before:

    - + 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 showing how to create a field multiplying another field by 2

    - + IDx2 = new CustomField(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(" * ?"); @@ -6745,10 +6745,10 @@ final Field IDx2 = new CustomField(BOOK.ID.getName(), BOOK.ID. @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(DSL.val(2)); } @@ -6762,7 +6762,7 @@ final Field IDx2 = new CustomField(BOOK.ID.getName(), BOOK.ID. create.select(IDx2).from(BOOK);]]>
    - +
    Plain SQL QueryParts @@ -6776,7 +6776,7 @@ create.select(IDx2).from(BOOK);]]>

    The above distinction is best explained using an example:

    - +

    - +
    Custom SQL transformation @@ -6827,14 +6827,14 @@ create.attach(select);]]>
    - +
    SQL building in Scala

    jOOQ-Scala is a maven module used for leveraging some advanced Scala features for those users that wish to use jOOQ with Scala.

    - +

    Using Scala's implicit defs to allow for operator overloading

    The most obvious Scala feature to use in jOOQ are implicit defs for implicit conversions in order to enhance the type with SQL-esque operators. @@ -6842,7 +6842,7 @@ create.attach(select);]]>

    The following depicts a trait which wraps all fields:

    - + The following depicts a trait which wraps numeric fields:

    - + An example query using such overloaded operators would then look like this:

    - +

    In a previous section of the manual, we've seen how jOOQ can be used to that can be executed with any API including JDBC or ... jOOQ. This section of the manual deals with various means of actually executing SQL with jOOQ.

    - +

    SQL execution with JDBC

    JDBC calls executable objects "". It distinguishes between three types of statements: @@ -6982,7 +6982,7 @@ fetch]]>

    Today, the JDBC API may look weird to users being used to object-oriented design. While statements hide a lot of SQL dialect-specific implementation details quite well, they assume a lot of knowledge about the internal state of a statement. For instance, you can use the method, to add a the prepared statement being created to an "internal list" of batch statements. Instead of returning a new type, this method forces user to reflect on the prepared statement's internal state or "mode".

    - +

    jOOQ is wrapping JDBC

    These things are abstracted away by jOOQ, which exposes such concepts in a more object-oriented way. For more details about jOOQ's batch query execution, see the manual's section about . @@ -7004,7 +7004,7 @@ fetch]]>

  • Both APIs return the number of affected records in non-result queries. JDBC: , jOOQ:
  • Both APIs return a scrollable result set type from result queries. JDBC: , jOOQ:
  • - +

    Differences to JDBC

    Some of the most important differences between JDBC and jOOQ are listed here: @@ -7020,14 +7020,14 @@ fetch]]>

    - +
    Query vs. ResultQuery

    Unlike JDBC, jOOQ has a lot of knowledge about a SQL query's structure and internals (see the manual's section about ). Hence, jOOQ distinguishes between these two fundamental types of queries. While every can be executed, only can return results (see the manual's section about to learn more about fetching results). With plain SQL, the distinction can be made clear most easily:

    - + result = resultQuery.fetch();]]>
  • : Some databases allow for returning many result sets from a single query. JDBC can handle this but it's very verbose. A list of results should be returned instead.
  • : Some queries take too long to execute to wait for their results. You should be able to spawn query execution in a separate process.
  • - +

    Convenience and how ResultQuery, Result, and Record share API

    The term "fetch" is always reused in jOOQ when you can fetch data from the database. An provides many overloaded means of fetching data:

    - +

    Various modes of fetching

    These modes of fetching are also documented in subsequent sections of the manual

    - + fetch(); @@ -7089,7 +7089,7 @@ List> fetchMany(); // Execute a ResultQuery with jOOQ, but return a JDBC ResultSet, not a jOOQ object ResultSet fetchResultSet();]]> - +

    Fetch convenience

    These means of fetching are also available from and APIs @@ -7135,11 +7135,11 @@ ResultSet fetchResultSet();]]>

    These means of fetching are also available from and APIs

    - + Map fetchMap(Field key); Map fetchMap(Field key, Field value); @@ -7176,7 +7176,7 @@ ResultSet fetchResultSet();]]>

    jOOQ understands that SQL is much more expressive than Java, when it comes to the declarative typing of . As a declarative language, SQL allows for creating ad-hoc row value expressions (records with indexed columns, or tuples) and records (records with named columns). In Java, this is not possible to the same extent. Yet, still, sometimes you wish to use strongly typed records, when you know that you're selecting only from a single table

    - +

    Fetching strongly or weakly typed records

    When fetching data only from a single table, the type is known to jOOQ if you use jOOQ's to generate for your database tables. In order to fetch such strongly typed records, you will have to use the : @@ -7188,7 +7188,7 @@ BookRecord book = create.selectFrom(BOOK).where(BOOK.ID.equal(1)).fetchOne(); // Typesafe field access is now possible: 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:

    @@ -7234,7 +7234,7 @@ System.out.println("Published in: " + book.getPublishedIn());]]>

    By default, jOOQ returns an object, which is essentially a of . Often, you will find yourself wanting to transform this result object into a type that corresponds more to your specific needs. Or you just want to list all values of one specific column. Here are some examples to illustrate those use cases:

    - + titles1 = create.select().from(BOOK).fetch().getValues(BOOK.TITLE); List titles2 = create.select().from(BOOK).fetch(BOOK.TITLE); @@ -7269,7 +7269,7 @@ Map> group4 = create.selectFrom(BOOK).fetchGroups(BO

    In a more functional operating mode, you might want to write callbacks that receive records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + () {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -7304,7 +7304,7 @@ create.selectFrom(BOOK)

    In a more functional operating mode, you might want to write callbacks that map records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + ids = create.selectFrom(BOOK) @@ -7316,12 +7316,12 @@ create.selectFrom(BOOK) return book.getId(); } }); - + // Or more concisely create.selectFrom(BOOK) .orderBy(BOOK.ID) .fetch(new RecordMapper() {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -7347,7 +7347,7 @@ create.selectFrom(BOOK)

    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. See the manual's section about to see how to modify jOOQ's standard POJO mapping behaviour.

    - +

    Using JPA-annotated POJOs

    jOOQ tries to find JPA annotations on your POJO types. If it finds any, they are used as the primary source for mapping meta-information. Only the annotation is used and understood by jOOQ. An example: @@ -7357,7 +7357,7 @@ create.selectFrom(BOOK) public class MyBook { @Column(name = "ID") public int myId; - + @Column(name = "TITLE") public String myTitle; } @@ -7366,16 +7366,16 @@ public class MyBook { MyBook myBook = create.select().from(BOOK).fetchAny().into(MyBook.class); List myBooks = create.select().from(BOOK).fetch().into(MyBook.class); List myBooks = create.select().from(BOOK).fetchInto(MyBook.class);]]> - +

    Just as with any other JPA implementation, you can put the annotation on any class member, including attributes, setters and getters. Please refer to the Javadoc for more details.

    - +

    Using simple POJOs

    If jOOQ does not find any JPA-annotations, columns are mapped to the "best-matching" constructor, attribute or setter. An example illustrates this:

    - + myBooks = create.select().from(BOOK).fetchInto(MyBook1.class);]]><

    Please refer to the Javadoc for more details.

    - +

    Using "immutable" POJOs

    If jOOQ does not find any default constructor, columns are mapped to the "best-matching" constructor. This allows for using "immutable" POJOs with jOOQ. An example illustrates this:

    - + myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchInto( public class MyBook3 { public final String title; public final int id; - + @ConstructorProperties({ "title", "id"}) public MyBook2(String title, int id) { this.title = title; @@ -7430,7 +7430,7 @@ MyBook3 myBook = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchA List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetch().into(MyBook3.class); List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchInto(MyBook3.class); ]]> - +

    Please refer to the Javadoc for more details.

    @@ -7439,12 +7439,12 @@ List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchI

    jOOQ also allows for fetching data into abstract classes or interfaces, or in other words, "proxyable" types. This means that jOOQ will return a wrapped in a implementing your custom type. An example of this is given here:

    - + - +

    Note: Because of your manual setting of ID = 10, jOOQ's store() method will asume that you want to insert a new record. See the manual's section about for more details on this.

    - +

    Interaction with DAOs

    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: @@ -7511,21 +7511,21 @@ bookDao.update(book); // Delete it again bookDao.delete(book);]]> - +

    More complex data structures

    jOOQ currently doesn't support more complex data structures, the way Hibernate/JPA attempt to map relational data onto POJOs. While future developments in this direction are not excluded, jOOQ claims that generic mapping strategies lead to an enormous additional complexity that only serves very few use cases. You are likely to find a solution using any of jOOQ's various , with only little boiler-plate code on the client side.

    - +
    POJOs with RecordMappers

    In the previous sections we have seen how to create types to map jOOQ records onto arbitrary objects. We have also seen how jOOQ provides default algorithms to map jOOQ records onto . Your own custom domain model might be much more complex, but you want to avoid looking up the most appropriate RecordMapper every time you need one. For this, you can provide jOOQ's with your own implementation of the interface. An example is given here:

    - + } } } - + // Books might be joined with their authors, create a 1:1 mapping if (type == Book.class) { return new BookMapper(); @@ -7562,7 +7562,7 @@ bookDao.delete(book);]]>

    The above is a very simple example showing that you will have complete flexibility in how to override jOOQ's record to POJO mapping mechanisms.

    - +

    If you're looking into a generic, third-party mapping utility, have a look at ModelMapper, or Orika Mapper, which can both be easily integrated with jOOQ.

    @@ -7575,7 +7575,7 @@ bookDao.delete(book);]]>

    Unlike JDBC's , jOOQ's does not represent an open database cursor with various fetch modes and scroll modes, that needs to be closed after usage. jOOQ's results are simple in-memory Java objects, containing all of the result values. If your result sets are large, or if you have a lot of network latency, you may wish to fetch records one-by-one, or in small chunks. jOOQ supports a type for that purpose. In order to obtain such a reference, use the method. An example is given here:

    - + cursor = null; @@ -7585,7 +7585,7 @@ try { // Cursor has similar methods as Iterator while (cursor.hasNext()) { BookRecord book = cursor.fetchOne(); - + Util.doThingsWithBook(book); } } @@ -7600,7 +7600,7 @@ finally {

    As a holds an internal reference to an open , it may need to be closed at the end of iteration. If a cursor is completely scrolled through, it will conveniently close the underlying ResultSet. However, you should not rely on that.

    - +

    Cursors ship with all the other fetch features

    Like or , gives access to all of the other fetch features that we've seen so far, i.e. @@ -7642,7 +7642,7 @@ finally {

    The correct (and verbose) way to do this with JDBC is as follows:

    - +

    As previously discussed in the chapter about , jOOQ does not rely on an internal state of any JDBC object, which is "externalised" by Javadoc. Instead, it has a straight-forward API allowing you to do the above in a one-liner:

    - + > results = create.fetchMany("sp_help 'author'");]]> @@ -7683,22 +7683,22 @@ List> results = create.fetchMany("sp_help 'author'");]]>
    Later fetching

    Using Java 8 CompletableFutures

    - +

    Java 8 has introduced the new type, which allows for functional composition of asynchronous execution units. When applying this to SQL and jOOQ, you might be writing code as follows:

    - + + .supplyAsync(() -> DSL.using(configuration) .insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .values(3, "Hitchcock") .execute() ) - + // This will supply an AuthorRecord value for the newly inserted author .handleAsync((rows, throwable) -> DSL.using(configuration) @@ -7711,30 +7711,30 @@ CompletableFuture record.changed(true); return record.insert(); }) - + // This will supply an int value indicating the number of deleted rows - .handleAsync((rows, throwable) -> + .handleAsync((rows, throwable) -> DSL.using(configuration) .delete(AUTHOR) .where(AUTHOR.ID.eq(3)) .execute() ) .join();]]> - +

    The above example will execute four actions one after the other, but asynchronously in the JDK's default or common . -

    - +

    +

    For more information, please refer to the Javadoc and official documentation. -

    - +

    +

    Using deprecated API

    - +

    Some queries take very long to execute, yet they are not crucial for the continuation of the main program. For instance, you could be generating a complicated report in a Swing application, and while this report is being calculated in your database, you want to display a background progress bar, allowing the user to pursue some other work. This can be achived simply with jOOQ, by creating a , a type that extends . An example is given here:

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(); @@ -7750,7 +7750,7 @@ Result result = future.get();]]>

    Note, that instead of letting jOOQ spawn a new thread, you can also provide jOOQ with your own :

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(service);]]> @@ -7764,7 +7764,7 @@ FutureResult future = create.selectFrom(BOOK).where(... complex pred

    When interacting with legacy applications, you may prefer to have jOOQ return a , rather than jOOQ's own types. This can be done simply, in two ways:

    - + cursor = create.fetchLazy(rs);]]>

    You can also tighten the interaction with jOOQ's data type system and features, by passing the record type to the above fetch methods:

    - + result = create.fetch (rs, Integer.class, String.class); Cursor result = create.fetchLazy(rs, Integer.class, String.class); @@ -7826,7 +7826,7 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Apart from a few extra features (), jOOQ only supports basic types as supported by the JDBC API. In your application, you may choose to transform these data types into your own ones, without writing too much boiler-plate code. This can be done using jOOQ's types. A converter essentially allows for two-way conversion between two Java data types <T> and <U>. By convention, the <T> type corresponds to the type in your database whereas the <U> type corresponds to your own user type. The Converter API is given here:

    - + extends Serializable { /** @@ -7853,12 +7853,12 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Such a converter can be used in many parts of the jOOQ API. Some examples have been illustrated in the manual's section about .

    - +

    A Converter for GregorianCalendar

    Here is a some more elaborate example involving a Converter for :

    - + { @@ -7889,12 +7889,12 @@ public class CalendarConverter implements Converter dates1 = create.selectFrom(BOOK).fetch().getValues(BOOK.PUBLISHING_DATE, new CalendarConverter()); List dates2 = create.selectFrom(BOOK).fetch(BOOK.PUBLISHING_DATE, new CalendarConverter()); ]]> - +

    Enum Converters

    jOOQ ships with a built-in default , that you can use to map VARCHAR values to enum literals or NUMBER values to enum ordinals (both modes are supported). Let's say, you want to map a YES / NO / MAYBE column to a custom Enum:

    - + - +

    Using Converters in generated source code

    jOOQ also allows for generated source code to reference your own custom converters, in order to permanently replace a <T> type by your own, custom <U> type. See the manual's section about for details. @@ -7956,20 +7956,20 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE) .join(AUTHOR).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) .intern(BOOK.AUTHOR_ID) .fetch();]]> - +

    You can specify as many fields as you want for interning. The above has the following effect:

    - +
    • If the interned Field is of type , then is called upon each string
    • If the interned Field is of any other type, then the call is ignored
    - +

    Future versions of jOOQ will implement interning of data for non-String data types by collecting values in , removing duplicate instances.

    - +

    Note, that jOOQ will not use interned data for identity comparisons: string1 == string2. Interning is used only to reduce the memory footprint of objects.

    @@ -7977,7 +7977,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)
    - +
    Static statements vs. Prepared Statements @@ -7987,7 +7987,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)

    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:

    - + @@ -8017,7 +8017,7 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    Whichever aproach is more optimal for you cannot be decided by jOOQ. In most cases, prepared statements are probably better. But you always have the option of forcing jOOQ to render inlined bind values.

    - +

    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 @@ -8031,15 +8031,15 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    As previously discussed in the chapter about , reusing PreparedStatements is handled a bit differently in jOOQ from how it is handled in JDBC

    - +

    Keeping open PreparedStatements with JDBC

    With JDBC, you can easily reuse a by not closing it between subsequent executions. An example is given here:

    - + The above technique can be quite useful when you want to reuse expensive database resources. This can be the case when your statement is executed very frequently and your database would take non-negligible time to soft-parse the prepared statement and generate a new statement / cursor resource.

    - +

    Keeping open PreparedStatements with jOOQ

    This is also modeled in jOOQ. However, the difference to JDBC is that closing a statement is the default action, whereas keeping it open has to be configured explicitly. This is better than JDBC, because the default action should be the one that is used most often. Keeping open statements is rarely done in average applications. Here's an example of how to keep open PreparedStatements with jOOQ:

    - + query = create.selectOne().keepStatement(true); @@ -8073,7 +8073,7 @@ finally {

    The above example shows how a query can be executed twice against the same underlying PreparedStatement. Unlike in other execution scenarios, you must not forget to close this query now

    - +

    Beware of resource leaks

    While jOOQ allows for explicitly keeping open PreparedStatement references in Query instances, the JDBC Connection may still be closed independently without jOOQ or the PreparedStatement noticing. It is the user's responsibility to close all resources according to the specification and behaviour of the concrete JDBC driver and the underlying database. @@ -8087,7 +8087,7 @@ finally {

    JDBC knows a couple of execution flags and modes, which can be set through the jOOQ API as well. jOOQ essentially supports these flags and execution modes:

    - + - + extends Query { // [...] @@ -8116,25 +8116,25 @@ finally { // The maximum number of rows to be fetched by JDBC // ----------------------------------------------------------- ResultQuery maxRows(int rows); - + }]]>

    Using ResultSet concurrency with ExecuteListeners

    An example of why you might want to manually set a ResultSet's concurrency flag to something non-default is given here:

    - + - +

    In the above example, your custom is triggered before jOOQ loads a new Record from the JDBC ResultSet. With the concurrency being set to ResultSet.CONCUR_UPDATABLE, you can now modify the database cursor through the standard JDBC ResultSet API.

    @@ -8252,18 +8252,18 @@ create.batch(create.insertInto(AUTHOR, ID, FIRST_NAME, LAST_NAME ).values((Inte

    Instead of actually phrasing a select statement, you can also use the convenience methods:

    - + - +

    Inlining sequence references in SQL

    You can inline sequence references in jOOQ SQL statements. The following are examples of how to do that:

    - + The general distinction between (stored) procedures and (stored) functions can be summarised like this:

    - +

    Procedures

    • Are called using JDBC CallableStatement
    • Have no return value
    • Usually support OUT parameters
    - +

    Functions

    • Can be used in SQL statements
    • Have a return value
    • Usually don't support OUT parameters
    - +

    Exceptions to these rules

    • DB2, H2, and HSQLDB don't allow for JDBC escape syntax when calling functions. Functions must be used in a SELECT statement
    • @@ -8323,19 +8323,19 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

      To simplify things a little bit, jOOQ handles both procedures and functions the same way, using a more general type.

      - +

      Using jOOQ for standalone calls to stored procedures and functions

      If you're using jOOQ's , it will generate objects for you. Let's consider the following example:

      - +

      The generated artefacts can then be used as follows:

      - + - +

      But you can also call the procedure using a generated convenience method in a global Routines class:

      @@ -8362,7 +8362,7 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]>

      For more details about for procedures, see the manual's section about .

      - +

      Inlining stored function references in SQL

      Unlike procedures, functions can be inlined in SQL statements to generate or , if you're using . Assume you have a function like this: @@ -8370,11 +8370,11 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]> - +

      The generated artefacts can then be used as follows:

      - + boolean exists = create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]> - +

      For more info about inlining stored function references in SQL statements, please refer to the manual's section about .

      @@ -8415,7 +8415,7 @@ create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]>

      Oracle UDTs can have object-oriented structures including member functions and procedures. With Oracle, you can do things like this:

      - + {"name":"field-n","type":"type-n"}], "records":[[value-1-1,value-1-2,...,value-1-n], [value-2-1,value-2-2,...,value-2-n]]} - +

      Note: This format has changed in jOOQ 2.6.0

      @@ -8755,12 +8755,12 @@ Query query = error.query();]]>

      CRUD always uses the same patterns, regardless of the nature of underlying tables. This again, leads to a lot of boilerplate code, if you have to issue your statements yourself. Like Hibernate / JPA and other ORMs, jOOQ facilitates CRUD using a specific API involving types.

      - +

      Primary keys and updatability

      In normalised databases, every table has a primary key by which a tuple/record within that table can be uniquely identified. In simple cases, this is a (possibly auto-generated) number called ID. But in many cases, primary keys include several non-numeric columns. An important feature of such keys is the fact that in most databases, they are enforced using an index that allows for very fast random access to the table. A typical way to access / modify / delete a book is this:

      - + - +

      Normalised databases assume that a primary key is unique "forever", i.e. that a key, once inserted into a table, will never be changed or re-inserted after deletion. In order to use jOOQ's operations correctly, you should design your database accordingly.

      @@ -8781,7 +8781,7 @@ DELETE FROM BOOK WHERE ID = 5;]]>

      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:

      - + - +

      See the manual's section about for some more insight on "attached" objects.

      - +

      Storing

      Storing a record will perform an or an . In general, new records are always inserted, whereas records loaded from the database are always updated. This is best visualised in code: @@ -8820,7 +8820,7 @@ BookRecord book2 = create.fetchOne(BOOK, BOOK.ID.equal(id)); // Update the record: UPDATE BOOK SET TITLE = 'Animal Farm' WHERE ID = [id] book2.setTitle("Animal Farm"); book2.store();]]> - +

      Some remarks about storing:

      @@ -8830,18 +8830,18 @@ book2.store();]]>
    • When loading records from , jOOQ will assume the record is a new record. It will hence attempt to INSERT it.
    • When you activate , storing a record may fail, if the underlying database record has been changed in the mean time.
    - +

    Deleting

    Deleting a record will remove it from the database. Here's how you delete records:

    - + - +

    Refreshing

    Refreshing a record from the database means that jOOQ will issue a to refresh all record values that are not the primary key. This is particularly useful when you use jOOQ's feature, in case a modified record is "stale" and cannot be stored to the database, because the underlying database record has changed in the mean time. @@ -8860,7 +8860,7 @@ book.refresh();]]>

    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 :

    - + The "original" value, i.e. the value as it was originally fetched from the database or null, if the record was never in the database
  • The "changed" flag, indicating if the value was ever changed through the Record API.
  • - +

    The purpose of the above information is for jOOQ's to know, which values need to be stored to the database, and which values have been left untouched.

    @@ -8896,19 +8896,19 @@ for (BookRecord book : create.fetch(BOOK, BOOK.PUBLISHED_IN.equal(1948))) {

    Many databases support the concept of IDENTITY values, or key values. This is reflected by JDBC's method. jOOQ abstracts using this method as many databases and JDBC drivers behave differently with respect to generated keys. Let's assume the following SQL Server BOOK table:

    - +

    If you're using jOOQ's , the above table will generate a with an IDENTITY column. This information is used by jOOQ internally, to update IDs after calling :

    - +

    and contain foreign key navigation methods. These navigation methods allow for "navigating" inbound or outbound foreign key references by executing an appropriate query. An example is given here:

    - + books = author.fetchChildren(FK_BOOK_AUTHOR);]]>

    Tables without a PRIMARY KEY are considered non-updatable by jOOQ, as jOOQ has no way of uniquely identifying such a record within the database. If you're using jOOQ's , such tables will generate classes, instead of classes. When you fetch from such a table, the returned records will not allow for calling any of the methods.

    - +

    Note, that some databases use internal rowid or object-id values to identify such records. jOOQ does not support these vendor-specific record meta-data.

    @@ -9039,7 +9039,7 @@ Result books = author.fetchChildren(FK_BOOK_AUTHOR);]]>
    - +

    Optimised optimistic locking using TIMESTAMP fields

    If you're using jOOQ's , you can take indicate TIMESTAMP or UPDATE COUNTER fields for every generated table in the . Let's say we have this table:

    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:

    - +

    As before, without the added TIMESTAMP column, optimistic locking is transparent to the API.

    - +

    Optimised optimistic locking using VERSION fields

    Instead of using TIMESTAMPs, you may also use numeric VERSION fields, containing version numbers that are incremented by jOOQ upon store() calls. @@ -9108,7 +9108,7 @@ book2.store();]]>

    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:

    - + books = create.fetch(BOOK); @@ -9124,7 +9124,7 @@ create.batchStore(books);]]>

    - +
    CRUD SPI: RecordListener @@ -9135,11 +9135,11 @@ create.batchStore(books);]]>
  • Adding a central ID generation algorithm, generating UUIDs for all of your records.
  • Adding a central record initialisation mechanism, preparing the database prior to inserting a new record.
  • - +

    An example of such a RecordListener is given here:

    - + - +

    Now, configure jOOQ's runtime to load your listener

    @@ -9179,7 +9179,7 @@ DSLContext create = DSL.using(configuration);]]>

    If you're using jOOQ's , you can configure it to generate and DAOs for you. jOOQ then generates one DAO per , i.e. per table with a single-column primary key. Generated DAOs implement a common jOOQ type called . This type contains the following methods:

    - + corresponds to the DAO's related table //

    corresponds to the DAO's related generated POJO type // corresponds to the DAO's related table's primary key type. @@ -9190,23 +9190,23 @@ public interface DAO, P, T> { void insert(P object) throws DataAccessException; void insert(P... objects) throws DataAccessException; void insert(Collection

    objects) throws DataAccessException; - + // These methods allow for updating POJOs based on their primary key void update(P object) throws DataAccessException; void update(P... objects) throws DataAccessException; void update(Collection

    objects) throws DataAccessException; - + // These methods allow for deleting POJOs based on their primary key void delete(P... objects) throws DataAccessException; void delete(Collection

    objects) throws DataAccessException; void deleteById(T... ids) throws DataAccessException; void deleteById(Collection ids) throws DataAccessException; - + // These methods allow for checking record existence boolean exists(P object) throws DataAccessException; boolean existsById(T id) throws DataAccessException; long count() throws DataAccessException; - + // These methods allow for retrieving POJOs by primary key or by some other field List

    findAll() throws DataAccessException; P findById(T id) throws DataAccessException; @@ -9235,7 +9235,7 @@ public class BookDao extends DAOImpl {

    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:

    - +

    With jOOQ, it's simple. All of jOOQ's exceptions are "system exceptions", hence they are all unchecked.

    - +

    jOOQ's DataAccessException

    jOOQ uses its own to wrap any underlying that might have occurred. Note that all methods in jOOQ that may cause such a DataAccessException document this both in the Javadoc as well as in their method signature. @@ -9286,7 +9286,7 @@ bookDao.delete(book);]]>

  • InvalidResultException: An operation was performed expecting only one result, but several results were returned.
  • MappingException: Something went wrong when loading a record from a or when mapping a record into a POJO
  • - +

    Override jOOQ's exception handling

    The following section about documents means of overriding jOOQ's exception handling, if you wish to deal separately with some types of constraint violations, or if you raise business errors from your database, etc. @@ -9303,7 +9303,7 @@ bookDao.delete(book);]]>

    For convenience and better backwards-compatibility, consider extending instead of implementing this interface.

    - +

    Example: Query statistics ExecuteListener

    Here is a sample implementation of an ExecuteListener, that is simply counting the number of queries per type that are being executed using jOOQ: @@ -9320,11 +9320,11 @@ public class StatisticsListener extends DefaultExecuteListener { public void start(ExecuteContext ctx) { synchronized (STATISTICS) { Integer count = STATISTICS.get(ctx.type()); - + if (count == null) { count = 0; } - + STATISTICS.put(ctx.type(), count + 1); } } @@ -9367,7 +9367,7 @@ for (ExecuteType type : ExecuteType.values()) {

    Please read the for more details

    - +

    Example: Custom Logging ExecuteListener

    The following depicts an example of a custom ExecuteListener, which pretty-prints all queries being executed by jOOQ to stdout: @@ -9390,7 +9390,7 @@ public class PrettyPrinter extends DefaultExecuteListener { // Create a new DSLContext for logging rendering purposes // This DSLContext doesn't need a connection, only the SQLDialect... DSLContext create = DSL.using(ctx.configuration().dialect(), - + // ... and the flag for pretty-printing new Settings().withRenderFormatted(true)); @@ -9398,12 +9398,12 @@ public class PrettyPrinter extends DefaultExecuteListener { if (ctx.query() != null) { System.out.println(create.renderInlined(ctx.query())); } - + // If we're executing a routine else if (ctx.routine() != null) { System.out.println(create.renderInlined(ctx.routine())); } - + // If we're executing anything else (e.g. plain SQL) else if (!StringUtils.isBlank(ctx.sql())) { System.out.println(ctx.sql()); @@ -9413,12 +9413,12 @@ public class PrettyPrinter extends DefaultExecuteListener {

    See also the manual's sections about for more sample implementations of actual ExecuteListeners.

    - +

    Example: Bad query execution ExecuteListener

    You can also use ExecuteListeners to interact with your SQL statements, for instance when you want to check if executed or statements contain a WHERE clause. This can be achieved trivially with the following sample ExecuteListener:

    - + 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:

    - + @@ -9470,7 +9470,7 @@ public class DeleteOrUpdateWithoutWhereException extends RuntimeException {}

    With the above configuration, let's fetch some data with jOOQ

    - +

    @@ -9518,7 +9518,7 @@ Finishing : Total: 4.814ms, +3.375ms

  • 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
  • - +

    Optimise wisely

    Don't be put off by the above paragraphs. You should optimise wisely, i.e. only in places where you really need very high throughput to your database. jOOQ's overhead compared to plain JDBC is typically less than 1ms per query. @@ -9575,7 +9575,7 @@ Finishing : Total: 4.814ms, +3.375ms

    You need to tell jOOQ some things about your database connection. Here's an example of how to do it for an Oracle database

    - + @@ -9584,7 +9584,7 @@ Finishing : Total: 4.814ms, +3.375ms jdbc:oracle:thin:@[your jdbc connection parameters] [your database user] [your database password] - + user[db-user] @@ -9644,7 +9644,7 @@ Finishing : Total: 4.814ms, +3.375ms @@ -9665,13 +9665,13 @@ Finishing : Total: 4.814ms, +3.375ms

    Code generation works by calling this class with the above property file as argument.

    - + org.jooq.util.GenerationTool /jooq-config.xml

    Be sure that these elements are located on the classpath:

    - +
    • The XML configuration file
    • jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar
    • @@ -9696,7 +9696,7 @@ Finishing : Total: 4.814ms, +3.375ms
    • this example uses jOOQ's log4j support by adding log4j.xml and log4j.jar to the project classpath.
    • the actual jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar artefacts may contain version numbers in the file names.
    - +
    Eclipse configuration
    @@ -9840,7 +9840,7 @@ Finishing : Total: 4.814ms, +3.375ms optimistic locking (A Java regular expression. Use the pipe to separate several expressions). See UpdatableRecord.store() and UpdatableRecord.delete() for details --> REC_TIMESTAMP - + @@ -9944,30 +9944,30 @@ Finishing : Total: 4.814ms, +3.375ms false - + true - + false ]]>
    @@ -9976,7 +9976,7 @@ Finishing : Total: 4.814ms, +3.375ms

    Some of the above properties depend on other properties to work correctly. For instance, when generating immutable pojos, pojos must be generated. jOOQ will enforce such properties even if you tell it otherwise. Here is a list of property interdependencies:

    - +
    • When daos = true, then jOOQ will set relations = true
    • When daos = true, then jOOQ will set records = true
    • @@ -9985,7 +9985,7 @@ Finishing : Total: 4.814ms, +3.375ms
    - +
    Programmatic generator configuration @@ -9993,7 +9993,7 @@ Finishing : Total: 4.814ms, +3.375ms

    In the previous sections, we have covered how to set up jOOQ's code generator using XML, either by running a standalone Java application, or by using Maven. However, it is also possible to use jOOQ's GenerationTool programmatically. The XSD file used for the configuration (http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd) is processed using XJC to produce Java artefacts. The below example uses those artefacts to produce the equivalent configuration of the previous :

    - +

    jOOQ allows you to override default implementations of the code generator or the generator strategy. Specifically, the latter can be very useful if you want to inject custom behaviour into jOOQ's code generator with respect to naming classes, members, methods, and other Java objects.

    - + @@ -10250,58 +10250,58 @@ public class Book implements java.io.Serializable { - + MY_SCHEMA - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + - + MY_TABLE - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomBaseClasscom.example.MyOptionalCustomInterface
    - + - + MY_FIELD - + --> MatcherRule --> MatcherRule @@ -10309,30 +10309,30 @@ public class Book implements java.io.Serializable { --> MatcherRule - + - + MY_ROUTINE - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + - + MY_SEQUENCE - + --> MatcherRule @@ -10348,19 +10348,19 @@ public class Book implements java.io.Serializable { CAMEL - + PREFIX_$0_SUFFIX ]]> - +

    Some examples

    The following example shows a matcher strategy that adds a "T_" prefix to all table classes and to table identifiers: @@ -10401,18 +10401,18 @@ public class Book implements java.io.Serializable { ]]> - +

    For more information about each XML tag, please refer to the http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd XSD file.

    - +

    Known issues

    With jOOQ 3.2, the above matchers cannot be used along with the jOOQ Maven plugin. The (incompatible) fix will only be available in jOOQ 3.3.

    - +
    Custom code sections @@ -10435,11 +10435,11 @@ public class Book implements java.io.Serializable {

    The above example simply adds a class footer to , in this case, overriding the default toString() implementation.

    - +

    Any of the below methods can be overridden:

    - + Tables.java: This file contains all table objects in the form of static member references to the actual singleton object
  • UDTs.java: This file contains all UDT objects in the form of static member references to the actual singleton object
  • - +

    Referencing global artefacts

    When referencing global artefacts from your client application, you would typically static import them as such:

    - + @@ -10523,7 +10523,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate a implementation that looks like this:

    - + { // The singleton instance @@ -10539,7 +10539,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE) public Book as(java.lang.String alias) { return new Book(alias); } - + // [...] }]]> @@ -10556,7 +10556,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)
  • instanceFields: This flag controls the "static" keyword on table columns, as well as aliasing convenience
  • records: The generated record type is referenced from tables allowing for type-safe single-table record fetching
  • - +

    Flags controlling table generation

    Table generation cannot be deactivated @@ -10570,7 +10570,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate an implementation that looks like this:

    - + - +

    Flags influencing generated records

    These flags from the influence generated records: @@ -10626,7 +10626,7 @@ implements IBook {

  • interfaces: If interfaces are generated, records will implement them
  • jpaAnnotations: JPA annotations are used on generated records
  • - +

    Flags controlling record generation

    Record generation can be deactivated using the records flag @@ -10640,7 +10640,7 @@ implements IBook {

    Every table in your database will generate a POJO implementation that looks like this:

    - + - +

    Flags influencing generated POJOs

    These flags from the influence generated POJOs: @@ -10689,7 +10689,7 @@ public class Book implements java.io.Serializable

  • jpaAnnotations: JPA annotations are used on generated records
  • validationAnnotations: JSR-303 validation annotations are used on generated records
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the pojos flag @@ -10703,16 +10703,16 @@ public class Book implements java.io.Serializable

    Every table in your database will generate an interface that looks like this:

    - + - +

    Flags influencing generated interfaces

    These flags from the influence generated interfaces: @@ -10721,7 +10721,7 @@ public class Book implements java.io.Serializable

  • dateAsTimestamp: This influences all relevant getters and setters
  • unsignedTypes: This influences all relevant getters and setters
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the interfaces flag @@ -10736,7 +10736,7 @@ public class Book implements java.io.Serializable

    Every table in your database will generate a implementation that looks like this:

    - + { // Generated constructors @@ -10760,10 +10760,10 @@ public class Book implements java.io.Serializable public List fetchByAuthorId(Integer... values) { return fetch(BOOK.AUTHOR_ID, values); } - + // [...] }]]> - +

    Flags controlling DAO generation

    DAO generation can be activated using the daos flag @@ -10777,13 +10777,13 @@ public class Book implements java.io.Serializable

    Every sequence in your database will generate a implementation that looks like this:

    - + S_AUTHOR_ID = new SequenceImpl("S_AUTHOR_ID", TEST, SQLDataType.INTEGER); }]]> - +

    Flags controlling sequence generation

    Sequence generation cannot be deactivated @@ -10821,7 +10821,7 @@ public class Book implements java.io.Serializable public BigDecimal getResult() { return getValue(RESULT); } - + // [...] }]]> @@ -10843,7 +10843,7 @@ public class Book implements java.io.Serializable

    Every UDT in your database will generate a implementation that looks like this:

    - + { // The singleton UDT instance @@ -10856,10 +10856,10 @@ public class Book implements java.io.Serializable createField("CITY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); public static final UDTField COUNTRY = createField("COUNTRY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); - + // [...] }]]> - +

    Besides the implementation, a implementation is also generated

    @@ -10874,7 +10874,7 @@ public class Book implements java.io.Serializable public String getCity() {...} public void setCountry(String value) {...} public String getCountry() {...} - + // [...] }]]>
    @@ -10906,7 +10906,7 @@ public class Book implements java.io.Serializable Use the pipe to separate several expressions. If provided, both "expressions" and "types" must match. --> .*\.IS_VALID - + .* @@ -10955,7 +10955,7 @@ public class Book implements java.io.Serializable Use the pipe to separate several expressions. If provided, both "expressions" and "types" must match. --> .*\.DATE_OF_.* - + .* @@ -11007,23 +11007,23 @@ create.selectFrom(AUTHOR)
    - +
    Code generation for large schemas

    Databases can become very large in real-world applications. This is not a problem for jOOQ's code generator, but it can be for the Java compiler. jOOQ generates some classes for . These classes can hit two sorts of limits of the compiler / JVM:

    - +
    • Methods (including static / instance initialisers) are allowed to contain only 64kb of bytecode.
    • Classes are allowed to contain at most 64k of constant literals
    - +

    While there exist workarounds for the above two limitations (delegating initialisations to nested classes, inheriting constant literals from implemented interfaces), the preferred approach is either one of these:

    - +
    • Distribute your database objects in several schemas. That is probably a good idea anyway for such large databases
    • to exclude excess database objects
    • @@ -11106,11 +11106,11 @@ create.selectFrom(AUTHOR)

      When writing unit tests for your data access layer, you have probably used some generic mocking tool offered by popular providers like Mockito, jmock, mockrunner, or even DBUnit. With jOOQ, you can take advantage of the built-in JDBC mock API that allows you to emulate a simple database on the JDBC level for precisely those SQL/JDBC use cases supported by jOOQ.

      - +

      - Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider. + Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider.

      - +

      Mocking the JDBC API

      JDBC is a very complex API. It takes a lot of time to write a useful and correct mock implementation, implementing at least these interfaces: @@ -11123,16 +11123,16 @@ create.selectFrom(AUTHOR)

    - +

    Optionally, you may even want to implement interfaces, such as , , , and many others. In addition to the above, you might need to find a way to simultaneously support incompatible JDBC minor versions, such as 4.0, 4.1

    - +

    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 :

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    As you can see, the configuration setup is simple. Now, the MockDataProvider acts as your single point of contact with JDBC / jOOQ. It unifies any of these execution modes, transparently:

    - +
    • Statements without results
    • Statements without results but with generated keys
    • @@ -11155,16 +11155,16 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
    • Batch statements with single queries and multiple bind value sets
    • Batch statements with multiple queries and no bind values
    - +

    The above are the execution modes supported by jOOQ. Whether you're using any of jOOQ's various fetching modes (e.g. , , , ) is irrelevant, as those modes are all built on top of the standard JDBC API.

    - +

    Implementing MockDataProvider

    Now, here's how to implement MockDataProvider:

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc // 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 String sql = ctx.sql(); - + // Exceptions are propagated through the JDBC and jOOQ APIs if (sql.toUpperCase().startsWith("DROP")) { throw new SQLException("Statement not supported: " + sql); } - + // You decide, whether any given statement returns results, and how many else if (sql.toUpperCase().startsWith("SELECT")) { - + // Always return one author record Result result = create.newResult(AUTHOR); result.add(create.newRecord(AUTHOR)); @@ -11192,12 +11192,12 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc result.get(0).setValue(AUTHOR.LAST_NAME, "Orwell"); mock[0] = new MockResult(1, result); } - + // You can detect batch statements easily else if (ctx.batch()) { // [...] } - + return mock; } }]]> @@ -11209,17 +11209,17 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • : The number of affected rows
  • : The result set
  • - +

    You should return as many MockResult objects as there were query executions (in ) or results (in ). Instead of an awkward JDBC ResultSet, however, you can construct a "friendlier" with your own record types. The jOOQ mock API will use meta data provided with this Result in order to create the necessary JDBC

    - +

    See the for a list of rules that you should follow.

    - +
    jOOQ Console @@ -11265,7 +11265,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • Sybase Adaptive Server Enterprise 15.5
  • Sybase SQL Anywhere 12
  • - +

    For an up-to-date list of currently supported RDBMS, please refer to http://www.jooq.org/legal/licensing/#databases.

    @@ -11286,7 +11286,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc This chapter should document the most important notes about SQL, JDBC and jOOQ data types.

    - +
    BLOBs and CLOBs @@ -11296,7 +11296,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    - +
    Unsigned integer types @@ -11320,7 +11320,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
    - +
    INTERVAL data types @@ -11331,11 +11331,11 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • YEAR TO MONTH: This interval type models a number of months and years
  • DAY TO SECOND: This interval type models a number of days, hours, minutes, seconds and milliseconds
  • - +

    Both interval types ship with a variant of subtypes, such as DAY TO HOUR, HOUR TO SECOND, etc. jOOQ models these types as Java objects extending : (where Number.intValue() corresponds to the absolute number of months) and (where Number.intValue() corresponds to the absolute number of milliseconds)

    - +

    Interval arithmetic

    In addition to the documented previously, interval arithmetic is also supported by jOOQ. Essentially, the following operations are supported: @@ -11350,7 +11350,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    - +
    XML data types @@ -11359,7 +11359,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    - +
    Geospacial data types @@ -11369,7 +11369,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    - +
    CURSOR data types @@ -11378,22 +11378,22 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    > cursor;]]> - +

    In fact, such a cursor will be fetched immediately by jOOQ and wrapped in an object.

    - +
    ARRAY and TABLE data types

    The SQL standard specifies ARRAY data types, that can be mapped to Java arrays as such:

    - + intArray;]]> - +

    The above array type is supported by these SQL dialects:

    @@ -11402,7 +11402,7 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • HSQLDB
  • Postgres
  • - +

    Oracle typed arrays

    Oracle has strongly-typed arrays and table types (as opposed to the previously seen anonymously typed arrays). These arrays are wrapped by types. @@ -11418,12 +11418,12 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    jOOQ takes SQL as an external domain-specific language and maps it onto Java, creating an internal domain-specific language. Internal DSLs cannot 100% implement their external language counter parts, as they have to adhere to the syntax rules of their host or target language (i.e. Java). This section explains the various problems and workarounds encountered and implemented in jOOQ.

    - +

    SQL allows for "keywordless" syntax

    SQL syntax does not always need keywords to form expressions. The clause takes various argument assignments:

    - + UPDATE t SET a = 1, b = 2 update(t).set(a, 1).set(b, 2) @@ -11441,12 +11441,12 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    In this case, ROW is an actual (optional) SQL keyword, implemented by at least PostgreSQL.

    - +

    SQL contains "composed" keywords

    As most languages, SQL does not attribute any meaning to whitespace. However, whitespace is important when forming "composed" keywords, i.e. SQL clauses composed of several keywords. jOOQ follows standard Java method naming conventions to map SQL keywords (case-insensitive) to Java methods (case-sensitive, camel-cased). Some examples:

    - + GROUP BY ORDER BY @@ -11459,7 +11459,7 @@ whenMatchedThenUpdate()

    Future versions of jOOQ may use all-uppercased method names in addition to the camel-cased ones (to prevent collisions with Java keywords):

    - + GROUP BY ORDER BY @@ -11490,7 +11490,7 @@ WHEN_MATCHED_THEN_UPDATE()

    The above example omits THEN and END keywords in Java. Future versions of jOOQ may comprise a more complete DSL, including such keywords again though, to provide a more 1:1 match for the SQL language.

    - +

    SQL contains "superfluous" syntactic elements

    Some SQL constructs are hard to map to Java, but they are also not really necessary. SQL often expects syntactic parentheses where they wouldn't really be needed, or where they feel slightly inconsistent with the rest of the SQL language. @@ -11527,7 +11527,7 @@ WHEN_MATCHED_THEN_UPDATE()

    jOOQ replaces those keywords by "synonyms":

    - + CASE .. ELSE PIVOT .. FOR .. IN .. @@ -11555,7 +11555,7 @@ pivot(..).on(..).in(..)

    Most SQL operators have to be mapped to descriptive method names in Java, as Java does not allow operator overloading:

    - + , != @@ -11584,7 +11584,7 @@ set(a, b)

    This is less of a syntactic SQL feature than a semantic one. In SQL, objects can be referenced before (i.e. "lexicographically before") they are declared. This is particularly true for

    - + @@ -11595,7 +11595,7 @@ select(t.a).from(t)]]>

    A more sophisticated example are common table expressions (CTE), which are currently not supported by jOOQ:

    - + WITH t(a, b) AS ( SELECT 1, 2 FROM DUAL ) @@ -11607,7 +11607,7 @@ FROM t

    - +
    jOOQ's BNF pseudo-notation @@ -11616,7 +11616,7 @@ FROM t

    - +
    Quality Assurance @@ -11628,16 +11628,16 @@ FROM t
  • To add lots of type-safety to your inline SQL
  • To increase productivity when writing inline SQL using your favourite IDE's autocompletion capabilities
  • - +

    With jOOQ being in the core of your application, you want to be sure that you can trust jOOQ. That is why jOOQ is heavily unit and integration tested with a strong focus on integration tests:

    - +

    Unit tests

    Unit tests are performed against dummy JDBC interfaces using http://jmock.org/. These tests verify that various implementations render correct SQL and bind variables correctly.

    - +

    Integration tests

    This is the most important part of the jOOQ test suites. Some 1500 queries are currently run against a standard integration test database. Both the test database and the queries are translated into every one of the 14 supported SQL dialects to ensure that regressions are unlikely to be introduced into the code base. @@ -11648,17 +11648,17 @@ FROM t

    jOOQ integration tests run the weirdest and most unrealistic queries. As a side-effect of these extensive integration test suites, many corner-case bugs for JDBC drivers and/or open source databases have been discovered, feature requests submitted through jOOQ and reported mainly to CUBRID, Derby, H2, HSQLDB.

    - +

    Code generation tests

    For every one of the 14 supported integration test databases, source code is generated and the tiniest differences in generated source code can be discovered. In case of compilation errors in generated source code, new test tables/views/columns are added to avoid regressions in this field.

    - +

    API Usability tests and proofs of concept

    jOOQ is used in jOOQ-meta as a proof of concept. This includes complex queries such as the following Postgres query

    - + These rather complex queries show that the jOOQ API is fit for advanced SQL use-cases, compared to the rather simple, often unrealistic queries in the integration test suite.

    - +

    Clean API and implementation. Code is kept DRY

    As a general rule of thumb throughout the jOOQ code, everything is kept DRY. Some examples: @@ -11724,19 +11724,19 @@ for (Record record : create.select(

    - +
    Migrating to jOOQ 3.0

    This section is for all users of jOOQ 2.x who wish to upgrade to the next major release. In the next sub-sections, the most important changes are explained. Some code hints are also added to help you fix compilation errors.

    - +

    Type-safe row value expressions

    Support for has been added in jOOQ 2.6. In jOOQ 3.0, many API parts were thoroughly (but often incompatibly) changed, in order to provide you with even more type-safety.

    - +

    Here are some affected API parts:

    @@ -11746,11 +11746,11 @@ for (Record record : create.select(
  • IN predicates and comparison predicates taking subselects changed incompatibly
  • INSERT and MERGE statements now take typesafe VALUES() clauses
  • - +

    Some hints related to row value expressions:

    - + record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result> result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch(); @@ -11758,31 +11758,31 @@ Result> result = create.select(BOOK.TITLE, BOOK.ID).fro // But Record2 extends Record. You don't have to use the additional typesafety: Record record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch();]]> - +

    SelectQuery and SelectXXXStep are now generic

    In order to support type-safe row value expressions and type-safe Record[N] types, SelectQuery is now generic: SelectQuery<R>

    - +

    SimpleSelectQuery and SimpleSelectXXXStep API were removed

    The duplication of the SELECT API is no longer useful, now that SelectQuery and SelectXXXStep are generic.

    - +

    Factory was split into DSL (query building) and DSLContext (query execution)

    The pre-existing Factory class has been split into two parts:

    - +
    1. 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
    2. 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 renamed to DSLContext. An example:

    - + - +

    Quantified comparison predicates

    Field.equalAny(...) and similar methods have been removed in favour of Field.equal(any(...)). This greatly simplified the Field API. An example:

    - + > subselect = any(select(BOOK.ID).from(BOOK)); Condition condition = BOOK.ID.equal(subselect);]]> - +

    FieldProvider

    The FieldProvider marker interface was removed. Its methods still exist on FieldProvider subtypes. Note, they have changed names from getField() to field() and from getIndex() to indexOf()

    - +

    GroupField

    GroupField has been introduced as a DSL marker interface to denote fields that can be passed to GROUP BY clauses. This includes all org.jooq.Field types. However, fields obtained from ROLLUP(), CUBE(), and GROUPING SETS() functions no longer implement Field. Instead, they only implement GroupField. An example:

    - + field1a = Factory.rollup(...); // OK Field field2a = Factory.one(); // OK @@ -11828,19 +11828,19 @@ GroupField field1b = DSL.rollup(...); // OK Field field1c = DSL.rollup(...); // Compilation error GroupField field2b = DSL.one(); // OK Field field2c = DSL.one(); // OK]]> - +

    NULL predicate

    Beware! Previously, Field.equal(null) was translated internally to an IS NULL predicate. This is no longer the case. Binding Java "null" to a comparison predicate will result in a regular comparison predicate (which never returns true). This was changed for several reasons:

    - +
    • To most users, this was a surprising "feature".
    • Other predicates didn't behave in such a way, e.g. the IN predicate, the BETWEEN predicate, or the LIKE predicate.
    • Variable binding behaved unpredictably, as IS NULL predicates don't bind any variables.
    • The generated SQL depended on the possible combinations of bind values, which creates unnecessary hard-parses every time a new unique SQL statement is rendered.
    - +

    Here is an example how to check if a field has a given value, without applying SQL's ternary NULL logic:

    @@ -11853,7 +11853,7 @@ Condition condition1 = BOOK.TITLE.equal(possiblyNull); // jOOQ 3.0 Condition condition2 = BOOK.TITLE.equal(possiblyNull).or(BOOK.TITLE.isNull().and(val(possiblyNull).isNull())); Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    Configuration

    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 @@ -11867,7 +11867,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> In order to resolve confusion that used to arise because of different lifecycle durations, these types are now no longer formally connected through inheritance.

    - +

    ConnectionProvider

    In order to allow for simpler connection / data source management, jOOQ externalised connection handling in a new ConnectionProvider type. The previous two connection modes are maintained backwards-compatibly (JDBC standalone connection mode, pooled DataSource mode). Other connection modes can be injected using: @@ -11877,24 +11877,24 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    These are some side-effects of the above change

    - +
    • 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. This resolves many class loader issues that were encountered before. It also helps listener implementations control their lifecycles themselves.

    - +

    Data type API

    The data type API has been changed drastically in order to enable some new DataType-related features. These changes include: @@ -11904,16 +11904,16 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]>[SQLDialect]DataType and SQLDataType no longer implement DataType. They're mere constant containers

  • Various minor API changes have been done.
  • - +

    Object renames

    These objects have been moved / renamed:

    - +
    • jOOU: a library used to represent unsigned integer types was moved from org.jooq.util.unsigned to org.jooq.util.types (which already contained INTERVAL data types)
    - +

    Feature removals

    Here are some minor features that have been removed in jOOQ 3.0 @@ -12007,7 +12007,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> --> diff --git a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.3.xml b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.3.xml index 3022575b75..6fc5520d08 100644 --- a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.3.xml +++ b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.3.xml @@ -126,7 +126,7 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ's reason for being - compared to SQL / JDBC

    So why not just use SQL? @@ -149,14 +149,14 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ is different

    SQL was never meant to be abstracted. To be confined in the narrow boundaries of heavy mappers, hiding the beauty and simplicity of relational data. SQL was never meant to be object-oriented. SQL was never meant to be anything other than... SQL!

    - + - +
    Getting started with jOOQ @@ -343,12 +343,12 @@ limitations under the License.

    This section helps you correctly interpret this manual in the context of jOOQ.

    - +

    Code blocks

    The following are code blocks:

    - + @@ -364,7 +364,7 @@ org.jooq.property=value]]>

    These are useful to provide examples in code. Often, with jOOQ, it is even more useful to compare SQL code with its corresponding Java/jOOQ code. When this is done, the blocks are aligned side-by-side, with SQL usually being on the left, and an equivalent jOOQ DSL query in Java usually being on the right:

    - + @@ -376,17 +376,17 @@ create.selectOne()]]>

    The contents of code blocks follow conventions, too. If nothing else is mentioned next to any given code block, then the following can be assumed:

    - - + + - +

    Your naming may differ, of course. For instance, you could name the "create" instance "db", instead.

    - +

    Execution

    - +

    When you're coding PL/SQL, T-SQL or some other procedural SQL language, SQL statements are always executed immediately at the semi-colon. This is not the case in jOOQ, because as an internal DSL, jOOQ can never be sure that your statement is complete until you call fetch() or execute(). The manual tries to apply fetch() and execute() as thoroughly as possible. If not, it is implied:

    @@ -426,7 +426,7 @@ create.update(T).set(T.V, 1).execute();]]>

    jOOQ allows to override runtime behaviour using . If nothing is specified, the default runtime settings are assumed.

    - +

    Sample database

    jOOQ query examples run against the sample database. See the manual's section about to learn more about the sample database. @@ -461,7 +461,7 @@ CREATE TABLE book ( title VARCHAR2(400) NOT NULL, published_in NUMBER(7) NOT NULL, language_id NUMBER(7) NOT NULL, - + CONSTRAINT fk_book_author FOREIGN KEY (author_id) REFERENCES author(id), CONSTRAINT fk_book_language FOREIGN KEY (language_id) REFERENCES language(id) ); @@ -474,7 +474,7 @@ CREATE TABLE book_to_book_store ( name VARCHAR2(400) NOT NULL, book_id INTEGER NOT NULL, stock INTEGER, - + PRIMARY KEY(name, book_id), CONSTRAINT fk_b2bs_book_store FOREIGN KEY (name) REFERENCES book_store (name) ON DELETE CASCADE, CONSTRAINT fk_b2bs_book FOREIGN KEY (book_id) REFERENCES book (id) ON DELETE CASCADE @@ -485,7 +485,7 @@ CREATE TABLE book_to_book_store (

    In addition to the above, you may assume the following sample data:

    - + Effectively, jOOQ was originally designed to replace any other database abstraction framework short of the ones handling connection pooling and transaction management (see also the )

    - +

    Use jOOQ the way you prefer

    ... but open source is community-driven. And the community has shown various ways of using jOOQ that diverge from its original intent. Some use cases encountered are: @@ -544,7 +544,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]>Using jOOQ for SQL building and Spring Data for SQL execution

  • Using jOOQ without the to build the basis of a framework for dynamic SQL execution.
  • - +

    The following sections explain about various use cases for using jOOQ in your application.

    @@ -557,7 +557,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]> This is the most simple of all use cases, allowing for construction of valid SQL for any database. In this use case, you will not use and probably not even . Instead, you'll use to wrap strings, literals and other user-defined objects into an object-oriented, type-safe AST modelling your SQL statements. An example is given here:

    - + - +

    The SQL string built with the jOOQ query DSL can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools (note that since jOOQ uses PreparedStatement by default, this will generate a bind variable for "1948". ).

    @@ -594,7 +594,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID)) .where(BOOK.PUBLISHED_IN.equal(1948)) .getSQL();]]> - +

    The SQL string that you can generate as such can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools.

    @@ -614,7 +614,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    Instead of any tool mentioned in the previous chapters, you can also use jOOQ directly to execute your jOOQ-generated SQL statements. This will add a lot of convenience on top of the previously discussed API for typesafe SQL construction, when you can re-use the information from generated classes to fetch records and custom data types. An example is given here:

    - + > result = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) @@ -668,10 +668,10 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { // Skip previously distinguished authors if ((int) author.getDistinguished() == 1) continue; - + // Check if the author has written more than 5 books if (author.fetchChildren(Keys.FK_BOOK_AUTHOR).size() > 5) { - + // Mark the author as a "distinguished" author author.setDistinguished(1); author.store(); @@ -688,7 +688,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {
    - +
    jOOQ for PROs @@ -726,7 +726,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { This manual section is intended for new users, to help them get a running application with jOOQ, quickly.

    - +
    Step 1: Preparation @@ -735,7 +735,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { If you haven't already downloaded it, download jOOQ:
    http://www.jooq.org/download

    - +

    Alternatively, you can create a Maven dependency to download jOOQ artefacts:

    @@ -758,7 +758,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    Note that only the jOOQ Open Source Edition is available from Maven Central. If you're using the jOOQ Professional Edition or the jOOQ Enterprise Edition, you will have to manually install jOOQ in your local Nexus, or in your local Maven cache. For more information, please refer to the licensing pages.

    - +

    Please refer to the manual's section about to learn how to use jOOQ's code generator with Maven.

    @@ -773,14 +773,14 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    - +
    Step 2: Your database

    We're going to create a database called "library" and a corresponding "author" table. Connect to MySQL via your command line client and type the following:

    - + CREATE DATABASE `library`; USE `library`; @@ -794,7 +794,7 @@ CREATE TABLE `author` (
    - +
    Step 3: Code generation @@ -806,7 +806,7 @@ CREATE TABLE `author` (

    The easiest way to generate a schema is to copy the jOOQ jar files (there should be 3) and the MySQL Connector jar file to a temporary directory. Then, create a library.xml that looks like this:

    - + @@ -860,7 +860,7 @@ CREATE TABLE `author` (

    generator.target.directory - the directory to output to.

    - +

    Once you have the JAR files and library.xml in your temp directory, type this on a Windows machine:

    @@ -880,12 +880,12 @@ CREATE TABLE `author` (

    There are two things to note:

    - +
    1. The prefix slash before the /library.xml. Even though it's in our working directory, we need to prepend a slash, as the configuration file is loaded from the classpath.
    2. The "trailing" period in the classpath: .. We need this because we want the current directory on the classpath in order to find the above /library.xml file at the root of your classpath.
    - +

    Replace the filenames with your actual filenames. In this example, jOOQ {jooq-version} is being used. If everything has worked, you should see this in your console output:

    @@ -947,17 +947,17 @@ INFO: Packages fetched : 0 (0 included, 0 excluded) Nov 1, 2011 7:25:08 PM org.jooq.impl.JooqLogger info INFO: GENERATION FINISHED! : Total: 791.688ms, +9.143ms - +
    - +
    Step 4: Connect to your database

    Let's just write a vanilla main class in the project containing the generated classes:

    - +
    - +
    Step 5: Querying

    Let's add a simple query constructed with jOOQ's query DSL:

    - + result = create.select().from(AUTHOR).fetch();]]> @@ -1007,7 +1007,7 @@ Result result = create.select().from(AUTHOR).fetch();]]>

    - +
    Step 6: Iterating @@ -1026,7 +1026,7 @@ Result result = create.select().from(AUTHOR).fetch();]]>

    The full program should now look like this:

    - +
    - +
    Step 7: Explore! @@ -1122,7 +1122,7 @@ public class Main {
  • Another example using Spring and Guice for transaction management can be downloaded from GitHub.
  • Another, excellent tutorial by Petri Kainulainen can be found here.
  • - +

    Add the required Maven dependencies

    For this example, we'll create the following Maven dependencies @@ -1201,7 +1201,7 @@ public class Main {

    The above dependencies are configured together using a Spring Beans configuration:

    - + - + @@ -1243,9 +1243,9 @@ public class Main { - + - + @@ -1264,7 +1264,7 @@ public class Main { - + ]]> @@ -1315,7 +1315,7 @@ public class QueryTest {

    The following example shows how you can use Spring's TransactionManager to explicitly handle transactions:

    - +
    - +
    Using jOOQ with JAX-RS

    In some use-cases, having a lean, single-tier server-side architecture is desireable. Typically, such architectures expose a RESTful API implementing client code and the UI using something like AngularJS.

    - +

    In Java, the standard API for RESTful applications is JAX-RS, which is part of JEE 7, along with a standard JSON implementation. But you can use JAX-RS also outside of a JEE container. The following example shows how to set up a simple license server using these technologies:

    @@ -1428,9 +1428,9 @@ public class TransactionTest {

    For the example, we'll use a PostgreSQL database.

    - +

    Creating the license server database

    - +

    We'll keep the example simple and use a LICENSE table to store all license keys and associated information, whereas a LOG_VERIFY table is used to log access to the license server. Here's the DDL:

    @@ -1442,7 +1442,7 @@ public class TransactionTest { LICENSEE TEXT NOT NULL, -- The e-mail address of the licensee LICENSE TEXT NOT NULL, -- The license key VERSION VARCHAR(50) NOT NULL DEFAULT '.*', -- The licensed version(s), a regular expression - + CONSTRAINT PK_LICENSE PRIMARY KEY (ID), CONSTRAINT UK_LICENSE UNIQUE (LICENSE) ); @@ -1455,7 +1455,7 @@ CREATE TABLE LICENSE_SERVER.LOG_VERIFY ( REQUEST_IP VARCHAR(50) NOT NULL, -- The request IP verifying the license VERSION VARCHAR(50) NOT NULL, -- The version that is being verified MATCH BOOLEAN NOT NULL, -- Whether the verification was successful - + CONSTRAINT PK_LOG_VERIFY PRIMARY KEY (ID) );]]> @@ -1477,13 +1477,13 @@ $$ LANGUAGE PLPGSQL;

    The actual algorithm might be using a secret salt to hash the function arguments. For the sake of a tutorial, a constant string will suffice.

    - +

    Setting up the project

    - +

    We're going to be setting up the

    - + 9966 - + org.jooq jooq-codegen-maven @@ -1549,7 +1549,7 @@ $$ LANGUAGE PLPGSQL; servlet-api 2.5 - + org.jooq jooq @@ -1571,13 +1571,13 @@ $$ LANGUAGE PLPGSQL;

    With the above setup, we're now pretty ready to start developing our license service as a JAX-RS service.

    - +

    The license service class

    - +

    Once we've run the , we can write the following service class:

    - + /license/verify checks if a given licensee has access to version using a license. * @@ -1637,7 +1637,7 @@ public class LicenseService { @Override public String run(DSLContext ctx) { String v = (version == null || version.equals("")) ? "" : version; - + // Use the jOOQ query DSL API to generate a log entry return ctx.insertInto(LOG_VERIFY) @@ -1658,10 +1658,10 @@ public class LicenseService { } }); } - + // [...] }]]> - +

    The INSERT INTO LOG_VERIFY query is actually rather interesting. In plain SQL, it would look like this:

    @@ -1686,7 +1686,7 @@ RETURNING MATCH;]]> */ private String run(CtxRunnable runnable) { Connection c = null; - + try { Class.forName("org.postgresql.Driver"); c = getConnection("jdbc:postgresql:postgres", "postgres", System.getProperty("pw", "test")); @@ -1694,7 +1694,7 @@ RETURNING MATCH;]]> .set(new DefaultConnectionProvider(c)) .set(SQLDialect.POSTGRES) .set(new Settings().withExecuteLogging(false))); - + return runnable.run(ctx); } catch (Exception e) { @@ -1706,13 +1706,13 @@ RETURNING MATCH;]]> JDBCUtils.safeClose(c); } } - + private interface CtxRunnable { String run(DSLContext ctx); }]]>

    Configuring Spring and Jetty

    - +

    All we need now is to configure Spring...

    @@ -1770,7 +1770,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/sch

    Using the license server

    - +

    You can now use the license server at the following URLs

    @@ -1787,7 +1787,7 @@ http://localhost:8088/jooq-jax-rs-example/license/verify?mail=test@example.com&l

    Let's verify what happened, in the database:

    - + - +

    Downloading the complete example

    - +

    The complete example can be downloaded for free and under the terms of the Apache Software License 2.0 from here:
    https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-jax-rs-example @@ -1817,7 +1817,7 @@ select * from license_server.log_verify

    - +
    jOOQ and Scala @@ -1831,7 +1831,7 @@ select * from license_server.log_verify
  • Type inference using "var" and "val" keywords
  • Lambda expressions and for-comprehension syntax for record iteration and data type conversion
  • - +

    But jOOQ also leverages other useful Scala features, such as

    @@ -1839,15 +1839,15 @@ select * from license_server.log_verify
  • implicit defs for operator overloading
  • Scala Macros (soon to come)
  • - +

    All of the above heavily improve jOOQ's querying DSL API experience for Scala developers.

    - +

    A short example jOOQ application in Scala might look like this:

    - +
    - - + +
    jOOQ and Groovy @@ -1913,7 +1913,7 @@ object Test { //

    A short example jOOQ application in Groovy might look like this:

    - +
    - +
    jOOQ and NoSQL @@ -1966,7 +1966,7 @@ DSL.using(sql.connection)

    - +
    Dependencies @@ -1984,7 +1984,7 @@ DSL.using(sql.connection)
    - +
    Build your own @@ -2013,7 +2013,7 @@ DSL.using(sql.connection)
    - +
    jOOQ and backwards-compatibility @@ -2025,7 +2025,7 @@ DSL.using(sql.connection)
  • If a minor release includes backwards-compatible, API-relevant new features, [Y] is incremented by one and [Z] is reset to zero.
  • If a major release includes backwards-incompatible, API-relevant new features, [X] is incremented by one and [Y], [Z] are reset to zero.
  • - +

    jOOQ's understanding of backwards-compatibility

    Backwards-compatibility is important to jOOQ. You've chosen jOOQ as a strategic SQL engine and you don't want your SQL to break. That is why there is at most one major release per year, which changes only those parts of jOOQ's API and functionality, which were agreed upon on the user group. During the year, only minor releases are shipped, adding new features in a backwards-compatible way @@ -2038,15 +2038,15 @@ DSL.using(sql.connection)

  • Overloading methods for convenience
  • Changing the type hierarchy of interfaces
  • - +

    It becomes obvious that it would be impossible to add new language elements (e.g. new , new ) to the API without breaking any client code that actually implements those interfaces. Hence, the following rule should be observed:

    - +

    jOOQ's DSL interfaces should not be implemented by client code! Extend only those extension points that are explicitly documented as "extendable" (e.g. )

    - +

    jOOQ-codegen and jOOQ-meta

    While a reasonable amount of care is spent to maintain these two modules under the rules of semantic versioning, it may well be that minor releases introduce backwards-incompatible changes. This will be announced in the respective release notes and should be the exception. @@ -2074,7 +2074,7 @@ DSL.using(sql.connection) - +

    The query DSL type @@ -2105,7 +2105,7 @@ DSL.using(sql.connection) // ... which is in fact the same as: DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    DSL subclasses @@ -2124,7 +2124,7 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME));
    - + @@ -2133,14 +2133,14 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    The DSLContext class

    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.

    - +

    Fluent creation of a DSLContext object

    The DSLContext object can be created fluently from the : @@ -2155,7 +2155,7 @@ DSLContext create = DSL.using(connection, dialect);]]>

    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

    A Configuration can be supplied with these objects: @@ -2174,7 +2174,7 @@ DSLContext create = DSL.using(connection, dialect);]]> - +

    Wrapping a Configuration object, a DSLContext can construct , for later . An example is given here:

    @@ -2216,7 +2216,7 @@ DSL.using(connection, dialect) CONNECT BY clause to the query */ -@Support({ SQLDialect.CUBRID, SQLDialect.}) +@Support({ SQLDialect.CUBRID, SQLDialect.ORACLE }) SelectConnectByConditionStep connectBy(Condition condition);]]>

    @@ -2238,7 +2238,7 @@ SelectSelectStep select(Field... fields);]]>

    Nevertheless, the IS DISTINCT FROM predicate is supported by jOOQ in all dialects, as its semantics can be expressed with an equivalent . For more details, see the manual's section about the .

    - +

    jOOQ and the Oracle SQL dialect

    Oracle SQL is much more expressive than many other SQL dialects. It features many unique keywords, clauses and functions that are out of scope for the SQL standard. Some examples for this are @@ -2262,13 +2262,13 @@ SelectSelectStep select(Field... fields);]]>

    In jOOQ 3.1, the notion of a SQLDialect.family() was introduced, in order to group several similar into a common family. An example for this is SQL Server, which is supported by jOOQ in various versions:

    - +
    • : The "version-less" SQL Server version. This always maps to the latest supported version of SQL Server
    • : The SQL Server version 2012
    • : The SQL Server version 2008
    - +

    In the above list, SQLSERVER is both a dialect and a family of three dialects. This distinction is used internally by jOOQ to distinguish whether to use the clause (SQL Server 2012), or whether to emulate it using ROW_NUMBER() OVER() (SQL Server 2008).

    @@ -2285,7 +2285,7 @@ SelectSelectStep select(Field... fields);]]>

    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.

    - +

    Interact with JDBC DataSources

    If you're in a J2EE or Spring context, however, you may wish to use a instead. Connections obtained from such a DataSource will be closed after query execution by jOOQ. The semantics of such a close operation should be the returning of the connection into a connection pool, not the actual closing of the underlying connection. Typically, this makes sense in an environment using distributed JTA transactions. An example of using DataSources with jOOQ can be seen in the tutorial section about . @@ -2293,17 +2293,17 @@ SelectSelectStep select(Field... fields);]]>

    Note, in this case, jOOQ will internally use a , which you can reference directly if you prefer that.

    - +

    Inject custom behaviour

    If your specific environment works differently from any of the above approaches, you can inject your own custom implementation of a ConnectionProvider into jOOQ. This is the API contract you have to fulfil:

    - + @@ -2313,19 +2313,19 @@ 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...

    - +
    - +

    Here is an example of how to use the custom data API. Let's assume that you have written an , that prevents INSERT statements, when a given flag is set to true:

    @@ -2335,10 +2335,10 @@ public class NoInsertListener extends DefaultExecuteListener { @Override public void start(ExecuteContext ctx) { - + // This listener is active only, when your custom flag is set to true 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) { throw new DataAccessException("No INSERT statements allowed"); @@ -2349,11 +2349,11 @@ public class NoInsertListener extends DefaultExecuteListener {

    See the manual's section about to learn more about how to implement an ExecuteListener.

    - +

    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:

    - + ExecuteListeners are a useful tool to...

    - +
    • implement custom logging
    • apply triggers written in Java
    • collect query execution statistics
    - +

    ExecuteListeners are hooked into your by returning them from an :

    @@ -2411,7 +2411,7 @@ configuration.set( new DefaultExecuteListenerProvider(new PerformanceLoggingListener()), new DefaultExecuteListenerProvider(new NoInsertListener()) );]]>
    - +

    See the manual's section about to see examples of such listener implementations.

    @@ -2452,22 +2452,22 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - +

    All Settings

    - +

    This section of the manual explains all the available Settings flags as available from the XSD specification.

    - + false - + ... @@ -2478,17 +2478,17 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - UPPER_CASED : UPPER - lower_cased : LOWER - CasedAsReportedByTheDatabase : AS_IS - + Defaults to "QUOTED" --> LOWER UPPER - + false @@ -2496,54 +2496,54 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - question marks : INDEXED - named parameters : NAMED - inlined values : INLINED - + Defaults to "INDEXED". - + This value is overridden by statementType == STATIC_STATEMENT, in case of which, this defaults to INLINED --> INDEXED - + PREPARED_STATEMENT - + true false true false ]]> - +

    More details

    - +

    Please refer to the jOOQ runtime configuration XSD for more details:
    http://www.jooq.org/xsd/jooq-runtime-{runtime-xsd-version}.xsd

    - +
    Runtime schema and table mapping @@ -2551,7 +2551,7 @@ DSLContext create = DSL.using(connection, dialect, settings);]]>

    You may wish to design your database in a way that you have several instances of your schema. This is useful when you want to cleanly separate data belonging to several customers / organisation units / branches / users and put each of those entities' data in a separate database or schema.

    - +

    In our AUTHOR example this would mean that you provide a book reference database to several companies, such as My Book World and Books R Us. In that case, you'll probably have a schema setup like this:

    @@ -2581,7 +2581,7 @@ create.selectFrom(AUTHOR).fetch();

    The query executed with a Configuration equipped with the above mapping will in fact produce this SQL statement:

    - + SELECT * FROM MY_BOOK_WORLD.AUTHOR

    Even if AUTHOR was generated from DEV. @@ -2656,7 +2656,7 @@ create.selectFrom(AUTHOR).fetch();

    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

    @@ -2690,7 +2690,7 @@ create.selectFrom(AUTHOR).fetch();

    Here is an example to illustrate what that means:

    - + 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) @@ -2762,7 +2762,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); @@ -2789,7 +2789,7 @@ query.addJoin(BOOK, BOOK.AUTHOR_ID.equal(AUTHOR.ID));]]>

    Note, that for historic reasons, the DSL API mixes mutable and immutable behaviour with respect to the internal representation of the being constructed. While creating , (such as functions) assumes immutable behaviour, creating does not. In other words, the following can be said:

    - + select2 = create.selectOne();]]>

    jOOQ does not explicitly support the asterisk operator in projections. However, you can omit the projection as in these examples:

    - +

    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:

    - + select(Collection> fields); public static SelectSelectStep select(Field... fields); @@ -2969,14 +2969,14 @@ public static SelectSelectStep> select(Field SelectSelectStep> select(Field field1, Field field2); public static SelectSelectStep> select(Field field1, Field field2, Field field3); // [...]]]> - +

    Since the generic R type is bound to some , the associated T type information can be used in various other contexts, e.g. the . Such a SELECT statement can be assigned typesafely:

    > s1 = create.select(BOOK.ID, BOOK.TITLE); Select> s2 = create.select(BOOK.ID, trim(BOOK.TITLE));]]> - +

    For more information about typesafe record types with degree up to {max-row-degree}, see the manual's section about .

    @@ -3002,7 +3002,7 @@ create.selectOne().from(BOOK.as("b"), AUTHOR.as("a"));]]>

    Read more about aliasing in the manual's section about .

    - +

    More advanced table expressions

    Apart from simple tables, you can pass any arbitrary to the jOOQ FROM clause. This may include in Oracle: @@ -3054,11 +3054,11 @@ DSL.using(SQLDialect.POSTGRES).selectOne().getSQL();]]>

  • NATURAL LEFT [ OUTER ] JOIN
  • NATURAL RIGHT [ OUTER ] JOIN
  • - +

    Besides, jOOQ also supports

    - +
    • CROSS APPLY (T-SQL and Oracle 12c specific)
    • OUTER APPLY (T-SQL and Oracle 12c specific)
    • @@ -3181,7 +3181,7 @@ ON BOOK.AUTHOR_ID = AUTHOR.ID]]>

      T-SQL has long known what the SQL standard calls lateral derived tables, lateral joins using the APPLY keyword. To every row resulting from the table expression on the left, we apply the table expression on the right. This is extremely useful for table-valued functions, which are also supported by jOOQ. Some examples:

      - + .where(BOOK.AUTHOR_ID.eq(AUTHOR.ID))) ) .fetch("c", int.class);]]> - +

      The above example shows standard usage of the LATERAL keyword to connect a derived table to the previous table in the . A similar statement can be written in T-SQL:

      - +

      Note that this syntax is also supported in the CUBRID database and might be emulated in other dialects supporting common table expressions in the future.

      - +

      ORDER SIBLINGS

      The Oracle database allows for specifying a SIBLINGS keyword in the . Instead of ordering the overall result, this will only order siblings among each other, keeping the hierarchy intact. An example is given here:

      - + .startWith(DIRECTORY.PARENT_ID.isNull()) .orderSiblingsBy(1);]]>
      - +
    @@ -3366,7 +3366,7 @@ GROUP BY AUTHOR_ID]]>

    Note, as defined in the SQL standard, when grouping, you may no longer project any columns that are not a formal part of the GROUP BY clause, or .

    - +

    MySQL's deviation from the SQL standard

    MySQL has a peculiar way of not adhering to this standard behaviour. This is documented in the MySQL manual. In short, with MySQL, you can also project any other field that is not part of the GROUP BY clause. The projected values will just be arbitrary values from within the group. You cannot rely on any ordering. For example: @@ -3397,7 +3397,7 @@ GROUP BY ()]]> .from(BOOK) .groupBy();]]> - +

    ROLLUP(), CUBE() and GROUPING SETS()

    Some databases support the SQL standard grouping functions and some extensions thereof. See the manual's section about for more details. @@ -3417,7 +3417,7 @@ GROUP BY ()]]> FROM BOOK GROUP BY AUTHOR_ID HAVING COUNT(*) >= 2]]> - @@ -3436,14 +3436,14 @@ HAVING COUNT(*) >= 4]]>

    - +
    The WINDOW clause

    The SQL:2003 standard as well as PostgreSQL and Sybase SQL Anywhere support a WINDOW clause that allows for specifying WINDOW frames for reuse in and .

    - + .window(w) .orderBy(AUTHOR.FIRST_NAME.desc());]]> - +

    Even if only PostgreSQL and Sybase SQL Anywhere natively support this great feature, jOOQ can emulate it by expanding any and types that you pass to the window() method - if the database supports window functions at all.

    - +

    Some more information about and the WINDOW clause can be found on our blog: http://blog.jooq.org/2013/11/03/probably-the-coolest-sql-feature-window-functions/

    @@ -3597,8 +3597,8 @@ ORDER BY CASE TITLE

    The SQL standard defines that a "query expression" can be ordered, and that query expressions can contain , whose subqueries cannot be ordered. While this is defined as such in the SQL standard, many databases allowing for the non-standard in one way or another, do not adhere to this part of the SQL standard. Hence, jOOQ allows for ordering all SELECT statements, regardless whether they are constructed as a part of a UNION or not. Corner-cases are handled internally by jOOQ, by introducing synthetic subselects to adhere to the correct syntax, where this is needed.

    - - + +

    Oracle's ORDER SIBLINGS BY clause

    jOOQ also supports Oracle's SIBLINGS keyword to be used with ORDER BY clauses for @@ -3647,7 +3647,7 @@ SELECT TOP 1 * FROM BOOK

    Things get a little more tricky in those databases that have no native idiom for OFFSET pagination (actual queries may vary):

    - + 1]]>

    As you can see, jOOQ will take care of the incredibly painful ROW_NUMBER() OVER() (or ROWNUM for Oracle) filtering in subselects for you, you'll just have to write limit(1).offset(2) in any dialect.

    - +

    Side-note: If you're interested in understanding why we chose ROWNUM for Oracle, please refer to this very interesting benchmark, comparing the different approaches of doing pagination in Oracle: http://www.inf.unideb.hu/~gabora/pagination/results.html.

    @@ -3695,7 +3695,7 @@ WHERE RN > 1]]>

    - +
    The SEEK clause @@ -3705,7 +3705,7 @@ WHERE RN > 1]]>

    A much faster and more stable way to perform paging is the so-called keyset paging method also called seek method. jOOQ supports a synthetic seek() clause, that can be used to perform keyset paging. Imagine we have these data:

    - + 1]]>

    Now, if we want to display page 6 to the user, instead of going to page 6 by using a record OFFSET, we could just fetch the record strictly after the last record on page 5, which yields the values (533, 2). This is how you would do it with SQL or with jOOQ:

    - +

    As you can see, the jOOQ SEEK clause is a synthetic clause that does not really exist in SQL. However, the jOOQ syntax is far more intuitive for a variety of reasons:

    - +
    • It replaces OFFSET where you would expect
    • It doesn't force you to mix regular predicates with "seek" predicates
    • It is typesafe
    • It emulates for you, in those databases that do not support them
    - +

    This query now yields:

    - +

    Note that you cannot combine the SEEK clause with the OFFSET clause.

    - +

    More information about this great feature can be found in the jOOQ blog:

    @@ -3774,11 +3774,11 @@ LIMIT 5]]>
  • http://blog.jooq.org/2013/10/26/faster-sql-paging-with-jooq-using-the-seek-method/
  • http://blog.jooq.org/2013/11/18/faster-sql-pagination-with-keysets-continued/
  • - +

    Further information about offset pagination vs. keyset pagination performance can be found on our partner page:

    - +
    No more offset @@ -3886,7 +3886,7 @@ SELECT * FROM author ORDER BY id DESC;]]>

    SQL allows to perform set operations as understood in standard set theory on result sets. These operations include unions, intersections, subtractions. For two subselects to be combinable by such a set operator, each subselect must return a of the same degree and type.

    - +

    UNION and UNION ALL

    These operators combine two results into one. While UNION removes all duplicate records resulting from this combination, UNION ALL leaves subselect results as they are. Typically, you should prefer UNION ALL over UNION, if you don't really need to remove duplicates. The following example shows how to use such a UNION operation in jOOQ. @@ -3899,12 +3899,12 @@ SELECT * FROM BOOK WHERE ID = 5]]> - +

    INTERSECT [ ALL ] and EXCEPT [ ALL ]

    INTERSECT is the operation that produces only those values that are returned by both subselects. EXCEPT is the operation that returns only those values that are returned exclusively in the first subselect. Both operators will remove duplicates from their results. The SQL standard allows to specify the ALL keyword for both of these operators as well, but this is hardly supported in any database. jOOQ does not support INTERSECT ALL, EXEPT ALL operations either.

    - +

    jOOQ's set operators and how they're different from standard SQL

    As previously mentioned in the manual's section about the , jOOQ has slightly changed the semantics of these set operators. While in SQL, a subselect may not contain any or (unless you wrap the subselect into a ), jOOQ allows you to do so. In order to select both the youngest and the oldest author from the database, you can issue the following statement with jOOQ (rendered to the MySQL dialect): @@ -3921,12 +3921,12 @@ UNION .union( create.selectFrom(AUTHOR) .orderBy(AUTHOR.DATE_OF_BIRTH.desc()).limit(1));]]> - +

    Projection typesafety for degrees between 1 and {max-row-degree}

    Two subselects that are combined by a set operator are required to be of the same degree and, in most databases, also of the same type. jOOQ 3.0's introduction of helps compile-checking these constraints:

    - + > s1 = select(BOOK.ID, BOOK.TITLE).from(BOOK); Select> s2 = selectOne(); @@ -3961,7 +3961,7 @@ s1.union(s4); // OK. The two Record[N] types match]]>

    Note that you can pass any string in the .hint() clause. If you use that clause, the passed string will always be put in between the SELECT [DISTINCT] keywords and the actual projection list. This can be useful in other databases too, such as MySQL, for instance:

    - +
    - +
    Lexical and logical SELECT clause order

    SQL has a lexical and a logical order of SELECT clauses. The lexical order of SELECT clauses is inspired by the English language. As SQL statements are commands for the database, it is natural to express a statement in an imperative tense, such as "SELECT this and that!".

    - +

    Logical SELECT clause order

    The logical order of SELECT clauses, however, does not correspond to the syntax. In fact, the logical order is this:

    - +
    • : First, all data sources are defined and joined
    • : Then, data is filtered as early as possible
    • @@ -3997,11 +3997,11 @@ FROM table1
    • : Then, a paging view is created for the ordered tuples
    • : Finally, pessimistic locking is applied
    - +

    The SQL Server documentation also explains this, with slightly different clauses:

    - +
    • FROM
    • ON
    • @@ -4015,16 +4015,16 @@ FROM table1
    • ORDER BY
    • TOP
    - +

    As can be seen, databases have to logically reorder a SQL statement in order to determine the best execution plan.

    - +

    Alternative syntaxes: LINQ, SLICK

    Some "higher-level" abstractions, such as C#'s LINQ or Scala's SLICK try to inverse the lexical order of SELECT clauses to what appears to be closer to the logical order. The obvious advantage of moving the SELECT clause to the end is the fact that the projection type, which is the record type returned by the SELECT statement can be re-used more easily in the target environment of the internal domain specific language.

    - +

    A LINQ example:

    @@ -4037,11 +4037,11 @@ Where p.UnitsInStock <= p.ReorderLevel AndAlso Not p.Discontinued // SELECT clause Select p]]> - +

    A SLICK example:

    - + .set(AUTHOR.ID, 101) .set(AUTHOR.FIRST_NAME, "Alfred") .set(AUTHOR.LAST_NAME, "Döblin"); - +

    As you can see, this syntax is a bit more verbose, but also more readable, as every field can be matched with its value. Internally, the two syntaxes are strictly equivalent.

    @@ -4140,7 +4140,7 @@ SELECT 101, 'Alfred', 'Döblin' FROM DUAL;

    The MySQL database supports a very convenient way to INSERT or UPDATE a record. This is a non-standard extension to the SQL syntax, which is supported by jOOQ and emulated in other RDBMS, where this is possible (i.e. if they support the SQL standard ). Here is an example how to use the ON DUPLICATE KEY UPDATE clause:

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, update the author's name create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -4149,11 +4149,11 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .set(AUTHOR.LAST_NAME, "Koontz");

    The synthetic ON DUPLICATE KEY IGNORE clause

    - +

    The MySQL database also supports an INSERT IGNORE INTO clause. This is supported by jOOQ using the more convenient SQL syntax variant of ON DUPLICATE KEY IGNORE, which can be equally emulated in other databases using a :

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, ignore the INSERT statement create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -4189,14 +4189,14 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    The INSERT SELECT statement

    - +

    In some occasions, you may prefer the INSERT SELECT syntax, for instance, when you copy records from one table to another:

    - + create.insertInto(AUTHOR_ARCHIVE) .select(create.selectFrom(AUTHOR).where(AUTHOR.DECEASED.isTrue())); - +
    @@ -4244,7 +4244,7 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    jOOQ supports formal in various contexts, among which the UPDATE statement. Only one row value expression can be updated at a time. Here's an example:

    - + UPDATE AUTHOR SET (FIRST_NAME, LAST_NAME) = @@ -4280,12 +4280,12 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    The above row value expressions usages are completely typesafe.

    - +

    UPDATE .. RETURNING

    The Firebird and Postgres databases support a RETURNING clause on their UPDATE statements, similar as the RETURNING clause in . This is useful to fetch trigger-generated values in one go. An example is given here:

    - +

    The H2 database ships with a somewhat less powerful but a little more intuitive syntax for its own version of the MERGE statement. An example more or less equivalent to the previous one can be seen here:

    - + -- Check if there is already an author called 'Hitchcock' -- If there is, rename him to John. If there isn't add him. @@ -4374,7 +4374,7 @@ VALUES ('John', 'Hitchcock') This syntax can be fully emulated by jOOQ for all other databases that support the SQL standard MERGE statement. For more information about the H2 MERGE syntax, see the documentation here:
    http://www.h2database.com/html/grammar.html#merge

    - +

    Typesafety of VALUES() for degrees up to {max-row-degree}

    Much like the , the MERGE statement's VALUES() clause provides typesafety for degrees up to {max-row-degree}, in both the standard syntax variant as well as the H2 variant. @@ -4396,7 +4396,7 @@ VALUES ('John', 'Hitchcock') TRUNCATE TABLE AUTHOR; create.truncate(AUTHOR).execute(); - +

    TRUNCATE is not supported by Ingres and SQLite. jOOQ will execute a DELETE FROM AUTHOR statement instead.

    @@ -4420,7 +4420,7 @@ VALUES ('John', 'Hitchcock')

    Most of the times, when thinking about a you're probably thinking about an actual table in your database schema. If you're using jOOQ's , you will have all tables from your database schema available to you as type safe Java objects. You can then use these tables in SQL , or in other , just like any other table expression. An example is given here:

    - + .from(AUTHOR) // Table expression AUTHOR .join(BOOK) // Table expression BOOK .on(AUTHOR.ID.equal(BOOK.AUTHOR_ID));]]> - +

    The above example shows how AUTHOR and BOOK tables are joined in a . It also shows how you can access by dereferencing the relevant Java attributes of their tables.

    @@ -4469,11 +4469,11 @@ create.select() .where(a.YEAR_OF_BIRTH.greaterThan(1920) .and(a.FIRST_NAME.equal("Paulo"))) .orderBy(b.TITLE);]]>
    - +

    As you can see in the above example, calling as() on generated tables returns an object of the same type as the table. This means that the resulting object can be used to dereference fields from the aliased table. This is quite powerful in terms of having your Java compiler check the syntax of your SQL statements. If you remove a column from a table, dereferencing that column from that table alias will cause compilation errors.

    - +

    Dereferencing columns from other table expressions

    Only few table expressions provide the SQL syntax typesafety as shown above, where generated tables are used. Most tables, however, expose their fields through field() methods: @@ -4485,12 +4485,12 @@ Table a = AUTHOR.as("a"); // Get fields from a: Field id = a.field("ID"); Field firstName = a.field("FIRST_NAME");]]> - +

    Derived column lists

    The SQL standard specifies how a table can be renamed / aliased in one go along with its columns. It references the term "derived column list" for the following syntax (as supported by Postgres, for instance):

    - + In jOOQ, you would simply specify a varargs list of column aliases as such:

    - + The that can be used in are the most powerful and best supported means of creating new in SQL. Informally, the following can be said:

    - + A(colA1, ..., colAn) "join" B(colB1, ..., colBm) "produces" C(colA1, ..., colAn, colB1, ..., colBm)

    @@ -4564,7 +4564,7 @@ create.select().from(values(

    jOOQ supports all of these JOIN types (except semi-join and anti-join) directly on any :

    - + table) @@ -4602,7 +4602,7 @@ Table naturalRightOuterJoin(TableLike)]]>

    Some databases allow for expressing in-memory temporary tables using a VALUES() constructor. This constructor usually works the same way as the VALUES() clause known from the or from the . With jOOQ, you can also use the VALUES() table constructor, to create tables that can be used in a :

    - + Note, that it is usually quite useful to provide column aliases ("derived column lists") along with the table alias for the VALUES() constructor.

    - +

    The above statement is emulated by jOOQ for those databases that do not support the VALUES() constructor, natively (actual emulations may vary):

    - + A can appear almost anywhere a can. Such a "nested SELECT" is often called a "derived table". Apart from many convenience methods accepting objects directly, a SELECT statement can always be transformed into a object using the asTable() method.

    - +

    Example: Scalar subquery

    - + SELECT * FROM BOOK @@ -4720,11 +4720,11 @@ create.select(AUTHOR.ID, books)

    If you are closely coupling your application to an Oracle database, you can take advantage of some Oracle-specific features, such as the PIVOT clause, used for statistical analyses. The formal syntax definition is as follows:

    - + -- SELECT .. FROM table PIVOT (aggregateFunction [, aggregateFunction] FOR column IN (expression [, expression])) -- WHERE .. - +

    The PIVOT clause is available from the type, as pivoting is done directly on a table. Currently, only Oracle's PIVOT clause is supported. Support for SQL Server's slightly different PIVOT clause will be added later. Also, jOOQ may emulate PIVOT for other dialects in the future.

    @@ -4787,7 +4787,7 @@ WHERE NOT EXISTS (

    The SQL standard specifies how SQL databases should implement ARRAY and TABLE types, as well as CURSOR types. Put simply, a CURSOR is a pointer to any materialised . Depending on the cursor's features, this table expression can be scrolled through in both directions, records can be locked, updated, removed, inserted, etc. Often, CURSOR types contain s, whereas ARRAY and TABLE types contain simple scalar values, although that is not a requirement

    - +

    ARRAY types in SQL are similar to Java's array types. They contain a "component type" or "element type" and a "dimension". This sort of ARRAY type is implemented in H2, HSQLDB and Postgres and supported by jOOQ as such. Oracle uses strongly-typed arrays, which means that an ARRAY type (VARRAY or TABLE type) has a name and possibly a maximum capacity associated with it.

    @@ -4870,12 +4870,12 @@ DSL.using(SQLDialect.SYBASE ).selectOne().getSQL();]]>

    Column expressions can be used in various SQL clauses in order to refer to one or several columns. This chapter explains how to form various types of column expressions with jOOQ. A particular type of column expression is given in the section about , where an expression may have a degree of more than one.

    - +

    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:

    - + field1 = BOOK.TITLE; @@ -4929,7 +4929,7 @@ ORDER BY BOOK.TITLE]]>

    Just like , columns can be renamed using aliases. Here is an example:

    - + SELECT FIRST_NAME || ' ' || LAST_NAME author, COUNT(*) books FROM AUTHOR JOIN BOOK ON AUTHOR.ID = AUTHOR_ID @@ -4938,21 +4938,21 @@ GROUP BY FIRST_NAME, LAST_NAME;

    Here is how it's done with jOOQ:

    - + Record record = create.select( concat(AUTHOR.FIRST_NAME, val(" "), AUTHOR.LAST_NAME).as("author"), count().as("books")) .from(AUTHOR) .join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID)) .groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME).fetchAny(); - +

    When you alias Fields like above, you can access those Fields' values using the alias name:

    - + System.out.println("Author : " + record.getValue("author")); System.out.println("Books : " + record.getValue("books")); - +
    @@ -4965,7 +4965,7 @@ System.out.println("Books : " + record.getValue("books"));

    Sometimes, this automatic mapping might not be what you needed, or jOOQ cannot know the type of a field. In those cases you would write SQL type CAST like this:

    - + -- Let's say, your Postgres column LAST_NAME was VARCHAR(30) -- Then you could do this: SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL @@ -4973,27 +4973,27 @@ SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL

    in jOOQ, you can write something like that:

    - + create.select(TAuthor.LAST_NAME.cast(PostgresDataType.TEXT));

    The same thing can be achieved by casting a Field directly to String.class, as TEXT is the default data type in Postgres to map to Java's String

    - + create.select(TAuthor.LAST_NAME.cast(String.class)); - +

    The complete CAST API in consists of these three methods:

    - + { // Cast this field to the type of another field Field cast(Field field); - + // Cast this field to a given DataType Field cast(DataType type); - + // Cast this field to the default DataType for a given Class Field cast(Class type); } @@ -5016,14 +5016,14 @@ public class DSL {

    A slightly different use case than are data type coercions, which are not rendered through to generated SQL. Sometimes, you may want to pretend that a numeric value is really treated as a string value, for instance when binding a numeric :

    - + field1 = val(1).coerce(String.class); Field field2 = val("1").coerce(Integer.class);]]>

    In the above example, field1 will be treated by jOOQ as a Field<String>, binding the numeric literal 1 as a VARCHAR value. The same applies to field2, whose string literal "1" will be bound as an INTEGER value.

    - +

    This technique is better than performing unsafe or rawtype casting in Java, if you cannot access the "right" field type from any given expression.

    @@ -5043,15 +5043,15 @@ Field field2 = val("1").coerce(Integer.class);]]>

    In order to express a SQL query like this one:

    - + SELECT ((1 + 2) * (5 - 3) / 2) % 10 FROM DUAL - +

    You can write something like this in jOOQ:

    - + create.select(val(1).add(2).mul(val(5).sub(3)).div(2).mod(10)); - +

    Operator precedence

    jOOQ does not know any operator precedence (see also ). All operations are evaluated from left to right, as with any object-oriented API. The two following expressions are the same: @@ -5079,14 +5079,14 @@ Field field2 = val("1").coerce(Integer.class);]]> - +

    String concatenation

    The SQL standard defines the concatenation operator to be an infix operator, similar to the ones we've seen in the chapter about . This operator looks like this: ||. Some other dialects do not support this operator, but expect a concat() function, instead. jOOQ renders the right operator / function, depending on your :

    - + SELECT 'A' || 'B' || 'C' FROM DUAL -- Or in MySQL: @@ -5114,13 +5114,13 @@ create.select(concat("A", "B", "C"));
  • NVL: Get the first non-null value among two arguments.
  • NVL2: Get the second argument if the first is null, or the third argument, otherwise.
  • - +

    Please refer to the for more details.

    - +
    Numeric functions @@ -5130,7 +5130,7 @@ create.select(concat("A", "B", "C"));

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ABS: Get the absolute value of a value.
    • ACOS: Get the arc cosine of a value.
    • @@ -5161,7 +5161,7 @@ create.select(concat("A", "B", "C"));
    • TANH: Get the hyperbolic tangent of a value.
    • TRUNC: Truncate the decimals off a given value.
    - +

    Please refer to the for more details.

    @@ -5186,13 +5186,13 @@ create.select(concat("A", "B", "C"));
  • SHL: Shift bits to the left
  • SHR: Shift bits to the right
  • - +

    Some background about bitwise operation emulation

    As stated before, not all databases support all of these bitwise operations. jOOQ emulates them wherever this is possible. More details can be seen in this blog post:
    http://blog.jooq.org/2011/10/30/the-comprehensive-sql-bitwise-operations-compatibility-list/

    - +
    @@ -5205,7 +5205,7 @@ create.select(concat("A", "B", "C"));

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ASCII: Get the ASCII code of a character.
    • BIT_LENGTH: Get the length of a string in bits.
    • @@ -5226,16 +5226,16 @@ create.select(concat("A", "B", "C"));
    • TRIM: Trim a string on both sides.
    • UPPER: Get a string in upper case letters.
    - +

    Please refer to the for more details.

    - +

    Regular expressions, REGEXP, REGEXP_LIKE, etc.

    Various databases have some means of searching through columns using regular expressions if the does not provide sufficient pattern matching power. While there are many different functions and operators in the various databases, jOOQ settled for the SQL:2008 standard REGEX_LIKE operator. Being an operator (and not a function), you should use the corresponding method on :

    - +

    @@ -5244,7 +5244,7 @@ create.select(concat("A", "B", "C")); - +

    Case sensitivity with strings @@ -5257,20 +5257,20 @@ create.select(concat("A", "B", "C"));

    For these ad-hoc ordering use-cases, most people resort to using LOWER() or UPPER() as follows:

    - + -- Case-insensitive filtering: -SELECT * FROM BOOK +SELECT * FROM BOOK WHERE upper(TITLE) = 'ANIMAL FARM' -- Case-insensitive ordering: -SELECT * +SELECT * FROM AUTHOR ORDER BY upper(FIRST_NAME), upper(LAST_NAME) // Case-insensitive filtering: create.selectFrom(BOOK) .where(upper(BOOK.TITLE).eq("ANIMAL FARM")).fetch(); - + // Case-insensitive ordering: create.selectFrom(AUTHOR) .orderBy(upper(AUTHOR.FIRST_NAME), upper(AUTHOR.LAST_NAME)) @@ -5287,7 +5287,7 @@ create.selectFrom(AUTHOR)

    This is a list of date and time functions supported by jOOQ's :

    - +
    • CURRENT_DATE: Get current date as a DATE object.
    • CURRENT_TIME: Get current time as a TIME object.
    • @@ -5297,7 +5297,7 @@ create.selectFrom(AUTHOR)
    • TIMESTAMP_ADD: Add a number of days or an interval to a timestamp.
    • TIMESTAMP_DIFF: Get the difference as an INTERVAL DAY TO SECOND between two dates.
    - +

    Intervals in jOOQ

    jOOQ fills a gap opened by JDBC, which neglects an important SQL data type as defined by the SQL standards: INTERVAL types. See the manual's section about for more details. @@ -5445,7 +5445,7 @@ GROUP BY AUTHOR_ID WindowOverStep rank(); WindowOverStep denseRank(); WindowOverStep percentRank(); - + // Windowing functions WindowIgnoreNullsStep firstValue(Field field); WindowIgnoreNullsStep lastValue(Field field) @@ -5461,7 +5461,7 @@ GROUP BY AUTHOR_ID // Statistical functions WindowOverStep cumeDist(); WindowOverStep ntile(int number);]]> - +

    SQL distinguishes between various window function types (e.g. "ranking functions"). Depending on the function, SQL expects mandatory PARTITION BY or ORDER BY clauses within the OVER() clause. jOOQ does not enforce those rules for two reasons:

    @@ -5476,14 +5476,14 @@ GROUP BY AUTHOR_ID

    Here are some simple examples of window functions with jOOQ:

    - + -- Sample uses of ROW_NUMBER() ROW_NUMBER() OVER() ROW_NUMBER() OVER(PARTITION BY 1) ROW_NUMBER() OVER(ORDER BY BOOK.ID) ROW_NUMBER() OVER(PARTITION BY BOOK.AUTHOR_ID ORDER BY BOOK.ID) - + -- Sample uses of FIRST_VALUE FIRST_VALUE(BOOK.ID) OVER() FIRST_VALUE(BOOK.ID IGNORE NULLS) OVER() @@ -5494,14 +5494,14 @@ rowNumber().over() rowNumber().over().partitionByOne() rowNumber().over().partitionBy(BOOK.AUTHOR_ID) rowNumber().over().partitionBy(BOOK.AUTHOR_ID).orderBy(BOOK.ID) - + // Sample uses of firstValue() firstValue(BOOK.ID).over() firstValue(BOOK.ID).ignoreNulls().over() firstValue(BOOK.ID).respectNulls().over()
    - +

    An advanced window function example

    Window functions can be used for things like calculating a "running total". The following example fetches transactions and the running total for every transaction going back to the beginning of the transaction table (ordered by booked_at). Window functions are accessible from the previously seen type using the over() method: @@ -5527,7 +5527,7 @@ firstValue(BOOK.ID).respectNulls().over()

    In the previous chapter about , we have seen the concept of "ordered-set aggregate functions", such as Oracle's LISTAGG(). These functions have a window function / analytical function variant, as well. For example:

    - + SELECT LISTAGG(TITLE, ', ') WITHIN GROUP (ORDER BY TITLE) @@ -5610,7 +5610,7 @@ ORDER BY 1 NULLS LAST, 2 NULLS LAST

    In English, the ROLLUP() grouping function provides N+1 groupings, when N is the number of arguments to the ROLLUP() function. Each grouping has an additional group field from the ROLLUP() argument field list. The results of the second query might look something like this:

    - + GROUPING SETS() and other grouping functions:
    http://msdn.microsoft.com/en-us/library/bb510427(v=sql.105)

    - +

    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:

    - + ... fields); GroupField cube(Field... fields); @@ -5713,7 +5713,7 @@ Field groupingId(Field...);]]>

    MySQL and CUBRID don't know any grouping functions, but they support a WITH ROLLUP clause, that is equivalent to simple ROLLUP() grouping functions. jOOQ emulates ROLLUP() in MySQL and CUBRID, by rendering this WITH ROLLUP clause. The following two statements mean the same:

    - + Some databases support user-defined functions, which can be embedded in any SQL statement, if you're using jOOQ's . Let's say you have the following simple function in Oracle SQL:

    - + The above function will be made available from a generated class. You can use it like any other :

    - + - +

    Note that user-defined functions returning or data types can also be used wherever can be used, if they are

    @@ -5765,7 +5765,7 @@ END echo;

    Some databases support user-defined aggregate functions, which can then be used along with or as . An example for such a database is Oracle. With Oracle, you can define the following OBJECT type (the example was taken from the Oracle 11g documentation):

    - +

    jOOQ's will detect such aggregate functions and generate them differently from regular . They implement the type, as mentioned in the manual's section about . Here's how you can use the SECOND_MAX() aggregate function with jOOQ:

    - +
    - +
    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:

    - + Row1 row(T1 t1) { ... } public static Row2 row(T1 t1, T2 t2) { ... } @@ -5992,12 +5992,12 @@ public static RowN row(Object... values) { ... }]]>

    See the relevant sections for more details about how to use row value expressions in predicates.

    - +

    Using row value expressions in UPDATE statements

    The also supports a variant where row value expressions are updated, rather than single columns. See the relevant section for more details

    - +

    Higher-degree row value expressions

    jOOQ chose to explicitly support degrees up to {max-row-degree} to match Scala's typesafe tuple, function and product support. Unlike Scala, however, jOOQ also supports higher degrees without the additional typesafety. @@ -6021,7 +6021,7 @@ public static RowN row(Object... values) { ... }]]>

  • The of a
  • The 's ON clause
  • - +

    Boolean types in SQL

    Before SQL:1999, boolean types did not really exist in SQL. They were modelled by 0 and 1 numeric/char values. With SQL:1999, true booleans were introduced and are now supported by most databases. In short, these are possible boolean values: @@ -6117,7 +6117,7 @@ Condition combined2 = combined1.andNot(c); // The left-hand side of the AND NOT

    Here are all boolean operators on the interface:

    - + < to test for being strictly less
  • <= to test for being less or equal
  • - +

    Unfortunately, Java does not support operator overloading, hence these operators are also implemented as methods in jOOQ, like any other SQL syntax elements. The relevant parts of the interface are these:

    - + ); // = (some column expression) eq or equal(Select>); // = (some scalar SELECT statement) @@ -6179,12 +6179,12 @@ ge or greaterOrEqual(Select>); // >= (some scalar SELECT st

    Note that every operator is represented by two methods. A verbose one (such as equal()) and a two-character one (such as eq()). Both methods are the same. You may choose either one, depending on your taste. The manual will always use the more verbose one.

    - +

    jOOQ's convenience methods using comparison operators

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using comparison predicates:

    - +
    - +
    Boolean operator precedence @@ -6211,7 +6211,7 @@ BOOK.TITLE.notEqualIgnoreCase("animal farm")]]>

    In SQL, the two expressions wouldn't be the same, as SQL natively knows operator precedence.

    - + A AND B OR C AND D OR E -- Precedence is applied (((A AND B) OR C) AND D) OR E -- Precedence is overridden @@ -6225,7 +6225,7 @@ BOOK.TITLE.notEqualIgnoreCase("animal farm")]]>

    All variants of the that we've seen in the previous chapter also work for . If your database does not support row value expression comparison predicates, jOOQ emulates them the way they are defined in the SQL standard:

    - + (X, Y))]]>

    jOOQ supports all of the above row value expression comparison predicates, both with and at the right-hand side:

    - +
    - +
    Quantified comparison predicate @@ -6322,7 +6322,7 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    It is interesting to note that the SQL standard defines the in terms of the ANY-quantified predicate. The following two expressions are equivalent:

    - + @@ -6333,14 +6333,14 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    - +
    NULL predicate

    In SQL, you cannot compare NULL with any value using , as the result would yield NULL again, which is neither TRUE nor FALSE (see also the manual's section about ). In order to test a for NULL, use the NULL predicate as such:

    - + @@ -6378,7 +6378,7 @@ NOT((A, B) IS NOT NULL)]]>

    The SQL standard contains a nice truth table for the above rules:

    - + +-----------------------+-----------+---------------+---------------+-------------------+ | Expression | R IS NULL | R IS NOT NULL | NOT R IS NULL | NOT R IS NOT NULL | +-----------------------+-----------+---------------+---------------+-------------------+ @@ -6392,13 +6392,13 @@ NOT((A, B) IS NOT NULL)]]>

    In jOOQ, you would simply use the isNull() and isNotNull() methods on row value expressions. Again, as with the , the row value expression NULL predicate is emulated by jOOQ, if your database does not natively support it:

    - +
    - +
    DISTINCT predicate @@ -6425,7 +6425,7 @@ BOOK.TITLE.isNotDistinctFrom(BOOK.SUB_TITLE)]]>

    If your database does not natively support the DISTINCT predicate, jOOQ emulates it with an equivalent , modelling the above truth table:

    - + The BETWEEN predicate can be seen as syntactic sugar for a pair of . According to the SQL standard, the following two predicates are equivalent:

    - + = [B] AND [A] <= [C]]]> @@ -6474,7 +6474,7 @@ BOOK.PUBLISHED_IN.notBetween(1920).and(1940)]]>

    The SQL standard defines the SYMMETRIC keyword to be used along with BETWEEN to indicate that you do not care which bound of the range is larger than the other. A database system should simply swap range bounds, in case the first bound is greater than the second one. jOOQ supports this keyword as well, emulating it if necessary.

    - + @@ -6485,7 +6485,7 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The emulation is done trivially:

    - + @@ -6500,27 +6500,27 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The SQL BETWEEN predicate also works well for . Much like the , it is defined in terms of a pair of regular :

    - + = [B] AND [A] <= [C] ([A] >= [B] AND [A] <= [C]) OR ([A] >= [C] AND [A] <= [B])]]> - +

    The above can be factored out according to the rules listed in the manual's section about .

    - +

    jOOQ supports the BETWEEN [SYMMETRIC] predicate and emulates it in all SQL dialects where necessary. An example is given here:

    - + - +
    - +
    LIKE predicate @@ -6541,7 +6541,7 @@ TITLE NOT LIKE '%abc%']]> - +

    Escaping operands with the LIKE predicate

    Often, your pattern may contain any of the wildcard characters "_" and "%", in case of which you may want to escape them. jOOQ does not automatically escape patterns in like() and notLike() methods. Instead, you can explicitly define an escape character as such: @@ -6560,12 +6560,12 @@ BOOK.TITLE.notLike("%The !%-Sign Book%", '!')]]>

    Please refer to your database manual for more details about escaping patterns with the LIKE predicate.

    - +

    jOOQ's convenience methods using the LIKE predicate

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using the LIKE predicate. Typical operations are "contains predicates", "starts with predicates", "ends with predicates", etc. Here is the full convenience API wrapping LIKE predicates:

    - + >) // Construct a NOT IN predicate from a subse

    A sample IN predicate might look like this:

    - + @@ -6618,12 +6618,12 @@ TITLE NOT IN ('Animal Farm', '1984')]]>
    BOOK.TITLE.notIn("Animal Farm", "1984")]]>
    - +

    NOT IN and NULL values

    Beware that you should probably not have any NULL values in the right hand side of a NOT IN predicate, as the whole expression would evaluate to NULL, which is rarely desired. This can be shown informally using the following reasoning:

    - + -- The following conditional expressions are formally or informally equivalent A NOT IN (B, C) A != ANY(B, C) @@ -6664,7 +6664,7 @@ NULL -- [ANY] AND NULL yields NULL -- Using a subselect (BOOK.ID, BOOK.TITLE) IN ( SELECT T.ID, T.TITLE - FROM T + FROM T )]]> - +

    In both cases, i.e. when using an IN list or when using a subselect, the type of the predicate is checked. Both sides of the predicate must be of equal degree and row type.

    - +

    - Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value. + Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value.

    - +
    EXISTS predicate @@ -6698,7 +6698,7 @@ row(BOOK.ID, BOOK.TITLE).in(
  • From a using
  • From a using , and from other clauses
  • - +

    An example of an EXISTS predicate can be seen here:

    @@ -6717,7 +6717,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

    - +

    Performance of IN vs. EXISTS

    In theory, the two types of predicates can perform equally well. If your database system ships with a sophisticated cost-based optimiser, it will be able to transform one predicate into the other, if you have all necessary constraints set (e.g. referential constraints, not null constraints). However, in reality, performance between the two might differ substantially. An interesting blog post investigating this topic on the MySQL database can be seen here:
    @@ -6725,7 +6725,7 @@ notExists(create.selectOne().from(BOOK)

    - +
    OVERLAPS predicate @@ -6763,7 +6763,7 @@ row(Date.valueOf('2010-01-01'), new DayToSecond(2)).overlaps(Date.valueOf('2010-

    Unlike the standard (or any database implementing the standard), jOOQ also supports the OVERLAPS predicate for comparing arbitrary . For instance, (1, 3) OVERLAPS (2, 4) will yield true in jOOQ. This is emulated as such

    - +
    - +
    Dynamic SQL

    In most cases, , , and as introduced in the previous chapters will be embedded into different SQL statement clauses as if the statement were a static SQL statement (e.g. in a view or stored procedure):

    - + - +

    It is, however, interesting to think of all of the above expressions as what they are: expressions. And as such, nothing keeps users from extracting expressions and referencing them from outside the statement. The following statement is exactly equivalent:

    @@ -6807,26 +6807,26 @@ create.select(select) .groupBy(groupBy) .orderBy() .fetch();]]> - +

    Each individual expression, and collection of expressions can be seen as an independent entity that can be

    - +
    1. Constructed dynamically
    2. Reused across queries
    - +

    Dynamic construction is particularly useful in the case of the , for dynamic predicate building. For instance:

    - +

    The dynamic SQL building power may be one of the biggest advantages of using a runtime query model like the one offered by jOOQ. Queries can be created dynamically, of arbitrary complexity. In the above example, we've just constructed a dynamic . The same can be done for any other clauses, including dynamic as needed.

    @@ -6862,7 +6862,7 @@ create.select()
  • - +

    You'll probably find other examples. If verbosity scares you off, don't worry. The verbose use-cases for jOOQ are rather rare, and when they come up, you do have an option. Just write SQL the way you're used to!

    @@ -6892,7 +6892,7 @@ Condition condition(String sql, Object... bindings); // Construct a condition taking other jOOQ object arguments // Example: condition("a = {0}", val(1)); 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 DSL:

    @@ -6950,7 +6950,7 @@ Result fetch(String sql, QueryPart... parts);]]>

    Apart from the general factory methods, plain SQL is also available in various other contexts. For instance, when adding a .where("a = b") clause to a query. Hence, there exist several convenience methods where plain SQL can be inserted usefully. This is an example displaying all various use-cases in one single query:

    - + LAST_NAME = create.field("a.LAST_NAME"); @@ -7009,7 +7009,7 @@ create.select(LAST_NAME, COUNT1, COUNT2) On a JDBC level, you can also reuse the SQL string and prepared statement object instead of constructing it again, as you can bind new values to the prepared statement. jOOQ currently does not cache prepared statements, internally. - +

    The following sections explain how you can introduce bind values in jOOQ, and how you can control the way they are rendered and bound to SQL.

    @@ -7022,7 +7022,7 @@ create.select(LAST_NAME, COUNT1, COUNT2)

    JDBC only knows indexed bind values. A typical example for using bind values with JDBC is this:

    - + With dynamic SQL, keeping track of the number of question marks and their corresponding index may turn out to be hard. jOOQ abstracts this and lets you provide the bind value right where it is needed. A trivial example is this:

    - + 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

    Should you decide to run the above query outside of jOOQ, using your own , you can do so as follows:

    - + select = create.select().from(BOOK).where(BOOK.ID.equal(5)).and(BOOK.TITLE.equal("Animal Farm")); // Render the SQL statement: @@ -7175,7 +7175,7 @@ create.select()

    Special care needs to be taken when using . While jOOQ's API allows you to specify bind values for use with plain SQL, you're not forced to do that. For instance, both of the following queries will lead to the same, valid result:

    - +

    A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] FROM AUTHOR JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID @@ -7318,15 +7318,15 @@ public final void toSQL(RenderContext context) {

    As mentioned in the previous chapter about , there are some elements in the that are used for formatting / pretty-printing rendered SQL. In order to obtain pretty-printed SQL, just use the following :

    - - + +

    And then, use the above DSLContext to render pretty-printed SQL:

    - + A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] WHERE AUTHOR.ID = ? -- [...] @@ -7415,7 +7415,7 @@ public final void bind(BindContext context) throws DataAccessException {

    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:

    - + extends AbstractField {} public abstract class CustomCondition extends AbstractCondition {} public abstract class CustomTable> extends TableImpl {} @@ -7424,7 +7424,7 @@ public abstract class CustomRecord> extends TableRecord

    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 and methods, as discussed before:

    - + 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 showing how to create a field multiplying another field by 2

    - + IDx2 = new CustomField(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(" * ?"); @@ -7464,10 +7464,10 @@ final Field IDx2 = new CustomField(BOOK.ID.getName(), BOOK.ID. @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(DSL.val(2)); } @@ -7486,7 +7486,7 @@ create.select(IDx2).from(BOOK);]]>

    Many vendor-specific functions are not officially supported by jOOQ, but you can implement such support yourself using CustomField, for instance. Here's an example showing how to implement Oracle's TO_CHAR() function, emulating it in SQL Server using CONVERT():

    - + { @@ -7528,7 +7528,7 @@ class ToChar extends CustomField {

    The above CustomField implementation can be exposed from your own custom DSL class:

    - + toChar(Field field, String format) { return new ToChar(field, DSL.inline(format)); @@ -7536,7 +7536,7 @@ class ToChar extends CustomField { }]]>
    - +
    Plain SQL QueryParts @@ -7550,7 +7550,7 @@ class ToChar extends CustomField {

    The above distinction is best explained using an example:

    - +

    - +
    Custom SQL transformation @@ -7598,7 +7598,7 @@ create.attach(select);]]> With jOOQ 3.2's SPI, it is possible to perform custom SQL transformation to implement things like shared-schema multi-tenancy, or a security layer centrally preventing access to certain data. This SPI is extremely powerful, as you can make ad-hoc decisions at runtime regarding local or global transformation of your SQL statement. The following sections show a couple of simple, yet real-world use-cases.

    - +
    Logging abbreviated bind values @@ -7606,7 +7606,7 @@ create.attach(select);]]>

    When implementing a logger, one needs to carefully assess how much information should really be disclosed on what logger level. In log4j and similar frameworks, we distinguish between FATAL, ERROR, WARN, INFO, DEBUG, and TRACE. In DEBUG level, jOOQ's logs all executed statements including inlined bind values as such:

    - + with bind values : select * from "BOOK" where "BOOK"."TITLE" like 'How I stopped worrying%']]> @@ -7622,7 +7622,7 @@ public class BindValueAbbreviator extends DefaultVisitListener { @Override public void visitStart(VisitContext context) { - + // Transform only when rendering values if (context.renderContext() != null) { QueryPart part = context.queryPart(); @@ -7636,16 +7636,16 @@ public class BindValueAbbreviator extends DefaultVisitListener { // e.g. using commons-lang's StringUtils.abbreviate() if (value instanceof String && ((String) value).length() > maxLength) { anyAbbreviations = true; - + // ... and replace it in the current rendering context (not in the Query) context.queryPart(val(abbreviate((String) value, maxLength))); } - + // If the bind value is a byte[] (or Blob) of a given length, abbreviate it // e.g. by removing bytes from the array else if (value instanceof byte[] && ((byte[]) value).length > maxLength) { anyAbbreviations = true; - + // ... and replace it in the current rendering context (not in the Query) context.queryPart(val(Arrays.copyOf((byte[]) value, maxLength))); } @@ -7655,10 +7655,10 @@ public class BindValueAbbreviator extends DefaultVisitListener { @Override public void visitEnd(VisitContext context) { - + // If any abbreviations were performed before... if (anyAbbreviations) { - + // ... and if this is the top-level QueryPart, then append a SQL comment to indicate the abbreviation if (context.queryPartsLength() == 1) { context.renderContext().sql(" -- Bind values may have been abbreviated"); @@ -7683,14 +7683,14 @@ public class BindValueAbbreviator extends DefaultVisitListener {
    - +
    SQL building in Scala

    jOOQ-Scala is a maven module used for leveraging some advanced Scala features for those users that wish to use jOOQ with Scala.

    - +

    Using Scala's implicit defs to allow for operator overloading

    The most obvious Scala feature to use in jOOQ are implicit defs for implicit conversions in order to enhance the type with SQL-esque operators. @@ -7698,7 +7698,7 @@ public class BindValueAbbreviator extends DefaultVisitListener {

    The following depicts a trait which wraps all fields:

    - + The following depicts a trait which wraps numeric fields:

    - + An example query using such overloaded operators would then look like this:

    - +

    In a previous section of the manual, we've seen how jOOQ can be used to that can be executed with any API including JDBC or ... jOOQ. This section of the manual deals with various means of actually executing SQL with jOOQ.

    - +

    SQL execution with JDBC

    JDBC calls executable objects "". It distinguishes between three types of statements: @@ -7838,7 +7838,7 @@ fetch]]>

    Today, the JDBC API may look weird to users being used to object-oriented design. While statements hide a lot of SQL dialect-specific implementation details quite well, they assume a lot of knowledge about the internal state of a statement. For instance, you can use the method, to add a the prepared statement being created to an "internal list" of batch statements. Instead of returning a new type, this method forces user to reflect on the prepared statement's internal state or "mode".

    - +

    jOOQ is wrapping JDBC

    These things are abstracted away by jOOQ, which exposes such concepts in a more object-oriented way. For more details about jOOQ's batch query execution, see the manual's section about . @@ -7860,7 +7860,7 @@ fetch]]>

  • Both APIs return the number of affected records in non-result queries. JDBC: , jOOQ:
  • Both APIs return a scrollable result set type from result queries. JDBC: , jOOQ:
  • - +

    Differences to JDBC

    Some of the most important differences between JDBC and jOOQ are listed here: @@ -7876,14 +7876,14 @@ fetch]]>

    - +
    Query vs. ResultQuery

    Unlike JDBC, jOOQ has a lot of knowledge about a SQL query's structure and internals (see the manual's section about ). Hence, jOOQ distinguishes between these two fundamental types of queries. While every can be executed, only can return results (see the manual's section about to learn more about fetching results). With plain SQL, the distinction can be made clear most easily:

    - + result = resultQuery.fetch();]]>
  • : Some databases allow for returning many result sets from a single query. JDBC can handle this but it's very verbose. A list of results should be returned instead.
  • : Some queries take too long to execute to wait for their results. You should be able to spawn query execution in a separate process.
  • - +

    Convenience and how ResultQuery, Result, and Record share API

    The term "fetch" is always reused in jOOQ when you can fetch data from the database. An provides many overloaded means of fetching data:

    - +

    Various modes of fetching

    These modes of fetching are also documented in subsequent sections of the manual

    - + fetch(); @@ -7945,7 +7945,7 @@ List> fetchMany(); // Execute a ResultQuery with jOOQ, but return a JDBC ResultSet, not a jOOQ object ResultSet fetchResultSet();]]> - +

    Fetch convenience

    These means of fetching are also available from and APIs @@ -7991,11 +7991,11 @@ ResultSet fetchResultSet();]]>

    These means of fetching are also available from and APIs

    - + Map fetchMap(Field key); Map fetchMap(Field key, Field value); @@ -8032,7 +8032,7 @@ ResultSet fetchResultSet();]]>

    jOOQ understands that SQL is much more expressive than Java, when it comes to the declarative typing of . As a declarative language, SQL allows for creating ad-hoc row value expressions (records with indexed columns, or tuples) and records (records with named columns). In Java, this is not possible to the same extent. Yet, still, sometimes you wish to use strongly typed records, when you know that you're selecting only from a single table

    - +

    Fetching strongly or weakly typed records

    When fetching data only from a single table, the type is known to jOOQ if you use jOOQ's to generate for your database tables. In order to fetch such strongly typed records, you will have to use the : @@ -8044,7 +8044,7 @@ BookRecord book = create.selectFrom(BOOK).where(BOOK.ID.equal(1)).fetchOne(); // Typesafe field access is now possible: 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:

    @@ -8090,7 +8090,7 @@ System.out.println("Published in: " + book.getPublishedIn());]]>

    By default, jOOQ returns an object, which is essentially a of . Often, you will find yourself wanting to transform this result object into a type that corresponds more to your specific needs. Or you just want to list all values of one specific column. Here are some examples to illustrate those use cases:

    - + titles1 = create.select().from(BOOK).fetch().getValues(BOOK.TITLE); List titles2 = create.select().from(BOOK).fetch(BOOK.TITLE); @@ -8125,7 +8125,7 @@ Map> group4 = create.selectFrom(BOOK).fetchGroups(BO

    In a more functional operating mode, you might want to write callbacks that receive records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + () {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -8160,7 +8160,7 @@ create.selectFrom(BOOK)

    In a more functional operating mode, you might want to write callbacks that map records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + ids = create.selectFrom(BOOK) @@ -8172,12 +8172,12 @@ create.selectFrom(BOOK) return book.getId(); } }); - + // Or more concisely create.selectFrom(BOOK) .orderBy(BOOK.ID) .fetch(new RecordMapper() {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -8203,7 +8203,7 @@ create.selectFrom(BOOK)

    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. See the manual's section about to see how to modify jOOQ's standard POJO mapping behaviour.

    - +

    Using JPA-annotated POJOs

    jOOQ tries to find JPA annotations on your POJO types. If it finds any, they are used as the primary source for mapping meta-information. Only the annotation is used and understood by jOOQ. An example: @@ -8213,7 +8213,7 @@ create.selectFrom(BOOK) public class MyBook { @Column(name = "ID") public int myId; - + @Column(name = "TITLE") public String myTitle; } @@ -8222,16 +8222,16 @@ public class MyBook { MyBook myBook = create.select().from(BOOK).fetchAny().into(MyBook.class); List myBooks = create.select().from(BOOK).fetch().into(MyBook.class); List myBooks = create.select().from(BOOK).fetchInto(MyBook.class);]]> - +

    Just as with any other JPA implementation, you can put the annotation on any class member, including attributes, setters and getters. Please refer to the Javadoc for more details.

    - +

    Using simple POJOs

    If jOOQ does not find any JPA-annotations, columns are mapped to the "best-matching" constructor, attribute or setter. An example illustrates this:

    - + myBooks = create.select().from(BOOK).fetchInto(MyBook1.class);]]><

    Please refer to the Javadoc for more details.

    - +

    Using "immutable" POJOs

    If jOOQ does not find any default constructor, columns are mapped to the "best-matching" constructor. This allows for using "immutable" POJOs with jOOQ. An example illustrates this:

    - + myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchInto( public class MyBook3 { public final String title; public final int id; - + @ConstructorProperties({ "title", "id"}) public MyBook2(String title, int id) { this.title = title; @@ -8286,7 +8286,7 @@ MyBook3 myBook = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchA List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetch().into(MyBook3.class); List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchInto(MyBook3.class); ]]> - +

    Please refer to the Javadoc for more details.

    @@ -8295,12 +8295,12 @@ List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchI

    jOOQ also allows for fetching data into abstract classes or interfaces, or in other words, "proxyable" types. This means that jOOQ will return a wrapped in a implementing your custom type. An example of this is given here:

    - + - +

    Note: Because of your manual setting of ID = 10, jOOQ's store() method will asume that you want to insert a new record. See the manual's section about for more details on this.

    - +

    Interaction with DAOs

    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: @@ -8367,21 +8367,21 @@ bookDao.update(book); // Delete it again bookDao.delete(book);]]> - +

    More complex data structures

    jOOQ currently doesn't support more complex data structures, the way Hibernate/JPA attempt to map relational data onto POJOs. While future developments in this direction are not excluded, jOOQ claims that generic mapping strategies lead to an enormous additional complexity that only serves very few use cases. You are likely to find a solution using any of jOOQ's various , with only little boiler-plate code on the client side.

    - +
    POJOs with RecordMappers

    In the previous sections we have seen how to create types to map jOOQ records onto arbitrary objects. We have also seen how jOOQ provides default algorithms to map jOOQ records onto . Your own custom domain model might be much more complex, but you want to avoid looking up the most appropriate RecordMapper every time you need one. For this, you can provide jOOQ's with your own implementation of the interface. An example is given here:

    - + } } } - + // Books might be joined with their authors, create a 1:1 mapping if (type == Book.class) { return new BookMapper(); @@ -8418,7 +8418,7 @@ bookDao.delete(book);]]>

    The above is a very simple example showing that you will have complete flexibility in how to override jOOQ's record to POJO mapping mechanisms.

    - +

    If you're looking into a generic, third-party mapping utility, have a look at ModelMapper, or Orika Mapper, which can both be easily integrated with jOOQ.

    @@ -8431,7 +8431,7 @@ bookDao.delete(book);]]>

    Unlike JDBC's , jOOQ's does not represent an open database cursor with various fetch modes and scroll modes, that needs to be closed after usage. jOOQ's results are simple in-memory Java objects, containing all of the result values. If your result sets are large, or if you have a lot of network latency, you may wish to fetch records one-by-one, or in small chunks. jOOQ supports a type for that purpose. In order to obtain such a reference, use the method. An example is given here:

    - + cursor = null; @@ -8441,7 +8441,7 @@ try { // Cursor has similar methods as Iterator while (cursor.hasNext()) { BookRecord book = cursor.fetchOne(); - + Util.doThingsWithBook(book); } } @@ -8456,7 +8456,7 @@ finally {

    As a holds an internal reference to an open , it may need to be closed at the end of iteration. If a cursor is completely scrolled through, it will conveniently close the underlying ResultSet. However, you should not rely on that.

    - +

    Cursors ship with all the other fetch features

    Like or , gives access to all of the other fetch features that we've seen so far, i.e. @@ -8498,7 +8498,7 @@ finally {

    The correct (and verbose) way to do this with JDBC is as follows:

    - +

    As previously discussed in the chapter about , jOOQ does not rely on an internal state of any JDBC object, which is "externalised" by Javadoc. Instead, it has a straight-forward API allowing you to do the above in a one-liner:

    - + > results = create.fetchMany("sp_help 'author'");]]> @@ -8539,22 +8539,22 @@ List> results = create.fetchMany("sp_help 'author'");]]>
    Later fetching

    Using Java 8 CompletableFutures

    - +

    Java 8 has introduced the new type, which allows for functional composition of asynchronous execution units. When applying this to SQL and jOOQ, you might be writing code as follows:

    - + + .supplyAsync(() -> DSL.using(configuration) .insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .values(3, "Hitchcock") .execute() ) - + // This will supply an AuthorRecord value for the newly inserted author .handleAsync((rows, throwable) -> DSL.using(configuration) @@ -8567,30 +8567,30 @@ CompletableFuture record.changed(true); return record.insert(); }) - + // This will supply an int value indicating the number of deleted rows - .handleAsync((rows, throwable) -> + .handleAsync((rows, throwable) -> DSL.using(configuration) .delete(AUTHOR) .where(AUTHOR.ID.eq(3)) .execute() ) .join();]]> - +

    The above example will execute four actions one after the other, but asynchronously in the JDK's default or common . -

    - +

    +

    For more information, please refer to the Javadoc and official documentation. -

    - +

    +

    Using deprecated API

    - +

    Some queries take very long to execute, yet they are not crucial for the continuation of the main program. For instance, you could be generating a complicated report in a Swing application, and while this report is being calculated in your database, you want to display a background progress bar, allowing the user to pursue some other work. This can be achived simply with jOOQ, by creating a , a type that extends . An example is given here:

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(); @@ -8606,7 +8606,7 @@ Result result = future.get();]]>

    Note, that instead of letting jOOQ spawn a new thread, you can also provide jOOQ with your own :

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(service);]]> @@ -8620,7 +8620,7 @@ FutureResult future = create.selectFrom(BOOK).where(... complex pred

    When interacting with legacy applications, you may prefer to have jOOQ return a , rather than jOOQ's own types. This can be done simply, in two ways:

    - + cursor = create.fetchLazy(rs);]]>

    You can also tighten the interaction with jOOQ's data type system and features, by passing the record type to the above fetch methods:

    - + result = create.fetch (rs, Integer.class, String.class); Cursor result = create.fetchLazy(rs, Integer.class, String.class); @@ -8682,7 +8682,7 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Apart from a few extra features (), jOOQ only supports basic types as supported by the JDBC API. In your application, you may choose to transform these data types into your own ones, without writing too much boiler-plate code. This can be done using jOOQ's types. A converter essentially allows for two-way conversion between two Java data types <T> and <U>. By convention, the <T> type corresponds to the type in your database whereas the <U> type corresponds to your own user type. The Converter API is given here:

    - + extends Serializable { /** @@ -8709,12 +8709,12 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Such a converter can be used in many parts of the jOOQ API. Some examples have been illustrated in the manual's section about .

    - +

    A Converter for GregorianCalendar

    Here is a some more elaborate example involving a Converter for :

    - + { @@ -8745,12 +8745,12 @@ public class CalendarConverter implements Converter dates1 = create.selectFrom(BOOK).fetch().getValues(BOOK.PUBLISHING_DATE, new CalendarConverter()); List dates2 = create.selectFrom(BOOK).fetch(BOOK.PUBLISHING_DATE, new CalendarConverter()); ]]> - +

    Enum Converters

    jOOQ ships with a built-in default , that you can use to map VARCHAR values to enum literals or NUMBER values to enum ordinals (both modes are supported). Let's say, you want to map a YES / NO / MAYBE column to a custom Enum:

    - + - +

    Using Converters in generated source code

    jOOQ also allows for generated source code to reference your own custom converters, in order to permanently replace a <T> type by your own, custom <U> type. See the manual's section about for details. @@ -8812,20 +8812,20 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE) .join(AUTHOR).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) .intern(BOOK.AUTHOR_ID) .fetch();]]> - +

    You can specify as many fields as you want for interning. The above has the following effect:

    - +
    • If the interned Field is of type , then is called upon each string
    • If the interned Field is of any other type, then the call is ignored
    - +

    Future versions of jOOQ will implement interning of data for non-String data types by collecting values in , removing duplicate instances.

    - +

    Note, that jOOQ will not use interned data for identity comparisons: string1 == string2. Interning is used only to reduce the memory footprint of objects.

    @@ -8833,7 +8833,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)
    - +
    Static statements vs. Prepared Statements @@ -8843,7 +8843,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)

    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:

    - + @@ -8873,7 +8873,7 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    Whichever aproach is more optimal for you cannot be decided by jOOQ. In most cases, prepared statements are probably better. But you always have the option of forcing jOOQ to render inlined bind values.

    - +

    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 @@ -8887,15 +8887,15 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    As previously discussed in the chapter about , reusing PreparedStatements is handled a bit differently in jOOQ from how it is handled in JDBC

    - +

    Keeping open PreparedStatements with JDBC

    With JDBC, you can easily reuse a by not closing it between subsequent executions. An example is given here:

    - + The above technique can be quite useful when you want to reuse expensive database resources. This can be the case when your statement is executed very frequently and your database would take non-negligible time to soft-parse the prepared statement and generate a new statement / cursor resource.

    - +

    Keeping open PreparedStatements with jOOQ

    This is also modeled in jOOQ. However, the difference to JDBC is that closing a statement is the default action, whereas keeping it open has to be configured explicitly. This is better than JDBC, because the default action should be the one that is used most often. Keeping open statements is rarely done in average applications. Here's an example of how to keep open PreparedStatements with jOOQ:

    - + query = create.selectOne().keepStatement(true); @@ -8929,7 +8929,7 @@ finally {

    The above example shows how a query can be executed twice against the same underlying PreparedStatement. Unlike in other execution scenarios, you must not forget to close this query now

    - +

    Beware of resource leaks

    While jOOQ allows for explicitly keeping open PreparedStatement references in Query instances, the JDBC Connection may still be closed independently without jOOQ or the PreparedStatement noticing. It is the user's responsibility to close all resources according to the specification and behaviour of the concrete JDBC driver and the underlying database. @@ -8943,7 +8943,7 @@ finally {

    JDBC knows a couple of execution flags and modes, which can be set through the jOOQ API as well. jOOQ essentially supports these flags and execution modes:

    - + - + extends Query { // [...] @@ -8976,25 +8976,25 @@ finally { // The maximum number of rows to be fetched by JDBC // ----------------------------------------------------------- ResultQuery maxRows(int rows); - + }]]>

    Using ResultSet concurrency with ExecuteListeners

    An example of why you might want to manually set a ResultSet's concurrency flag to something non-default is given here:

    - + - +

    In the above example, your custom is triggered before jOOQ loads a new Record from the JDBC ResultSet. With the concurrency being set to ResultSet.CONCUR_UPDATABLE, you can now modify the database cursor through the standard JDBC ResultSet API.

    @@ -9112,18 +9112,18 @@ create.batch(create.insertInto(AUTHOR, ID, FIRST_NAME, LAST_NAME ).values((Inte

    Instead of actually phrasing a select statement, you can also use the convenience methods:

    - + - +

    Inlining sequence references in SQL

    You can inline sequence references in jOOQ SQL statements. The following are examples of how to do that:

    - + The general distinction between (stored) procedures and (stored) functions can be summarised like this:

    - +

    Procedures

    • Are called using JDBC CallableStatement
    • Have no return value
    • Usually support OUT parameters
    - +

    Functions

    • Can be used in SQL statements
    • Have a return value
    • Usually don't support OUT parameters
    - +

    Exceptions to these rules

    • DB2, H2, and HSQLDB don't allow for JDBC escape syntax when calling functions. Functions must be used in a SELECT statement
    • @@ -9183,19 +9183,19 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

      To simplify things a little bit, jOOQ handles both procedures and functions the same way, using a more general type.

      - +

      Using jOOQ for standalone calls to stored procedures and functions

      If you're using jOOQ's , it will generate objects for you. Let's consider the following example:

      - +

      The generated artefacts can then be used as follows:

      - + - +

      But you can also call the procedure using a generated convenience method in a global Routines class:

      @@ -9222,7 +9222,7 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]>

      For more details about for procedures, see the manual's section about .

      - +

      Inlining stored function references in SQL

      Unlike procedures, functions can be inlined in SQL statements to generate or , if you're using . Assume you have a function like this: @@ -9230,11 +9230,11 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]> - +

      The generated artefacts can then be used as follows:

      - + boolean exists = create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]> - +

      For more info about inlining stored function references in SQL statements, please refer to the manual's section about .

      @@ -9275,7 +9275,7 @@ create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]>

      Oracle UDTs can have object-oriented structures including member functions and procedures. With Oracle, you can do things like this:

      - + {"name":"field-n","type":"type-n"}], "records":[[value-1-1,value-1-2,...,value-1-n], [value-2-1,value-2-2,...,value-2-n]]} - +

      Note: This format has changed in jOOQ 2.6.0

      @@ -9590,7 +9590,7 @@ Query query = error.query();]]>
    - +
    Importing JSON @@ -9649,12 +9649,12 @@ create.loadInto(BOOK)

    CRUD always uses the same patterns, regardless of the nature of underlying tables. This again, leads to a lot of boilerplate code, if you have to issue your statements yourself. Like Hibernate / JPA and other ORMs, jOOQ facilitates CRUD using a specific API involving types.

    - +

    Primary keys and updatability

    In normalised databases, every table has a primary key by which a tuple/record within that table can be uniquely identified. In simple cases, this is a (possibly auto-generated) number called ID. But in many cases, primary keys include several non-numeric columns. An important feature of such keys is the fact that in most databases, they are enforced using an index that allows for very fast random access to the table. A typical way to access / modify / delete a book is this:

    - + - +

    Normalised databases assume that a primary key is unique "forever", i.e. that a key, once inserted into a table, will never be changed or re-inserted after deletion. In order to use jOOQ's operations correctly, you should design your database accordingly.

    @@ -9675,7 +9675,7 @@ DELETE FROM BOOK WHERE ID = 5;]]>

    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:

    - + - +

    See the manual's section about for some more insight on "attached" objects.

    - +

    Storing

    Storing a record will perform an or an . In general, new records are always inserted, whereas records loaded from the database are always updated. This is best visualised in code: @@ -9714,7 +9714,7 @@ BookRecord book2 = create.fetchOne(BOOK, BOOK.ID.equal(id)); // Update the record: UPDATE BOOK SET TITLE = 'Animal Farm' WHERE ID = [id] book2.setTitle("Animal Farm"); book2.store();]]> - +

    Some remarks about storing:

    @@ -9724,18 +9724,18 @@ book2.store();]]>
  • When loading records from , jOOQ will assume the record is a new record. It will hence attempt to INSERT it.
  • When you activate , storing a record may fail, if the underlying database record has been changed in the mean time.
  • - +

    Deleting

    Deleting a record will remove it from the database. Here's how you delete records:

    - + - +

    Refreshing

    Refreshing a record from the database means that jOOQ will issue a to refresh all record values that are not the primary key. This is particularly useful when you use jOOQ's feature, in case a modified record is "stale" and cannot be stored to the database, because the underlying database record has changed in the mean time. @@ -9754,7 +9754,7 @@ book.refresh();]]>

    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 :

    - + The "original" value, i.e. the value as it was originally fetched from the database or null, if the record was never in the database
  • The "changed" flag, indicating if the value was ever changed through the Record API.
  • - +

    The purpose of the above information is for jOOQ's to know, which values need to be stored to the database, and which values have been left untouched.

    @@ -9790,19 +9790,19 @@ for (BookRecord book : create.fetch(BOOK, BOOK.PUBLISHED_IN.equal(1948))) {

    Many databases support the concept of IDENTITY values, or key values. This is reflected by JDBC's method. jOOQ abstracts using this method as many databases and JDBC drivers behave differently with respect to generated keys. Let's assume the following SQL Server BOOK table:

    - +

    If you're using jOOQ's , the above table will generate a with an IDENTITY column. This information is used by jOOQ internally, to update IDs after calling :

    - +

    and contain foreign key navigation methods. These navigation methods allow for "navigating" inbound or outbound foreign key references by executing an appropriate query. An example is given here:

    - + books = author.fetchChildren(FK_BOOK_AUTHOR);]]>

    Tables without a PRIMARY KEY are considered non-updatable by jOOQ, as jOOQ has no way of uniquely identifying such a record within the database. If you're using jOOQ's , such tables will generate classes, instead of classes. When you fetch from such a table, the returned records will not allow for calling any of the methods.

    - +

    Note, that some databases use internal rowid or object-id values to identify such records. jOOQ does not support these vendor-specific record meta-data.

    @@ -9933,7 +9933,7 @@ Result books = author.fetchChildren(FK_BOOK_AUTHOR);]]>
    - +

    Optimised optimistic locking using TIMESTAMP fields

    If you're using jOOQ's , you can take indicate TIMESTAMP or UPDATE COUNTER fields for every generated table in the . Let's say we have this table:

    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:

    - +

    As before, without the added TIMESTAMP column, optimistic locking is transparent to the API.

    - +

    Optimised optimistic locking using VERSION fields

    Instead of using TIMESTAMPs, you may also use numeric VERSION fields, containing version numbers that are incremented by jOOQ upon store() calls. @@ -10002,7 +10002,7 @@ book2.store();]]>

    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:

    - + books = create.fetch(BOOK); @@ -10018,7 +10018,7 @@ create.batchStore(books);]]>

    - +
    CRUD SPI: RecordListener @@ -10029,11 +10029,11 @@ create.batchStore(books);]]>
  • Adding a central ID generation algorithm, generating UUIDs for all of your records.
  • Adding a central record initialisation mechanism, preparing the database prior to inserting a new record.
  • - +

    An example of such a RecordListener is given here:

    - + - +

    Now, configure jOOQ's runtime to load your listener

    @@ -10073,7 +10073,7 @@ DSLContext create = DSL.using(configuration);]]>

    If you're using jOOQ's , you can configure it to generate and DAOs for you. jOOQ then generates one DAO per , i.e. per table with a single-column primary key. Generated DAOs implement a common jOOQ type called . This type contains the following methods:

    - + corresponds to the DAO's related table //

    corresponds to the DAO's related generated POJO type // corresponds to the DAO's related table's primary key type. @@ -10084,23 +10084,23 @@ public interface DAO, P, T> { void insert(P object) throws DataAccessException; void insert(P... objects) throws DataAccessException; void insert(Collection

    objects) throws DataAccessException; - + // These methods allow for updating POJOs based on their primary key void update(P object) throws DataAccessException; void update(P... objects) throws DataAccessException; void update(Collection

    objects) throws DataAccessException; - + // These methods allow for deleting POJOs based on their primary key void delete(P... objects) throws DataAccessException; void delete(Collection

    objects) throws DataAccessException; void deleteById(T... ids) throws DataAccessException; void deleteById(Collection ids) throws DataAccessException; - + // These methods allow for checking record existence boolean exists(P object) throws DataAccessException; boolean existsById(T id) throws DataAccessException; long count() throws DataAccessException; - + // These methods allow for retrieving POJOs by primary key or by some other field List

    findAll() throws DataAccessException; P findById(T id) throws DataAccessException; @@ -10129,7 +10129,7 @@ public class BookDao extends DAOImpl {

    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:

    - +

    With jOOQ, it's simple. All of jOOQ's exceptions are "system exceptions", hence they are all unchecked.

    - +

    jOOQ's DataAccessException

    jOOQ uses its own to wrap any underlying that might have occurred. Note that all methods in jOOQ that may cause such a DataAccessException document this both in the Javadoc as well as in their method signature. @@ -10180,7 +10180,7 @@ bookDao.delete(book);]]>

  • InvalidResultException: An operation was performed expecting only one result, but several results were returned.
  • MappingException: Something went wrong when loading a record from a or when mapping a record into a POJO
  • - +

    Override jOOQ's exception handling

    The following section about documents means of overriding jOOQ's exception handling, if you wish to deal separately with some types of constraint violations, or if you raise business errors from your database, etc. @@ -10197,7 +10197,7 @@ bookDao.delete(book);]]>

    For convenience and better backwards-compatibility, consider extending instead of implementing this interface.

    - +

    Example: Query statistics ExecuteListener

    Here is a sample implementation of an ExecuteListener, that is simply counting the number of queries per type that are being executed using jOOQ: @@ -10214,11 +10214,11 @@ public class StatisticsListener extends DefaultExecuteListener { public void start(ExecuteContext ctx) { synchronized (STATISTICS) { Integer count = STATISTICS.get(ctx.type()); - + if (count == null) { count = 0; } - + STATISTICS.put(ctx.type(), count + 1); } } @@ -10261,7 +10261,7 @@ for (ExecuteType type : ExecuteType.values()) {

    Please read the for more details

    - +

    Example: Custom Logging ExecuteListener

    The following depicts an example of a custom ExecuteListener, which pretty-prints all queries being executed by jOOQ to stdout: @@ -10284,7 +10284,7 @@ public class PrettyPrinter extends DefaultExecuteListener { // Create a new DSLContext for logging rendering purposes // This DSLContext doesn't need a connection, only the SQLDialect... DSLContext create = DSL.using(ctx.configuration().dialect(), - + // ... and the flag for pretty-printing new Settings().withRenderFormatted(true)); @@ -10292,12 +10292,12 @@ public class PrettyPrinter extends DefaultExecuteListener { if (ctx.query() != null) { System.out.println(create.renderInlined(ctx.query())); } - + // If we're executing a routine else if (ctx.routine() != null) { System.out.println(create.renderInlined(ctx.routine())); } - + // If we're executing anything else (e.g. plain SQL) else if (!StringUtils.isBlank(ctx.sql())) { System.out.println(ctx.sql()); @@ -10307,12 +10307,12 @@ public class PrettyPrinter extends DefaultExecuteListener {

    See also the manual's sections about for more sample implementations of actual ExecuteListeners.

    - +

    Example: Bad query execution ExecuteListener

    You can also use ExecuteListeners to interact with your SQL statements, for instance when you want to check if executed or statements contain a WHERE clause. This can be achieved trivially with the following sample ExecuteListener:

    - + 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:

    - + @@ -10364,7 +10364,7 @@ public class DeleteOrUpdateWithoutWhereException extends RuntimeException {}

    With the above configuration, let's fetch some data with jOOQ

    - +

    @@ -10412,7 +10412,7 @@ Finishing : Total: 4.814ms, +3.375ms

  • 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
  • - +

    Optimise wisely

    Don't be put off by the above paragraphs. You should optimise wisely, i.e. only in places where you really need very high throughput to your database. jOOQ's overhead compared to plain JDBC is typically less than 1ms per query. @@ -10469,7 +10469,7 @@ Finishing : Total: 4.814ms, +3.375ms

    You need to tell jOOQ some things about your database connection. Here's an example of how to do it for an Oracle database

    - + @@ -10478,7 +10478,7 @@ Finishing : Total: 4.814ms, +3.375ms jdbc:oracle:thin:@[your jdbc connection parameters] [your database user] [your database password] - + user[db-user] @@ -10538,7 +10538,7 @@ Finishing : Total: 4.814ms, +3.375ms @@ -10559,13 +10559,13 @@ Finishing : Total: 4.814ms, +3.375ms

    Code generation works by calling this class with the above property file as argument.

    - + org.jooq.util.GenerationTool /jooq-config.xml

    Be sure that these elements are located on the classpath:

    - +
    • The XML configuration file
    • jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar
    • @@ -10590,7 +10590,7 @@ Finishing : Total: 4.814ms, +3.375ms
    • this example uses jOOQ's log4j support by adding log4j.xml and log4j.jar to the project classpath.
    • the actual jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar artefacts may contain version numbers in the file names.
    - +
    Eclipse configuration
    @@ -10734,7 +10734,7 @@ Finishing : Total: 4.814ms, +3.375ms optimistic locking (A Java regular expression. Use the pipe to separate several expressions). See UpdatableRecord.store() and UpdatableRecord.delete() for details --> REC_TIMESTAMP - + @@ -10836,30 +10836,30 @@ Finishing : Total: 4.814ms, +3.375ms false - + true - + false ]]>
    @@ -10868,7 +10868,7 @@ Finishing : Total: 4.814ms, +3.375ms

    Some of the above properties depend on other properties to work correctly. For instance, when generating immutable pojos, pojos must be generated. jOOQ will enforce such properties even if you tell it otherwise. Here is a list of property interdependencies:

    - +
    • When daos = true, then jOOQ will set relations = true
    • When daos = true, then jOOQ will set records = true
    • @@ -10877,7 +10877,7 @@ Finishing : Total: 4.814ms, +3.375ms
    - +
    Programmatic generator configuration @@ -10885,7 +10885,7 @@ Finishing : Total: 4.814ms, +3.375ms

    In the previous sections, we have covered how to set up jOOQ's code generator using XML, either by running a standalone Java application, or by using Maven. However, it is also possible to use jOOQ's GenerationTool programmatically. The XSD file used for the configuration (http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd) is processed using XJC to produce Java artefacts. The below example uses those artefacts to produce the equivalent configuration of the previous :

    - +

    - +
    Custom generator strategies @@ -10922,7 +10922,7 @@ GenerationTool.main(configuration);]]>

    jOOQ allows you to override default implementations of the code generator or the generator strategy. Specifically, the latter can be very useful if you want to inject custom behaviour into jOOQ's code generator with respect to naming classes, members, methods, and other Java objects.

    - + @@ -11147,58 +11147,58 @@ public class Book implements java.io.Serializable { - + MY_SCHEMA - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + - + MY_TABLE - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomBaseClasscom.example.MyOptionalCustomInterface
    - + - + MY_FIELD - + --> MatcherRule --> MatcherRule @@ -11206,30 +11206,30 @@ public class Book implements java.io.Serializable { --> MatcherRule - + - + MY_ROUTINE - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + - + MY_SEQUENCE - + --> MatcherRule @@ -11245,19 +11245,19 @@ public class Book implements java.io.Serializable { CAMEL - + PREFIX_$0_SUFFIX ]]> - +

    Some examples

    The following example shows a matcher strategy that adds a "T_" prefix to all table classes and to table identifiers: @@ -11298,13 +11298,13 @@ public class Book implements java.io.Serializable { ]]> - +

    For more information about each XML tag, please refer to the http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd XSD file.

    - +
    Custom code sections @@ -11327,11 +11327,11 @@ public class Book implements java.io.Serializable {

    The above example simply adds a class footer to , in this case, overriding the default toString() implementation.

    - +

    Any of the below methods can be overridden:

    - + Tables.java: This file contains all table objects in the form of static member references to the actual singleton object
  • UDTs.java: This file contains all UDT objects in the form of static member references to the actual singleton object
  • - +

    Referencing global artefacts

    When referencing global artefacts from your client application, you would typically static import them as such:

    - + @@ -11415,7 +11415,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate a implementation that looks like this:

    - + { // The singleton instance @@ -11431,7 +11431,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE) public Book as(java.lang.String alias) { return new Book(alias); } - + // [...] }]]> @@ -11448,7 +11448,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)
  • instanceFields: This flag controls the "static" keyword on table columns, as well as aliasing convenience
  • records: The generated record type is referenced from tables allowing for type-safe single-table record fetching
  • - +

    Flags controlling table generation

    Table generation cannot be deactivated @@ -11462,7 +11462,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate an implementation that looks like this:

    - + - +

    Flags influencing generated records

    These flags from the influence generated records: @@ -11518,7 +11518,7 @@ implements IBook {

  • interfaces: If interfaces are generated, records will implement them
  • jpaAnnotations: JPA annotations are used on generated records
  • - +

    Flags controlling record generation

    Record generation can be deactivated using the records flag @@ -11532,7 +11532,7 @@ implements IBook {

    Every table in your database will generate a POJO implementation that looks like this:

    - + - +

    Flags influencing generated POJOs

    These flags from the influence generated POJOs: @@ -11581,7 +11581,7 @@ public class Book implements java.io.Serializable

  • jpaAnnotations: JPA annotations are used on generated records
  • validationAnnotations: JSR-303 validation annotations are used on generated records
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the pojos flag @@ -11595,16 +11595,16 @@ public class Book implements java.io.Serializable

    Every table in your database will generate an interface that looks like this:

    - + - +

    Flags influencing generated interfaces

    These flags from the influence generated interfaces: @@ -11613,7 +11613,7 @@ public class Book implements java.io.Serializable

  • dateAsTimestamp: This influences all relevant getters and setters
  • unsignedTypes: This influences all relevant getters and setters
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the interfaces flag @@ -11628,7 +11628,7 @@ public class Book implements java.io.Serializable

    Every table in your database will generate a implementation that looks like this:

    - + { // Generated constructors @@ -11652,10 +11652,10 @@ public class Book implements java.io.Serializable public List fetchByAuthorId(Integer... values) { return fetch(BOOK.AUTHOR_ID, values); } - + // [...] }]]> - +

    Flags controlling DAO generation

    DAO generation can be activated using the daos flag @@ -11669,13 +11669,13 @@ public class Book implements java.io.Serializable

    Every sequence in your database will generate a implementation that looks like this:

    - + S_AUTHOR_ID = new SequenceImpl("S_AUTHOR_ID", TEST, SQLDataType.INTEGER); }]]> - +

    Flags controlling sequence generation

    Sequence generation cannot be deactivated @@ -11713,7 +11713,7 @@ public class Book implements java.io.Serializable public BigDecimal getResult() { return getValue(RESULT); } - + // [...] }]]> @@ -11735,7 +11735,7 @@ public class Book implements java.io.Serializable

    Every UDT in your database will generate a implementation that looks like this:

    - + { // The singleton UDT instance @@ -11748,10 +11748,10 @@ public class Book implements java.io.Serializable createField("CITY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); public static final UDTField COUNTRY = createField("COUNTRY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); - + // [...] }]]> - +

    Besides the implementation, a implementation is also generated

    @@ -11766,7 +11766,7 @@ public class Book implements java.io.Serializable public String getCity() {...} public void setCountry(String value) {...} public String getCountry() {...} - + // [...] }]]>
    @@ -11798,7 +11798,7 @@ public class Book implements java.io.Serializable Use the pipe to separate several expressions. If provided, both "expressions" and "types" must match. --> .*\.IS_VALID - + .*\.DATE_OF_.* - + .* @@ -11899,23 +11899,23 @@ create.selectFrom(AUTHOR)
    - +
    Code generation for large schemas

    Databases can become very large in real-world applications. This is not a problem for jOOQ's code generator, but it can be for the Java compiler. jOOQ generates some classes for . These classes can hit two sorts of limits of the compiler / JVM:

    - +
    • Methods (including static / instance initialisers) are allowed to contain only 64kb of bytecode.
    • Classes are allowed to contain at most 64k of constant literals
    - +

    While there exist workarounds for the above two limitations (delegating initialisations to nested classes, inheriting constant literals from implemented interfaces), the preferred approach is either one of these:

    - +
    • Distribute your database objects in several schemas. That is probably a good idea anyway for such large databases
    • to exclude excess database objects
    • @@ -11998,11 +11998,11 @@ create.selectFrom(AUTHOR)

      When writing unit tests for your data access layer, you have probably used some generic mocking tool offered by popular providers like Mockito, jmock, mockrunner, or even DBUnit. With jOOQ, you can take advantage of the built-in JDBC mock API that allows you to emulate a simple database on the JDBC level for precisely those SQL/JDBC use cases supported by jOOQ.

      - +

      - Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider. + Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider.

      - +

      Mocking the JDBC API

      JDBC is a very complex API. It takes a lot of time to write a useful and correct mock implementation, implementing at least these interfaces: @@ -12015,16 +12015,16 @@ create.selectFrom(AUTHOR)

    - +

    Optionally, you may even want to implement interfaces, such as , , , and many others. In addition to the above, you might need to find a way to simultaneously support incompatible JDBC minor versions, such as 4.0, 4.1

    - +

    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 :

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    As you can see, the configuration setup is simple. Now, the MockDataProvider acts as your single point of contact with JDBC / jOOQ. It unifies any of these execution modes, transparently:

    - +
    • Statements without results
    • Statements without results but with generated keys
    • @@ -12047,16 +12047,16 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
    • Batch statements with single queries and multiple bind value sets
    • Batch statements with multiple queries and no bind values
    - +

    The above are the execution modes supported by jOOQ. Whether you're using any of jOOQ's various fetching modes (e.g. , , , ) is irrelevant, as those modes are all built on top of the standard JDBC API.

    - +

    Implementing MockDataProvider

    Now, here's how to implement MockDataProvider:

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc // 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 String sql = ctx.sql(); - + // Exceptions are propagated through the JDBC and jOOQ APIs if (sql.toUpperCase().startsWith("DROP")) { throw new SQLException("Statement not supported: " + sql); } - + // You decide, whether any given statement returns results, and how many else if (sql.toUpperCase().startsWith("SELECT")) { - + // Always return one author record Result result = create.newResult(AUTHOR); result.add(create.newRecord(AUTHOR)); @@ -12084,12 +12084,12 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc result.get(0).setValue(AUTHOR.LAST_NAME, "Orwell"); mock[0] = new MockResult(1, result); } - + // You can detect batch statements easily else if (ctx.batch()) { // [...] } - + return mock; } }]]> @@ -12101,17 +12101,17 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • : The number of affected rows
  • : The result set
  • - +

    You should return as many MockResult objects as there were query executions (in ) or results (in ). Instead of an awkward JDBC ResultSet, however, you can construct a "friendlier" with your own record types. The jOOQ mock API will use meta data provided with this Result in order to create the necessary JDBC

    - +

    See the for a list of rules that you should follow.

    - +
    SQL 2 jOOQ Parser @@ -12121,20 +12121,20 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    Gudu Software Ltd has been selling enterprise quality SQL software to hundreds of customers to help them migrate from one database to another using the General SQL Parser. Now you can take advantage of their knowledge to parse your SQL statements and transform them directly into jOOQ statements using a free trial version of SQL 2 jOOQ!

    - +

    It's as simple as this!

    - +
    • Create a JDBC connection
    • Create a new SQL2jOOQ converter object
    • Convert your SQL code
    • Get the result
    - +

    See it in action:

    - + If all goes well, the above program yields:

    - + > result = create.select( Actor.ACTOR.FIRST_NAME, Actor.ACTOR.LAST_NAME ) @@ -12198,21 +12198,21 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    Please take note of the fact that the sql2jooq library is Open Source, but it depends on the commercial gsp.jar parser, whose trial licensing terms can be seen here:

    - +

    https://github.com/sqlparser/sql2jooq/blob/master/sql2jooq/LICENSE-GSQLPARSER.txt

    - +

    For more information about the General SQL Parser, please refer to the product blog.

    - +

    Please report any issues, ideas, wishes to the jOOQ user group or the sql2jooq GitHub project.

    - +
    jOOQ Console @@ -12259,7 +12259,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • Sybase Adaptive Server Enterprise 15.5
  • Sybase SQL Anywhere 12
  • - +

    For an up-to-date list of currently supported RDBMS, please refer to http://www.jooq.org/legal/licensing/#databases.

    @@ -12280,7 +12280,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME, This chapter should document the most important notes about SQL, JDBC and jOOQ data types.

    - +
    BLOBs and CLOBs @@ -12290,7 +12290,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    Unsigned integer types @@ -12314,7 +12314,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
    - +
    INTERVAL data types @@ -12325,11 +12325,11 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • YEAR TO MONTH: This interval type models a number of months and years
  • DAY TO SECOND: This interval type models a number of days, hours, minutes, seconds and milliseconds
  • - +

    Both interval types ship with a variant of subtypes, such as DAY TO HOUR, HOUR TO SECOND, etc. jOOQ models these types as Java objects extending : (where Number.intValue() corresponds to the absolute number of months) and (where Number.intValue() corresponds to the absolute number of milliseconds)

    - +

    Interval arithmetic

    In addition to the documented previously, interval arithmetic is also supported by jOOQ. Essentially, the following operations are supported: @@ -12344,7 +12344,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    XML data types @@ -12353,7 +12353,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    Geospacial data types @@ -12363,7 +12363,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    CURSOR data types @@ -12372,22 +12372,22 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    > cursor;]]> - +

    In fact, such a cursor will be fetched immediately by jOOQ and wrapped in an object.

    - +
    ARRAY and TABLE data types

    The SQL standard specifies ARRAY data types, that can be mapped to Java arrays as such:

    - + intArray;]]> - +

    The above array type is supported by these SQL dialects:

    @@ -12396,7 +12396,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • HSQLDB
  • Postgres
  • - +

    Oracle typed arrays

    Oracle has strongly-typed arrays and table types (as opposed to the previously seen anonymously typed arrays). These arrays are wrapped by types. @@ -12412,12 +12412,12 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    jOOQ takes SQL as an external domain-specific language and maps it onto Java, creating an internal domain-specific language. Internal DSLs cannot 100% implement their external language counter parts, as they have to adhere to the syntax rules of their host or target language (i.e. Java). This section explains the various problems and workarounds encountered and implemented in jOOQ.

    - +

    SQL allows for "keywordless" syntax

    SQL syntax does not always need keywords to form expressions. The clause takes various argument assignments:

    - + UPDATE t SET a = 1, b = 2 update(t).set(a, 1).set(b, 2) @@ -12435,12 +12435,12 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    In this case, ROW is an actual (optional) SQL keyword, implemented by at least PostgreSQL.

    - +

    SQL contains "composed" keywords

    As most languages, SQL does not attribute any meaning to whitespace. However, whitespace is important when forming "composed" keywords, i.e. SQL clauses composed of several keywords. jOOQ follows standard Java method naming conventions to map SQL keywords (case-insensitive) to Java methods (case-sensitive, camel-cased). Some examples:

    - + GROUP BY ORDER BY @@ -12453,7 +12453,7 @@ whenMatchedThenUpdate()

    Future versions of jOOQ may use all-uppercased method names in addition to the camel-cased ones (to prevent collisions with Java keywords):

    - + GROUP BY ORDER BY @@ -12484,7 +12484,7 @@ WHEN_MATCHED_THEN_UPDATE()

    The above example omits THEN and END keywords in Java. Future versions of jOOQ may comprise a more complete DSL, including such keywords again though, to provide a more 1:1 match for the SQL language.

    - +

    SQL contains "superfluous" syntactic elements

    Some SQL constructs are hard to map to Java, but they are also not really necessary. SQL often expects syntactic parentheses where they wouldn't really be needed, or where they feel slightly inconsistent with the rest of the SQL language. @@ -12521,7 +12521,7 @@ WHEN_MATCHED_THEN_UPDATE()

    jOOQ replaces those keywords by "synonyms":

    - + CASE .. ELSE PIVOT .. FOR .. IN .. @@ -12549,7 +12549,7 @@ pivot(..).on(..).in(..)

    Most SQL operators have to be mapped to descriptive method names in Java, as Java does not allow operator overloading:

    - + , != @@ -12578,7 +12578,7 @@ set(a, b)

    This is less of a syntactic SQL feature than a semantic one. In SQL, objects can be referenced before (i.e. "lexicographically before") they are declared. This is particularly true for

    - + @@ -12589,7 +12589,7 @@ select(t.a).from(t)]]>

    A more sophisticated example are common table expressions (CTE), which are currently not supported by jOOQ:

    - + WITH t(a, b) AS ( SELECT 1, 2 FROM DUAL ) @@ -12601,7 +12601,7 @@ FROM t

    - +
    jOOQ's BNF pseudo-notation @@ -12610,7 +12610,7 @@ FROM t

    - +
    Quality Assurance @@ -12622,16 +12622,16 @@ FROM t
  • To add lots of type-safety to your inline SQL
  • To increase productivity when writing inline SQL using your favourite IDE's autocompletion capabilities
  • - +

    With jOOQ being in the core of your application, you want to be sure that you can trust jOOQ. That is why jOOQ is heavily unit and integration tested with a strong focus on integration tests:

    - +

    Unit tests

    Unit tests are performed against dummy JDBC interfaces using http://jmock.org/. These tests verify that various implementations render correct SQL and bind variables correctly.

    - +

    Integration tests

    This is the most important part of the jOOQ test suites. Some 1500 queries are currently run against a standard integration test database. Both the test database and the queries are translated into every one of the 14 supported SQL dialects to ensure that regressions are unlikely to be introduced into the code base. @@ -12642,17 +12642,17 @@ FROM t

    jOOQ integration tests run the weirdest and most unrealistic queries. As a side-effect of these extensive integration test suites, many corner-case bugs for JDBC drivers and/or open source databases have been discovered, feature requests submitted through jOOQ and reported mainly to CUBRID, Derby, H2, HSQLDB.

    - +

    Code generation tests

    For every one of the 14 supported integration test databases, source code is generated and the tiniest differences in generated source code can be discovered. In case of compilation errors in generated source code, new test tables/views/columns are added to avoid regressions in this field.

    - +

    API Usability tests and proofs of concept

    jOOQ is used in jOOQ-meta as a proof of concept. This includes complex queries such as the following Postgres query

    - + These rather complex queries show that the jOOQ API is fit for advanced SQL use-cases, compared to the rather simple, often unrealistic queries in the integration test suite.

    - +

    Clean API and implementation. Code is kept DRY

    As a general rule of thumb throughout the jOOQ code, everything is kept DRY. Some examples: @@ -12718,19 +12718,19 @@ for (Record record : create.select(

    - +
    Migrating to jOOQ 3.0

    This section is for all users of jOOQ 2.x who wish to upgrade to the next major release. In the next sub-sections, the most important changes are explained. Some code hints are also added to help you fix compilation errors.

    - +

    Type-safe row value expressions

    Support for has been added in jOOQ 2.6. In jOOQ 3.0, many API parts were thoroughly (but often incompatibly) changed, in order to provide you with even more type-safety.

    - +

    Here are some affected API parts:

    @@ -12740,11 +12740,11 @@ for (Record record : create.select(
  • IN predicates and comparison predicates taking subselects changed incompatibly
  • INSERT and MERGE statements now take typesafe VALUES() clauses
  • - +

    Some hints related to row value expressions:

    - + record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result> result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch(); @@ -12752,31 +12752,31 @@ Result> result = create.select(BOOK.TITLE, BOOK.ID).fro // But Record2 extends Record. You don't have to use the additional typesafety: Record record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch();]]> - +

    SelectQuery and SelectXXXStep are now generic

    In order to support type-safe row value expressions and type-safe Record[N] types, SelectQuery is now generic: SelectQuery<R>

    - +

    SimpleSelectQuery and SimpleSelectXXXStep API were removed

    The duplication of the SELECT API is no longer useful, now that SelectQuery and SelectXXXStep are generic.

    - +

    Factory was split into DSL (query building) and DSLContext (query execution)

    The pre-existing Factory class has been split into two parts:

    - +
    1. 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
    2. 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 renamed to DSLContext. An example:

    - + - +

    Quantified comparison predicates

    Field.equalAny(...) and similar methods have been removed in favour of Field.equal(any(...)). This greatly simplified the Field API. An example:

    - + > subselect = any(select(BOOK.ID).from(BOOK)); Condition condition = BOOK.ID.equal(subselect);]]> - +

    FieldProvider

    The FieldProvider marker interface was removed. Its methods still exist on FieldProvider subtypes. Note, they have changed names from getField() to field() and from getIndex() to indexOf()

    - +

    GroupField

    GroupField has been introduced as a DSL marker interface to denote fields that can be passed to GROUP BY clauses. This includes all org.jooq.Field types. However, fields obtained from ROLLUP(), CUBE(), and GROUPING SETS() functions no longer implement Field. Instead, they only implement GroupField. An example:

    - + field1a = Factory.rollup(...); // OK Field field2a = Factory.one(); // OK @@ -12822,19 +12822,19 @@ GroupField field1b = DSL.rollup(...); // OK Field field1c = DSL.rollup(...); // Compilation error GroupField field2b = DSL.one(); // OK Field field2c = DSL.one(); // OK]]> - +

    NULL predicate

    Beware! Previously, Field.equal(null) was translated internally to an IS NULL predicate. This is no longer the case. Binding Java "null" to a comparison predicate will result in a regular comparison predicate (which never returns true). This was changed for several reasons:

    - +
    • To most users, this was a surprising "feature".
    • Other predicates didn't behave in such a way, e.g. the IN predicate, the BETWEEN predicate, or the LIKE predicate.
    • Variable binding behaved unpredictably, as IS NULL predicates don't bind any variables.
    • The generated SQL depended on the possible combinations of bind values, which creates unnecessary hard-parses every time a new unique SQL statement is rendered.
    - +

    Here is an example how to check if a field has a given value, without applying SQL's ternary NULL logic:

    @@ -12847,7 +12847,7 @@ Condition condition1 = BOOK.TITLE.equal(possiblyNull); // jOOQ 3.0 Condition condition2 = BOOK.TITLE.equal(possiblyNull).or(BOOK.TITLE.isNull().and(val(possiblyNull).isNull())); Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    Configuration

    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 @@ -12861,7 +12861,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> In order to resolve confusion that used to arise because of different lifecycle durations, these types are now no longer formally connected through inheritance.

    - +

    ConnectionProvider

    In order to allow for simpler connection / data source management, jOOQ externalised connection handling in a new ConnectionProvider type. The previous two connection modes are maintained backwards-compatibly (JDBC standalone connection mode, pooled DataSource mode). Other connection modes can be injected using: @@ -12871,24 +12871,24 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    These are some side-effects of the above change

    - +
    • 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. This resolves many class loader issues that were encountered before. It also helps listener implementations control their lifecycles themselves.

    - +

    Data type API

    The data type API has been changed drastically in order to enable some new DataType-related features. These changes include: @@ -12898,16 +12898,16 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]>[SQLDialect]DataType and SQLDataType no longer implement DataType. They're mere constant containers

  • Various minor API changes have been done.
  • - +

    Object renames

    These objects have been moved / renamed:

    - +
    • jOOU: a library used to represent unsigned integer types was moved from org.jooq.util.unsigned to org.jooq.util.types (which already contained INTERVAL data types)
    - +

    Feature removals

    Here are some minor features that have been removed in jOOQ 3.0 @@ -13001,7 +13001,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> --> diff --git a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.4.xml b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.4.xml index c1dc301178..b9b61c68f4 100644 --- a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.4.xml +++ b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.4.xml @@ -126,7 +126,7 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ's reason for being - compared to SQL / JDBC

    So why not just use SQL? @@ -149,14 +149,14 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ is different

    SQL was never meant to be abstracted. To be confined in the narrow boundaries of heavy mappers, hiding the beauty and simplicity of relational data. SQL was never meant to be object-oriented. SQL was never meant to be anything other than... SQL!

    - + - +
    Getting started with jOOQ @@ -344,12 +344,12 @@ limitations under the License.

    This section helps you correctly interpret this manual in the context of jOOQ.

    - +

    Code blocks

    The following are code blocks:

    - + @@ -365,7 +365,7 @@ org.jooq.property=value]]>

    These are useful to provide examples in code. Often, with jOOQ, it is even more useful to compare SQL code with its corresponding Java/jOOQ code. When this is done, the blocks are aligned side-by-side, with SQL usually being on the left, and an equivalent jOOQ DSL query in Java usually being on the right:

    - + @@ -377,17 +377,17 @@ create.selectOne().fetch()]]>

    The contents of code blocks follow conventions, too. If nothing else is mentioned next to any given code block, then the following can be assumed:

    - - + + - +

    Your naming may differ, of course. For instance, you could name the "create" instance "db", instead.

    - +

    Execution

    - +

    When you're coding PL/SQL, T-SQL or some other procedural SQL language, SQL statements are always executed immediately at the semi-colon. This is not the case in jOOQ, because as an internal DSL, jOOQ can never be sure that your statement is complete until you call fetch() or execute(). The manual tries to apply fetch() and execute() as thoroughly as possible. If not, it is implied:

    @@ -427,7 +427,7 @@ create.update(T).set(T.V, 1).execute();]]>

    jOOQ allows to override runtime behaviour using . If nothing is specified, the default runtime settings are assumed.

    - +

    Sample database

    jOOQ query examples run against the sample database. See the manual's section about to learn more about the sample database. @@ -462,7 +462,7 @@ CREATE TABLE book ( title VARCHAR2(400) NOT NULL, published_in NUMBER(7) NOT NULL, language_id NUMBER(7) NOT NULL, - + CONSTRAINT fk_book_author FOREIGN KEY (author_id) REFERENCES author(id), CONSTRAINT fk_book_language FOREIGN KEY (language_id) REFERENCES language(id) ); @@ -475,7 +475,7 @@ CREATE TABLE book_to_book_store ( name VARCHAR2(400) NOT NULL, book_id INTEGER NOT NULL, stock INTEGER, - + PRIMARY KEY(name, book_id), CONSTRAINT fk_b2bs_book_store FOREIGN KEY (name) REFERENCES book_store (name) ON DELETE CASCADE, CONSTRAINT fk_b2bs_book FOREIGN KEY (book_id) REFERENCES book (id) ON DELETE CASCADE @@ -486,7 +486,7 @@ CREATE TABLE book_to_book_store (

    In addition to the above, you may assume the following sample data:

    - + Effectively, jOOQ was originally designed to replace any other database abstraction framework short of the ones handling connection pooling (and more sophisticated )

    - +

    Use jOOQ the way you prefer

    ... but open source is community-driven. And the community has shown various ways of using jOOQ that diverge from its original intent. Some use cases encountered are: @@ -545,7 +545,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]>Using jOOQ for SQL building and Spring Data for SQL execution

  • Using jOOQ without the to build the basis of a framework for dynamic SQL execution.
  • - +

    The following sections explain about various use cases for using jOOQ in your application.

    @@ -558,7 +558,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]> This is the most simple of all use cases, allowing for construction of valid SQL for any database. In this use case, you will not use and probably not even . Instead, you'll use to wrap strings, literals and other user-defined objects into an object-oriented, type-safe AST modelling your SQL statements. An example is given here:

    - + - +

    The SQL string built with the jOOQ query DSL can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools (note that since jOOQ uses PreparedStatement by default, this will generate a bind variable for "1948". ).

    @@ -595,7 +595,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID)) .where(BOOK.PUBLISHED_IN.equal(1948)) .getSQL();]]> - +

    The SQL string that you can generate as such can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools.

    @@ -615,7 +615,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    Instead of any tool mentioned in the previous chapters, you can also use jOOQ directly to execute your jOOQ-generated SQL statements. This will add a lot of convenience on top of the previously discussed API for typesafe SQL construction, when you can re-use the information from generated classes to fetch records and custom data types. An example is given here:

    - + > result = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) @@ -669,10 +669,10 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { // Skip previously distinguished authors if ((int) author.getDistinguished() == 1) continue; - + // Check if the author has written more than 5 books if (author.fetchChildren(Keys.FK_BOOK_AUTHOR).size() > 5) { - + // Mark the author as a "distinguished" author author.setDistinguished(1); author.store(); @@ -689,7 +689,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {
    - +
    jOOQ for PROs @@ -727,7 +727,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { This manual section is intended for new users, to help them get a running application with jOOQ, quickly.

    - +
    Step 1: Preparation @@ -736,7 +736,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { If you haven't already downloaded it, download jOOQ:
    http://www.jooq.org/download

    - +

    Alternatively, you can create a Maven dependency to download jOOQ artefacts:

    @@ -759,7 +759,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    Note that only the jOOQ Open Source Edition is available from Maven Central. If you're using the jOOQ Professional Edition or the jOOQ Enterprise Edition, you will have to manually install jOOQ in your local Nexus, or in your local Maven cache. For more information, please refer to the licensing pages.

    - +

    Please refer to the manual's section about to learn how to use jOOQ's code generator with Maven.

    @@ -774,14 +774,14 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    - +
    Step 2: Your database

    We're going to create a database called "library" and a corresponding "author" table. Connect to MySQL via your command line client and type the following:

    - + CREATE DATABASE `library`; USE `library`; @@ -795,7 +795,7 @@ CREATE TABLE `author` (
    - +
    Step 3: Code generation @@ -807,7 +807,7 @@ CREATE TABLE `author` (

    The easiest way to generate a schema is to copy the jOOQ jar files (there should be 3) and the MySQL Connector jar file to a temporary directory. Then, create a library.xml that looks like this:

    - + @@ -861,7 +861,7 @@ CREATE TABLE `author` (

    generator.target.directory - the directory to output to.

    - +

    Once you have the JAR files and library.xml in your temp directory, type this on a Windows machine:

    @@ -881,12 +881,12 @@ CREATE TABLE `author` (

    There are two things to note:

    - +
    1. The prefix slash before the /library.xml. Even though it's in our working directory, we need to prepend a slash, as the configuration file is loaded from the classpath.
    2. The "trailing" period in the classpath: .. We need this because we want the current directory on the classpath in order to find the above /library.xml file at the root of your classpath.
    - +

    Replace the filenames with your actual filenames. In this example, jOOQ {jooq-version} is being used. If everything has worked, you should see this in your console output:

    @@ -948,17 +948,17 @@ INFO: Packages fetched : 0 (0 included, 0 excluded) Nov 1, 2011 7:25:08 PM org.jooq.impl.JooqLogger info INFO: GENERATION FINISHED! : Total: 791.688ms, +9.143ms - +
    - +
    Step 4: Connect to your database

    Let's just write a vanilla main class in the project containing the generated classes:

    - +
    - +
    Step 5: Querying

    Let's add a simple query constructed with jOOQ's query DSL:

    - + result = create.select().from(AUTHOR).fetch();]]> @@ -1008,7 +1008,7 @@ Result result = create.select().from(AUTHOR).fetch();]]>

    - +
    Step 6: Iterating @@ -1027,7 +1027,7 @@ Result result = create.select().from(AUTHOR).fetch();]]>

    The full program should now look like this:

    - +
    - +
    Step 7: Explore! @@ -1123,7 +1123,7 @@ public class Main {
  • Another example using Spring and Guice for transaction management can be downloaded from GitHub.
  • Another, excellent tutorial by Petri Kainulainen can be found here.
  • - +

    Add the required Maven dependencies

    For this example, we'll create the following Maven dependencies @@ -1202,7 +1202,7 @@ public class Main {

    The above dependencies are configured together using a Spring Beans configuration:

    - + - + - + @@ -1267,7 +1267,7 @@ public class Main { - + ]]> @@ -1318,7 +1318,7 @@ public class QueryTest {

    The following example shows how you can use Spring's TransactionManager to explicitly handle transactions:

    - +
    - +
    Using jOOQ with Flyway

    Flyway - Database Migrations Made EasyWhen performing database migrations, we at Data Geekery recommend using jOOQ with Flyway - Database Migrations Made Easy. In this chapter, we're going to look into a simple way to get started with the two frameworks.

    - +

    Philosophy

    - +

    There are a variety of ways how jOOQ and Flyway could interact with each other in various development setups. In this tutorial we're going to show just one variant of such framework team play - a variant that we find particularly compelling for most use cases.

    - +

    The general philosophy behind the following approach can be summarised as this:

    - +
    • 1. Database increment
    • 2. Database migration
    • 3. Code re-generation
    • 4. Development
    - +

    The four steps above can be repeated time and again, every time you need to modify something in your database. More concretely, let's consider:

    - +
    • 1. Database increment - You need a new column in your database, so you write the necessary DDL in a Flyway script
    • 2. Database migration - This Flyway script is now part of your deliverable, which you can share with all developers who can migrate their databases with it, the next time they check out your change
    • @@ -1464,15 +1464,15 @@ public class TransactionTest { ]]>

      0. Maven Project Configuration - Dependencies

      - +

      While jOOQ and Flyway could be used in standalone migration scripts, in this tutorial, we'll be using Maven for the standard project setup. You will also find the source code of this tutorial on GitHub at https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-flyway-example, and the full pom.xml file here.

      - +

      These are the dependencies that we're using in our Maven configuration:

      - + org.jooq @@ -1805,14 +1805,14 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre;

    - +
    Using jOOQ with JAX-RS

    In some use-cases, having a lean, single-tier server-side architecture is desirable. Typically, such architectures expose a RESTful API implementing client code and the UI using something like AngularJS.

    - +

    In Java, the standard API for RESTful applications is JAX-RS, which is part of JEE 7, along with a standard JSON implementation. But you can use JAX-RS also outside of a JEE container. The following example shows how to set up a simple license server using these technologies:

    @@ -1825,9 +1825,9 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre;

    For the example, we'll use a PostgreSQL database.

    - +

    Creating the license server database

    - +

    We'll keep the example simple and use a LICENSE table to store all license keys and associated information, whereas a LOG_VERIFY table is used to log access to the license server. Here's the DDL:

    @@ -1839,7 +1839,7 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre; LICENSEE TEXT NOT NULL, -- The e-mail address of the licensee LICENSE TEXT NOT NULL, -- The license key VERSION VARCHAR(50) NOT NULL DEFAULT '.*', -- The licensed version(s), a regular expression - + CONSTRAINT PK_LICENSE PRIMARY KEY (ID), CONSTRAINT UK_LICENSE UNIQUE (LICENSE) ); @@ -1852,7 +1852,7 @@ CREATE TABLE LICENSE_SERVER.LOG_VERIFY ( REQUEST_IP VARCHAR(50) NOT NULL, -- The request IP verifying the license VERSION VARCHAR(50) NOT NULL, -- The version that is being verified MATCH BOOLEAN NOT NULL, -- Whether the verification was successful - + CONSTRAINT PK_LOG_VERIFY PRIMARY KEY (ID) );]]> @@ -1874,13 +1874,13 @@ $$ LANGUAGE PLPGSQL;

    The actual algorithm might be using a secret salt to hash the function arguments. For the sake of a tutorial, a constant string will suffice.

    - +

    Setting up the project

    - +

    We're going to be setting up the

    - + 9966 - + org.jooq jooq-codegen-maven @@ -1946,7 +1946,7 @@ $$ LANGUAGE PLPGSQL; servlet-api 2.5 - + org.jooq jooq @@ -1968,13 +1968,13 @@ $$ LANGUAGE PLPGSQL;

    With the above setup, we're now pretty ready to start developing our license service as a JAX-RS service.

    - +

    The license service class

    - +

    Once we've run the , we can write the following service class:

    - + /license/verify checks if a given licensee has access to version using a license. * @@ -2034,7 +2034,7 @@ public class LicenseService { @Override public String run(DSLContext ctx) { String v = (version == null || version.equals("")) ? "" : version; - + // Use the jOOQ query DSL API to generate a log entry return ctx.insertInto(LOG_VERIFY) @@ -2055,10 +2055,10 @@ public class LicenseService { } }); } - + // [...] }]]> - +

    The INSERT INTO LOG_VERIFY query is actually rather interesting. In plain SQL, it would look like this:

    @@ -2083,7 +2083,7 @@ RETURNING MATCH;]]> */ private String run(CtxRunnable runnable) { Connection c = null; - + try { Class.forName("org.postgresql.Driver"); c = getConnection("jdbc:postgresql:postgres", "postgres", System.getProperty("pw", "test")); @@ -2091,7 +2091,7 @@ RETURNING MATCH;]]> .set(new DefaultConnectionProvider(c)) .set(SQLDialect.POSTGRES) .set(new Settings().withExecuteLogging(false))); - + return runnable.run(ctx); } catch (Exception e) { @@ -2103,13 +2103,13 @@ RETURNING MATCH;]]> JDBCUtils.safeClose(c); } } - + private interface CtxRunnable { String run(DSLContext ctx); }]]>

    Configuring Spring and Jetty

    - +

    All we need now is to configure Spring...

    @@ -2167,7 +2167,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/sch

    Using the license server

    - +

    You can now use the license server at the following URLs

    @@ -2184,7 +2184,7 @@ http://localhost:8088/jooq-jax-rs-example/license/verify?mail=test@example.com&l

    Let's verify what happened, in the database:

    - + - +

    Downloading the complete example

    - +

    The complete example can be downloaded for free and under the terms of the Apache Software License 2.0 from here:
    https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-jax-rs-example @@ -2214,21 +2214,21 @@ select * from license_server.log_verify

    - +
    jOOQ and Java 8

    Java 8 has introduced a great set of enhancements, among which lambda expressions and the new Streams API. These new constructs align very well with jOOQ's fluent API as can be seen in the following examples:

    - +

    jOOQ and lambda expressions

    jOOQ's API is fully Java-8-ready, which basically means that it is a SAM (Single Abstract Method) type, which can be instanciated using a lambda expression. Consider this example:

    - + - +

    The above example shows how jOOQ's method can receive a lambda expression that implements to map from jOOQ to your custom types.

    - +

    jOOQ and the Streams API

    @@ -2289,7 +2289,7 @@ select * from license_server.log_verify // Just emit a CREATE TABLE statement System.out.println( "CREATE TABLE " + table + " ("); - + // Map each "Column" type into a String // containing the column specification, // and join them using comma and @@ -2300,22 +2300,22 @@ select * from license_server.log_verify " " + col.type) .collect(Collectors.joining(",\n")) ); - + System.out.println(");"); } );]]> - +

    The above example is explained more in depth in this blog post: http://blog.jooq.org/2014/04/11/java-8-friday-no-more-need-for-orms/. For more information about Java 8, consider these resources:

    - +
    - +
    jOOQ and Scala @@ -2329,7 +2329,7 @@ select * from license_server.log_verify
  • Type inference using "var" and "val" keywords
  • Lambda expressions and for-comprehension syntax for record iteration and data type conversion
  • - +

    But jOOQ also leverages other useful Scala features, such as

    @@ -2337,15 +2337,15 @@ select * from license_server.log_verify
  • implicit defs for operator overloading
  • Scala Macros (soon to come)
  • - +

    All of the above heavily improve jOOQ's querying DSL API experience for Scala developers.

    - +

    A short example jOOQ application in Scala might look like this:

    - +
    - - + +
    jOOQ and Groovy @@ -2411,7 +2411,7 @@ object Test { //

    A short example jOOQ application in Groovy might look like this:

    - +
    - +
    jOOQ and NoSQL @@ -2464,7 +2464,7 @@ DSL.using(sql.connection)

    - +
    Dependencies @@ -2482,7 +2482,7 @@ DSL.using(sql.connection)
    - +
    Build your own @@ -2511,7 +2511,7 @@ DSL.using(sql.connection)
    - +
    jOOQ and backwards-compatibility @@ -2523,7 +2523,7 @@ DSL.using(sql.connection)
  • If a minor release includes backwards-compatible, API-relevant new features, [Y] is incremented by one and [Z] is reset to zero.
  • If a major release includes backwards-incompatible, API-relevant new features, [X] is incremented by one and [Y], [Z] are reset to zero.
  • - +

    jOOQ's understanding of backwards-compatibility

    Backwards-compatibility is important to jOOQ. You've chosen jOOQ as a strategic SQL engine and you don't want your SQL to break. That is why there is at most one major release per year, which changes only those parts of jOOQ's API and functionality, which were agreed upon on the user group. During the year, only minor releases are shipped, adding new features in a backwards-compatible way @@ -2536,15 +2536,15 @@ DSL.using(sql.connection)

  • Overloading methods for convenience
  • Changing the type hierarchy of interfaces
  • - +

    It becomes obvious that it would be impossible to add new language elements (e.g. new , new ) to the API without breaking any client code that actually implements those interfaces. Hence, the following rule should be observed:

    - +

    jOOQ's DSL interfaces should not be implemented by client code! Extend only those extension points that are explicitly documented as "extendable" (e.g. )

    - +

    jOOQ-codegen and jOOQ-meta

    While a reasonable amount of care is spent to maintain these two modules under the rules of semantic versioning, it may well be that minor releases introduce backwards-incompatible changes. This will be announced in the respective release notes and should be the exception. @@ -2572,7 +2572,7 @@ DSL.using(sql.connection) - +

    The query DSL type @@ -2603,7 +2603,7 @@ DSL.using(sql.connection) // ... which is in fact the same as: DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    DSL subclasses @@ -2622,7 +2622,7 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME));
    - + @@ -2631,14 +2631,14 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    The DSLContext class

    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.

    - +

    Fluent creation of a DSLContext object

    The DSLContext object can be created fluently from the : @@ -2653,7 +2653,7 @@ DSLContext create = DSL.using(connection, dialect);]]>

    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

    A Configuration can be supplied with these objects: @@ -2672,7 +2672,7 @@ DSLContext create = DSL.using(connection, dialect);]]> - +

    Wrapping a Configuration object, a DSLContext can construct , for later . An example is given here:

    @@ -2714,7 +2714,7 @@ DSL.using(connection, dialect) CONNECT BY clause to the query */ -@Support({ SQLDialect.CUBRID, SQLDialect.}) +@Support({ SQLDialect.CUBRID, SQLDialect.ORACLE }) SelectConnectByConditionStep connectBy(Condition condition);]]>

    @@ -2736,7 +2736,7 @@ SelectSelectStep select(Field... fields);]]>

    Nevertheless, the IS DISTINCT FROM predicate is supported by jOOQ in all dialects, as its semantics can be expressed with an equivalent . For more details, see the manual's section about the .

    - +

    jOOQ and the Oracle SQL dialect

    Oracle SQL is much more expressive than many other SQL dialects. It features many unique keywords, clauses and functions that are out of scope for the SQL standard. Some examples for this are @@ -2760,13 +2760,13 @@ SelectSelectStep select(Field... fields);]]>

    In jOOQ 3.1, the notion of a SQLDialect.family() was introduced, in order to group several similar into a common family. An example for this is SQL Server, which is supported by jOOQ in various versions:

    - +
    • : The "version-less" SQL Server version. This always maps to the latest supported version of SQL Server
    • : The SQL Server version 2012
    • : The SQL Server version 2008
    - +

    In the above list, SQLSERVER is both a dialect and a family of three dialects. This distinction is used internally by jOOQ to distinguish whether to use the clause (SQL Server 2012), or whether to emulate it using ROW_NUMBER() OVER() (SQL Server 2008).

    @@ -2783,7 +2783,7 @@ SelectSelectStep select(Field... fields);]]>

    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.

    - +

    Interact with JDBC DataSources

    If you're in a J2EE or Spring context, however, you may wish to use a instead. Connections obtained from such a DataSource will be closed after query execution by jOOQ. The semantics of such a close operation should be the returning of the connection into a connection pool, not the actual closing of the underlying connection. Typically, this makes sense in an environment using distributed JTA transactions. An example of using DataSources with jOOQ can be seen in the tutorial section about . @@ -2791,17 +2791,17 @@ SelectSelectStep select(Field... fields);]]>

    Note, in this case, jOOQ will internally use a , which you can reference directly if you prefer that.

    - +

    Inject custom behaviour

    If your specific environment works differently from any of the above approaches, you can inject your own custom implementation of a ConnectionProvider into jOOQ. This is the API contract you have to fulfil:

    - + @@ -2811,19 +2811,19 @@ 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...

    - +
    - +

    Here is an example of how to use the custom data API. Let's assume that you have written an , that prevents INSERT statements, when a given flag is set to true:

    @@ -2833,10 +2833,10 @@ public class NoInsertListener extends DefaultExecuteListener { @Override public void start(ExecuteContext ctx) { - + // This listener is active only, when your custom flag is set to true 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) { throw new DataAccessException("No INSERT statements allowed"); @@ -2847,11 +2847,11 @@ public class NoInsertListener extends DefaultExecuteListener {

    See the manual's section about to learn more about how to implement an ExecuteListener.

    - +

    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:

    - + ExecuteListeners are a useful tool to...

    - +
    • implement custom logging
    • apply triggers written in Java
    • collect query execution statistics
    - +

    ExecuteListeners are hooked into your by returning them from an :

    @@ -2909,7 +2909,7 @@ configuration.set( new DefaultExecuteListenerProvider(new PerformanceLoggingListener()), new DefaultExecuteListenerProvider(new NoInsertListener()) );]]>
    - +

    See the manual's section about to see examples of such listener implementations.

    @@ -2953,22 +2953,22 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - +

    All Settings

    - +

    This section of the manual explains all the available Settings flags as available from the XSD specification.

    - + false - + ... @@ -2979,17 +2979,17 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - UPPER_CASED : UPPER - lower_cased : LOWER - CasedAsReportedByTheDatabase : AS_IS - + Defaults to "QUOTED" --> LOWER UPPER - + false @@ -2997,54 +2997,54 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - question marks : INDEXED - named parameters : NAMED - inlined values : INLINED - + Defaults to "INDEXED". - + This value is overridden by statementType == STATIC_STATEMENT, in case of which, this defaults to INLINED --> INDEXED - + PREPARED_STATEMENT - + true false true false ]]> - +

    More details

    - +

    Please refer to the jOOQ runtime configuration XSD for more details:
    http://www.jooq.org/xsd/jooq-runtime-{runtime-xsd-version}.xsd

    - +
    Runtime schema and table mapping @@ -3052,7 +3052,7 @@ DSLContext create = DSL.using(connection, dialect, settings);]]>

    You may wish to design your database in a way that you have several instances of your schema. This is useful when you want to cleanly separate data belonging to several customers / organisation units / branches / users and put each of those entities' data in a separate database or schema.

    - +

    In our AUTHOR example this would mean that you provide a book reference database to several companies, such as My Book World and Books R Us. In that case, you'll probably have a schema setup like this:

    @@ -3082,7 +3082,7 @@ create.selectFrom(AUTHOR).fetch();

    The query executed with a Configuration equipped with the above mapping will in fact produce this SQL statement:

    - + SELECT * FROM MY_BOOK_WORLD.AUTHOR

    Even if AUTHOR was generated from DEV. @@ -3157,7 +3157,7 @@ create.selectFrom(AUTHOR).fetch();

    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

    @@ -3191,7 +3191,7 @@ create.selectFrom(AUTHOR).fetch();

    Here is an example to illustrate what that means:

    - + 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) @@ -3263,7 +3263,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); @@ -3290,7 +3290,7 @@ query.addJoin(BOOK, BOOK.AUTHOR_ID.equal(AUTHOR.ID));]]>

    Note, that for historic reasons, the DSL API mixes mutable and immutable behaviour with respect to the internal representation of the being constructed. While creating , (such as functions) assumes immutable behaviour, creating does not. In other words, the following can be said:

    - + select2 = create.selectOne().fetch();]]>

    jOOQ does not explicitly support the asterisk operator in projections. However, you can omit the projection as in these examples:

    - +

    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:

    - + select(Collection> fields); public static SelectSelectStep select(Field... fields); @@ -3572,14 +3572,14 @@ public static SelectSelectStep> select(Field SelectSelectStep> select(Field field1, Field field2); public static SelectSelectStep> select(Field field1, Field field2, Field field3); // [...]]]> - +

    Since the generic R type is bound to some , the associated T type information can be used in various other contexts, e.g. the . Such a SELECT statement can be assigned typesafely:

    > s1 = create.select(BOOK.ID, BOOK.TITLE); Select> s2 = create.select(BOOK.ID, trim(BOOK.TITLE));]]> - +

    For more information about typesafe record types with degree up to {max-row-degree}, see the manual's section about .

    @@ -3605,7 +3605,7 @@ create.selectOne().from(BOOK.as("b"), AUTHOR.as("a")).fetch();]]>

    Read more about aliasing in the manual's section about .

    - +

    More advanced table expressions

    Apart from simple tables, you can pass any arbitrary to the jOOQ FROM clause. This may include in Oracle: @@ -3661,11 +3661,11 @@ DSL.using(SQLDialect.POSTGRES).selectOne().fetch();]]>

  • NATURAL LEFT [ OUTER ] JOIN
  • NATURAL RIGHT [ OUTER ] JOIN
  • - +

    Besides, jOOQ also supports

    - +
    • CROSS APPLY (T-SQL and Oracle 12c specific)
    • OUTER APPLY (T-SQL and Oracle 12c specific)
    • @@ -3798,7 +3798,7 @@ ON BOOK.AUTHOR_ID = AUTHOR.ID

      T-SQL has long known what the SQL standard calls lateral derived tables, lateral joins using the APPLY keyword. To every row resulting from the table expression on the left, we apply the table expression on the right. This is extremely useful for table-valued functions, which are also supported by jOOQ. Some examples:

      - + - +

      The above example shows standard usage of the LATERAL keyword to connect a derived table to the previous table in the . A similar statement can be written in T-SQL:

      - + Note that this syntax is also supported in the CUBRID database and might be emulated in other dialects supporting common table expressions in the future.

      - +

      ORDER SIBLINGS

      The Oracle database allows for specifying a SIBLINGS keyword in the . Instead of ordering the overall result, this will only order siblings among each other, keeping the hierarchy intact. An example is given here:

      - +
      - +
    @@ -3995,7 +3995,7 @@ GROUP BY AUTHOR_ID

    Note, as defined in the SQL standard, when grouping, you may no longer project any columns that are not a formal part of the GROUP BY clause, or .

    - +

    MySQL's deviation from the SQL standard

    MySQL has a peculiar way of not adhering to this standard behaviour. This is documented in the MySQL manual. In short, with MySQL, you can also project any other field that is not part of the GROUP BY clause. The projected values will just be arbitrary values from within the group. You cannot rely on any ordering. For example: @@ -4030,7 +4030,7 @@ GROUP BY () .groupBy() .fetch();]]> - +

    ROLLUP(), CUBE() and GROUPING SETS()

    Some databases support the SQL standard grouping functions and some extensions thereof. See the manual's section about for more details. @@ -4051,7 +4051,7 @@ FROM BOOK GROUP BY AUTHOR_ID HAVING COUNT(*) >= 2 ]]>  -= 4

    - +
    The WINDOW clause

    The SQL:2003 standard as well as PostgreSQL and Sybase SQL Anywhere support a WINDOW clause that allows for specifying WINDOW frames for reuse in and .

    - +   - +

    Note that in order to create such a window definition, we need to first create a using .

    Even if only PostgreSQL and Sybase SQL Anywhere natively support this great feature, jOOQ can emulate it by expanding any and types that you pass to the window() method - if the database supports window functions at all.

    - +

    Some more information about and the WINDOW clause can be found on our blog: http://blog.jooq.org/2013/11/03/probably-the-coolest-sql-feature-window-functions/

    @@ -4249,8 +4249,8 @@ ORDER BY CASE TITLE

    The SQL standard defines that a "query expression" can be ordered, and that query expressions can contain , whose subqueries cannot be ordered. While this is defined as such in the SQL standard, many databases allowing for the non-standard in one way or another, do not adhere to this part of the SQL standard. Hence, jOOQ allows for ordering all SELECT statements, regardless whether they are constructed as a part of a UNION or not. Corner-cases are handled internally by jOOQ, by introducing synthetic subselects to adhere to the correct syntax, where this is needed.

    - - + +

    Oracle's ORDER SIBLINGS BY clause

    jOOQ also supports Oracle's SIBLINGS keyword to be used with ORDER BY clauses for @@ -4299,7 +4299,7 @@ SELECT TOP 1 * FROM BOOK

    Things get a little more tricky in those databases that have no native idiom for OFFSET pagination (actual queries may vary):

    - + 1]]>

    As you can see, jOOQ will take care of the incredibly painful ROW_NUMBER() OVER() (or ROWNUM for Oracle) filtering in subselects for you, you'll just have to write limit(1).offset(2) in any dialect.

    - +

    Side-note: If you're interested in understanding why we chose ROWNUM for Oracle, please refer to this very interesting benchmark, comparing the different approaches of doing pagination in Oracle: http://www.inf.unideb.hu/~gabora/pagination/results.html.

    @@ -4346,7 +4346,7 @@ WHERE RN > 1]]>

    - +
    The SEEK clause @@ -4356,7 +4356,7 @@ WHERE RN > 1]]>

    A much faster and more stable way to perform paging is the so-called keyset paging method also called seek method. jOOQ supports a synthetic seek() clause, that can be used to perform keyset paging. Imagine we have these data:

    - + 1]]>

    Now, if we want to display page 6 to the user, instead of going to page 6 by using a record OFFSET, we could just fetch the record strictly after the last record on page 5, which yields the values (533, 2). This is how you would do it with SQL or with jOOQ:

    - + As you can see, the jOOQ SEEK clause is a synthetic clause that does not really exist in SQL. However, the jOOQ syntax is far more intuitive for a variety of reasons:

    - +
    • It replaces OFFSET where you would expect
    • It doesn't force you to mix regular predicates with "seek" predicates
    • It is typesafe
    • It emulates for you, in those databases that do not support them
    - +

    This query now yields:

    - + Note that you cannot combine the SEEK clause with the OFFSET clause.

    - +

    More information about this great feature can be found in the jOOQ blog:

    @@ -4427,11 +4427,11 @@ LIMIT 5
  • http://blog.jooq.org/2013/10/26/faster-sql-paging-with-jooq-using-the-seek-method/
  • http://blog.jooq.org/2013/11/18/faster-sql-pagination-with-keysets-continued/
  • - +

    Further information about offset pagination vs. keyset pagination performance can be found on our partner page:

    - +
    No more offset @@ -4543,7 +4543,7 @@ SELECT * FROM author ORDER BY id DESC;]]>

    SQL allows to perform set operations as understood in standard set theory on result sets. These operations include unions, intersections, subtractions. For two subselects to be combinable by such a set operator, each subselect must return a of the same degree and type.

    - +

    UNION and UNION ALL

    These operators combine two results into one. While UNION removes all duplicate records resulting from this combination, UNION ALL leaves subselect results as they are. Typically, you should prefer UNION ALL over UNION, if you don't really need to remove duplicates. The following example shows how to use such a UNION operation in jOOQ. @@ -4558,12 +4558,12 @@ SELECT * FROM BOOK WHERE ID = 5 .unionAll( create.selectFrom(BOOK).where(BOOK.ID.equal(5))) .fetch();]]> - +

    INTERSECT [ ALL ] and EXCEPT [ ALL ]

    INTERSECT is the operation that produces only those values that are returned by both subselects. EXCEPT is the operation that returns only those values that are returned exclusively in the first subselect. Both operators will remove duplicates from their results. The SQL standard allows to specify the ALL keyword for both of these operators as well, but this is hardly supported in any database. jOOQ does not support INTERSECT ALL, EXEPT ALL operations either.

    - +

    jOOQ's set operators and how they're different from standard SQL

    As previously mentioned in the manual's section about the , jOOQ has slightly changed the semantics of these set operators. While in SQL, a subselect may not contain any or (unless you wrap the subselect into a ), jOOQ allows you to do so. In order to select both the youngest and the oldest author from the database, you can issue the following statement with jOOQ (rendered to the MySQL dialect): @@ -4584,12 +4584,12 @@ ORDER BY 1 .orderBy(AUTHOR.DATE_OF_BIRTH.desc()).limit(1)) .orderBy(1) .fetch();]]> - +

    Projection typesafety for degrees between 1 and {max-row-degree}

    Two subselects that are combined by a set operator are required to be of the same degree and, in most databases, also of the same type. jOOQ 3.0's introduction of helps compile-checking these constraints:

    - + > s1 = select(BOOK.ID, BOOK.TITLE).from(BOOK); Select> s2 = selectOne(); @@ -4625,7 +4625,7 @@ s1.union(s4); // OK. The two Record[N] types match]]>

    Note that you can pass any string in the .hint() clause. If you use that clause, the passed string will always be put in between the SELECT [DISTINCT] keywords and the actual projection list. This can be useful in other databases too, such as MySQL, for instance:

    - +
    - +
    Lexical and logical SELECT clause order

    SQL has a lexical and a logical order of SELECT clauses. The lexical order of SELECT clauses is inspired by the English language. As SQL statements are commands for the database, it is natural to express a statement in an imperative tense, such as "SELECT this and that!".

    - +

    Logical SELECT clause order

    The logical order of SELECT clauses, however, does not correspond to the syntax. In fact, the logical order is this:

    - +
    • : First, all data sources are defined and joined
    • : Then, data is filtered as early as possible
    • @@ -4663,11 +4663,11 @@ FROM table1
    • : Then, a paging view is created for the ordered tuples
    • : Finally, pessimistic locking is applied
    - +

    The SQL Server documentation also explains this, with slightly different clauses:

    - +
    • FROM
    • ON
    • @@ -4681,16 +4681,16 @@ FROM table1
    • ORDER BY
    • TOP
    - +

    As can be seen, databases have to logically reorder a SQL statement in order to determine the best execution plan.

    - +

    Alternative syntaxes: LINQ, SLICK

    Some "higher-level" abstractions, such as C#'s LINQ or Scala's SLICK try to inverse the lexical order of SELECT clauses to what appears to be closer to the logical order. The obvious advantage of moving the SELECT clause to the end is the fact that the projection type, which is the record type returned by the SELECT statement can be re-used more easily in the target environment of the internal domain specific language.

    - +

    A LINQ example:

    @@ -4703,11 +4703,11 @@ Where p.UnitsInStock <= p.ReorderLevel AndAlso Not p.Discontinued // SELECT clause Select p]]> - +

    A SLICK example:

    - + - +

    As you can see, this syntax is a bit more verbose, but also more readable, as every field can be matched with its value. Internally, the two syntaxes are strictly equivalent.

    @@ -4813,7 +4813,7 @@ SELECT 101, 'Alfred', 'Döblin' FROM DUAL;

    The MySQL database supports a very convenient way to INSERT or UPDATE a record. This is a non-standard extension to the SQL syntax, which is supported by jOOQ and emulated in other RDBMS, where this is possible (i.e. if they support the SQL standard ). Here is an example how to use the ON DUPLICATE KEY UPDATE clause:

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, update the author's name create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -4823,11 +4823,11 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .execute();

    The synthetic ON DUPLICATE KEY IGNORE clause

    - +

    The MySQL database also supports an INSERT IGNORE INTO clause. This is supported by jOOQ using the more convenient SQL syntax variant of ON DUPLICATE KEY IGNORE, which can be equally emulated in other databases using a :

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, ignore the INSERT statement create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -4864,15 +4864,15 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    The INSERT SELECT statement

    - +

    In some occasions, you may prefer the INSERT SELECT syntax, for instance, when you copy records from one table to another:

    - + create.insertInto(AUTHOR_ARCHIVE) .select(create.selectFrom(AUTHOR).where(AUTHOR.DECEASED.isTrue())) .execute(); - +
    @@ -4924,7 +4924,7 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    jOOQ supports formal in various contexts, among which the UPDATE statement. Only one row value expression can be updated at a time. Here's an example:

    - + The above row value expressions usages are completely typesafe.

    - +

    UPDATE .. RETURNING

    The Firebird and Postgres databases support a RETURNING clause on their UPDATE statements, similar as the RETURNING clause in . This is useful to fetch trigger-generated values in one go. An example is given here:

    - + The H2 database ships with a somewhat less powerful but a little more intuitive syntax for its own version of the MERGE statement. An example more or less equivalent to the previous one can be seen here:

    - + -- Check if there is already an author called 'Hitchcock' -- If there is, rename him to John. If there isn't add him. @@ -5061,7 +5061,7 @@ VALUES ('John', 'Hitchcock') This syntax can be fully emulated by jOOQ for all other databases that support the SQL standard MERGE statement. For more information about the H2 MERGE syntax, see the documentation here:
    http://www.h2database.com/html/grammar.html#merge

    - +

    Typesafety of VALUES() for degrees up to {max-row-degree}

    Much like the , the MERGE statement's VALUES() clause provides typesafety for degrees up to {max-row-degree}, in both the standard syntax variant as well as the H2 variant. @@ -5187,7 +5187,7 @@ create.alterSequence(S_AUTHOR_ID).restartWith(n).execute();]]>

    Most of the times, when thinking about a you're probably thinking about an actual table in your database schema. If you're using jOOQ's , you will have all tables from your database schema available to you as type safe Java objects. You can then use these tables in SQL , or in other , just like any other table expression. An example is given here:

    - + - +

    The above example shows how AUTHOR and BOOK tables are joined in a . It also shows how you can access by dereferencing the relevant Java attributes of their tables.

    @@ -5240,11 +5240,11 @@ create.select() .and(a.FIRST_NAME.equal("Paulo"))) .orderBy(b.TITLE) .fetch();]]>
    - +

    As you can see in the above example, calling as() on generated tables returns an object of the same type as the table. This means that the resulting object can be used to dereference fields from the aliased table. This is quite powerful in terms of having your Java compiler check the syntax of your SQL statements. If you remove a column from a table, dereferencing that column from that table alias will cause compilation errors.

    - +

    Dereferencing columns from other table expressions

    Only few table expressions provide the SQL syntax typesafety as shown above, where generated tables are used. Most tables, however, expose their fields through field() methods: @@ -5256,12 +5256,12 @@ Table a = AUTHOR.as("a"); // Get fields from a: Field id = a.field("ID"); Field firstName = a.field("FIRST_NAME");]]> - +

    Derived column lists

    The SQL standard specifies how a table can be renamed / aliased in one go along with its columns. It references the term "derived column list" for the following syntax (as supported by Postgres, for instance):

    - + In jOOQ, you would simply specify a varargs list of column aliases as such:

    - + The that can be used in are the most powerful and best supported means of creating new in SQL. Informally, the following can be said:

    - + A(colA1, ..., colAn) "join" B(colB1, ..., colBm) "produces" C(colA1, ..., colAn, colB1, ..., colBm)

    @@ -5336,7 +5336,7 @@ create.select().from(values(

    jOOQ supports all of these JOIN types (except semi-join and anti-join) directly on any :

    - + table) @@ -5374,7 +5374,7 @@ Table naturalRightOuterJoin(TableLike)]]>

    Some databases allow for expressing in-memory temporary tables using a VALUES() constructor. This constructor usually works the same way as the VALUES() clause known from the or from the . With jOOQ, you can also use the VALUES() table constructor, to create tables that can be used in a :

    - + Note, that it is usually quite useful to provide column aliases ("derived column lists") along with the table alias for the VALUES() constructor.

    - +

    The above statement is emulated by jOOQ for those databases that do not support the VALUES() constructor, natively (actual emulations may vary):

    - + A can appear almost anywhere a can. Such a "nested SELECT" is often called a "derived table". Apart from many convenience methods accepting objects directly, a SELECT statement can always be transformed into a object using the asTable() method.

    - +

    Example: Scalar subquery

    - + If you are closely coupling your application to an Oracle database, you can take advantage of some Oracle-specific features, such as the PIVOT clause, used for statistical analyses. The formal syntax definition is as follows:

    - + -- SELECT .. FROM table PIVOT (aggregateFunction [, aggregateFunction] FOR column IN (expression [, expression])) -- WHERE .. - +

    The PIVOT clause is available from the type, as pivoting is done directly on a table. Currently, only Oracle's PIVOT clause is supported. Support for SQL Server's slightly different PIVOT clause will be added later. Also, jOOQ may emulate PIVOT for other dialects in the future.

    @@ -5566,7 +5566,7 @@ WHERE NOT EXISTS (

    The SQL standard specifies how SQL databases should implement ARRAY and TABLE types, as well as CURSOR types. Put simply, a CURSOR is a pointer to any materialised . Depending on the cursor's features, this table expression can be scrolled through in both directions, records can be locked, updated, removed, inserted, etc. Often, CURSOR types contain s, whereas ARRAY and TABLE types contain simple scalar values, although that is not a requirement

    - +

    ARRAY types in SQL are similar to Java's array types. They contain a "component type" or "element type" and a "dimension". This sort of ARRAY type is implemented in H2, HSQLDB and Postgres and supported by jOOQ as such. Oracle uses strongly-typed arrays, which means that an ARRAY type (VARRAY or TABLE type) has a name and possibly a maximum capacity associated with it.

    @@ -5655,12 +5655,12 @@ DSL.using(SQLDialect.SYBASE ).selectOne().getSQL();]]>

    Column expressions can be used in various SQL clauses in order to refer to one or several columns. This chapter explains how to form various types of column expressions with jOOQ. A particular type of column expression is given in the section about , where an expression may have a degree of more than one.

    - +

    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:

    - + field1 = BOOK.TITLE; @@ -5716,7 +5716,7 @@ ORDER BY BOOK.TITLE

    Just like , columns can be renamed using aliases. Here is an example:

    - + SELECT FIRST_NAME || ' ' || LAST_NAME author, COUNT(*) books FROM AUTHOR JOIN BOOK ON AUTHOR.ID = AUTHOR_ID @@ -5725,7 +5725,7 @@ GROUP BY FIRST_NAME, LAST_NAME;

    Here is how it's done with jOOQ:

    - + Record record = create.select( concat(AUTHOR.FIRST_NAME, val(" "), AUTHOR.LAST_NAME).as("author"), count().as("books")) @@ -5733,14 +5733,14 @@ GROUP BY FIRST_NAME, LAST_NAME;
    .join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID)) .groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .fetchAny(); - +

    When you alias Fields like above, you can access those Fields' values using the alias name:

    - + System.out.println("Author : " + record.getValue("author")); System.out.println("Books : " + record.getValue("books")); - +
    @@ -5753,7 +5753,7 @@ System.out.println("Books : " + record.getValue("books"));

    Sometimes, this automatic mapping might not be what you needed, or jOOQ cannot know the type of a field. In those cases you would write SQL type CAST like this:

    - + -- Let's say, your Postgres column LAST_NAME was VARCHAR(30) -- Then you could do this: SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL @@ -5761,27 +5761,27 @@ SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL

    in jOOQ, you can write something like that:

    - + create.select(TAuthor.LAST_NAME.cast(PostgresDataType.TEXT)).fetch();

    The same thing can be achieved by casting a Field directly to String.class, as TEXT is the default data type in Postgres to map to Java's String

    - + create.select(TAuthor.LAST_NAME.cast(String.class)).fetch(); - +

    The complete CAST API in consists of these three methods:

    - + { // Cast this field to the type of another field Field cast(Field field); - + // Cast this field to a given DataType Field cast(DataType type); - + // Cast this field to the default DataType for a given Class Field cast(Class type); } @@ -5804,14 +5804,14 @@ public class DSL {

    A slightly different use case than are data type coercions, which are not rendered through to generated SQL. Sometimes, you may want to pretend that a numeric value is really treated as a string value, for instance when binding a numeric :

    - + field1 = val(1).coerce(String.class); Field field2 = val("1").coerce(Integer.class);]]>

    In the above example, field1 will be treated by jOOQ as a Field<String>, binding the numeric literal 1 as a VARCHAR value. The same applies to field2, whose string literal "1" will be bound as an INTEGER value.

    - +

    This technique is better than performing unsafe or rawtype casting in Java, if you cannot access the "right" field type from any given expression.

    @@ -5831,15 +5831,15 @@ Field field2 = val("1").coerce(Integer.class);]]>

    In order to express a SQL query like this one:

    - + SELECT ((1 + 2) * (5 - 3) / 2) % 10 FROM DUAL - +

    You can write something like this in jOOQ:

    - + create.select(val(1).add(2).mul(val(5).sub(3)).div(2).mod(10)).fetch(); - +

    Operator precedence

    jOOQ does not know any operator precedence (see also ). All operations are evaluated from left to right, as with any object-oriented API. The two following expressions are the same: @@ -5867,14 +5867,14 @@ Field field2 = val("1").coerce(Integer.class);]]> - +

    String concatenation

    The SQL standard defines the concatenation operator to be an infix operator, similar to the ones we've seen in the chapter about . This operator looks like this: ||. Some other dialects do not support this operator, but expect a concat() function, instead. jOOQ renders the right operator / function, depending on your :

    - + SELECT 'A' || 'B' || 'C' FROM DUAL -- Or in MySQL: @@ -5902,13 +5902,13 @@ create.select(concat("A", "B", "C")).fetch();
  • NVL: Get the first non-null value among two arguments.
  • NVL2: Get the second argument if the first is null, or the third argument, otherwise.
  • - +

    Please refer to the for more details.

    - +
    Numeric functions @@ -5918,7 +5918,7 @@ create.select(concat("A", "B", "C")).fetch();

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ABS: Get the absolute value of a value.
    • ACOS: Get the arc cosine of a value.
    • @@ -5949,7 +5949,7 @@ create.select(concat("A", "B", "C")).fetch();
    • TANH: Get the hyperbolic tangent of a value.
    • TRUNC: Truncate the decimals off a given value.
    - +

    Please refer to the for more details.

    @@ -5974,13 +5974,13 @@ create.select(concat("A", "B", "C")).fetch();
  • SHL: Shift bits to the left
  • SHR: Shift bits to the right
  • - +

    Some background about bitwise operation emulation

    As stated before, not all databases support all of these bitwise operations. jOOQ emulates them wherever this is possible. More details can be seen in this blog post:
    http://blog.jooq.org/2011/10/30/the-comprehensive-sql-bitwise-operations-compatibility-list/

    - +
    @@ -5993,7 +5993,7 @@ create.select(concat("A", "B", "C")).fetch();

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ASCII: Get the ASCII code of a character.
    • BIT_LENGTH: Get the length of a string in bits.
    • @@ -6014,16 +6014,16 @@ create.select(concat("A", "B", "C")).fetch();
    • TRIM: Trim a string on both sides.
    • UPPER: Get a string in upper case letters.
    - +

    Please refer to the for more details.

    - +

    Regular expressions, REGEXP, REGEXP_LIKE, etc.

    Various databases have some means of searching through columns using regular expressions if the does not provide sufficient pattern matching power. While there are many different functions and operators in the various databases, jOOQ settled for the SQL:2008 standard REGEX_LIKE operator. Being an operator (and not a function), you should use the corresponding method on :

    - +

    @@ -6032,7 +6032,7 @@ create.select(concat("A", "B", "C")).fetch(); - +

    Case sensitivity with strings @@ -6045,20 +6045,20 @@ create.select(concat("A", "B", "C")).fetch();

    For these ad-hoc ordering use-cases, most people resort to using LOWER() or UPPER() as follows:

    - + -- Case-insensitive filtering: -SELECT * FROM BOOK +SELECT * FROM BOOK WHERE upper(TITLE) = 'ANIMAL FARM' -- Case-insensitive ordering: -SELECT * +SELECT * FROM AUTHOR ORDER BY upper(FIRST_NAME), upper(LAST_NAME) // Case-insensitive filtering: create.selectFrom(BOOK) .where(upper(BOOK.TITLE).eq("ANIMAL FARM")).fetch(); - + // Case-insensitive ordering: create.selectFrom(AUTHOR) .orderBy(upper(AUTHOR.FIRST_NAME), upper(AUTHOR.LAST_NAME)) @@ -6075,7 +6075,7 @@ create.selectFrom(AUTHOR)

    This is a list of date and time functions supported by jOOQ's :

    - +
    • CURRENT_DATE: Get current date as a DATE object.
    • CURRENT_TIME: Get current time as a TIME object.
    • @@ -6085,7 +6085,7 @@ create.selectFrom(AUTHOR)
    • TIMESTAMP_ADD: Add a number of days or an interval to a timestamp.
    • TIMESTAMP_DIFF: Get the difference as an INTERVAL DAY TO SECOND between two dates.
    - +

    Intervals in jOOQ

    jOOQ fills a gap opened by JDBC, which neglects an important SQL data type as defined by the SQL standards: INTERVAL types. See the manual's section about for more details. @@ -6237,7 +6237,7 @@ GROUP BY AUTHOR_ID WindowOverStep rank(); WindowOverStep denseRank(); WindowOverStep percentRank(); - + // Windowing functions WindowIgnoreNullsStep firstValue(Field field); WindowIgnoreNullsStep lastValue(Field field) @@ -6253,7 +6253,7 @@ GROUP BY AUTHOR_ID // Statistical functions WindowOverStep cumeDist(); WindowOverStep ntile(int number);]]> - +

    SQL distinguishes between various window function types (e.g. "ranking functions"). Depending on the function, SQL expects mandatory PARTITION BY or ORDER BY clauses within the OVER() clause. jOOQ does not enforce those rules for two reasons:

    @@ -6268,14 +6268,14 @@ GROUP BY AUTHOR_ID

    Here are some simple examples of window functions with jOOQ:

    - + -- Sample uses of ROW_NUMBER() ROW_NUMBER() OVER() ROW_NUMBER() OVER(PARTITION BY 1) ROW_NUMBER() OVER(ORDER BY BOOK.ID) ROW_NUMBER() OVER(PARTITION BY BOOK.AUTHOR_ID ORDER BY BOOK.ID) - + -- Sample uses of FIRST_VALUE FIRST_VALUE(BOOK.ID) OVER() FIRST_VALUE(BOOK.ID IGNORE NULLS) OVER() @@ -6286,14 +6286,14 @@ rowNumber().over() rowNumber().over().partitionByOne() rowNumber().over().partitionBy(BOOK.AUTHOR_ID) rowNumber().over().partitionBy(BOOK.AUTHOR_ID).orderBy(BOOK.ID) - + // Sample uses of firstValue() firstValue(BOOK.ID).over() firstValue(BOOK.ID).ignoreNulls().over() firstValue(BOOK.ID).respectNulls().over()
    - +

    An advanced window function example

    Window functions can be used for things like calculating a "running total". The following example fetches transactions and the running total for every transaction going back to the beginning of the transaction table (ordered by booked_at). Window functions are accessible from the previously seen type using the over() method: @@ -6321,7 +6321,7 @@ firstValue(BOOK.ID).respectNulls().over()

    In the previous chapter about , we have seen the concept of "ordered-set aggregate functions", such as Oracle's LISTAGG(). These functions have a window function / analytical function variant, as well. For example:

    - + SELECT LISTAGG(TITLE, ', ') WITHIN GROUP (ORDER BY TITLE) @@ -6406,7 +6406,7 @@ ORDER BY 1 NULLS LAST, 2 NULLS LAST

    In English, the ROLLUP() grouping function provides N+1 groupings, when N is the number of arguments to the ROLLUP() function. Each grouping has an additional group field from the ROLLUP() argument field list. The results of the second query might look something like this:

    - + GROUPING SETS() and other grouping functions:
    http://msdn.microsoft.com/en-us/library/bb510427(v=sql.105)

    - +

    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:

    - + ... fields); GroupField cube(Field... fields); @@ -6509,7 +6509,7 @@ Field groupingId(Field...);]]>

    MySQL and CUBRID don't know any grouping functions, but they support a WITH ROLLUP clause, that is equivalent to simple ROLLUP() grouping functions. jOOQ emulates ROLLUP() in MySQL and CUBRID, by rendering this WITH ROLLUP clause. The following two statements mean the same:

    - + Some databases support user-defined functions, which can be embedded in any SQL statement, if you're using jOOQ's . Let's say you have the following simple function in Oracle SQL:

    - + The above function will be made available from a generated class. You can use it like any other :

    - + - +

    Note that user-defined functions returning or data types can also be used wherever can be used, if they are

    @@ -6561,7 +6561,7 @@ END echo;

    Some databases support user-defined aggregate functions, which can then be used along with or as . An example for such a database is Oracle. With Oracle, you can define the following OBJECT type (the example was taken from the Oracle 11g documentation):

    - +

    jOOQ's will detect such aggregate functions and generate them differently from regular . They implement the type, as mentioned in the manual's section about . Here's how you can use the SECOND_MAX() aggregate function with jOOQ:

    - +
    - +
    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:

    - + Row1 row(T1 t1) { ... } public static Row2 row(T1 t1, T2 t2) { ... } @@ -6791,12 +6791,12 @@ public static RowN row(Object... values) { ... }]]>

    See the relevant sections for more details about how to use row value expressions in predicates.

    - +

    Using row value expressions in UPDATE statements

    The also supports a variant where row value expressions are updated, rather than single columns. See the relevant section for more details

    - +

    Higher-degree row value expressions

    jOOQ chose to explicitly support degrees up to {max-row-degree} to match Scala's typesafe tuple, function and product support. Unlike Scala, however, jOOQ also supports higher degrees without the additional typesafety. @@ -6820,7 +6820,7 @@ public static RowN row(Object... values) { ... }]]>

  • The of a
  • The 's ON clause
  • - +

    Boolean types in SQL

    Before SQL:1999, boolean types did not really exist in SQL. They were modelled by 0 and 1 numeric/char values. With SQL:1999, true booleans were introduced and are now supported by most databases. In short, these are possible boolean values: @@ -6916,7 +6916,7 @@ Condition combined2 = combined1.andNot(c); // The left-hand side of the AND NOT

    Here are all boolean operators on the interface:

    - + < to test for being strictly less
  • <= to test for being less or equal
  • - +

    Unfortunately, Java does not support operator overloading, hence these operators are also implemented as methods in jOOQ, like any other SQL syntax elements. The relevant parts of the interface are these:

    - + ); // = (some column expression) eq or equal(Select>); // = (some scalar SELECT statement) @@ -6978,12 +6978,12 @@ ge or greaterOrEqual(Select>); // >= (some scalar SELECT st

    Note that every operator is represented by two methods. A verbose one (such as equal()) and a two-character one (such as eq()). Both methods are the same. You may choose either one, depending on your taste. The manual will always use the more verbose one.

    - +

    jOOQ's convenience methods using comparison operators

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using comparison predicates:

    - +
    - +
    Boolean operator precedence @@ -7010,7 +7010,7 @@ BOOK.TITLE.notEqualIgnoreCase("animal farm")]]>

    In SQL, the two expressions wouldn't be the same, as SQL natively knows operator precedence.

    - + A AND B OR C AND D OR E -- Precedence is applied (((A AND B) OR C) AND D) OR E -- Precedence is overridden @@ -7024,7 +7024,7 @@ BOOK.TITLE.notEqualIgnoreCase("animal farm")]]>

    All variants of the that we've seen in the previous chapter also work for . If your database does not support row value expression comparison predicates, jOOQ emulates them the way they are defined in the SQL standard:

    - + (X, Y))]]>

    jOOQ supports all of the above row value expression comparison predicates, both with and at the right-hand side:

    - +
    - +
    Quantified comparison predicate @@ -7121,7 +7121,7 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    It is interesting to note that the SQL standard defines the in terms of the ANY-quantified predicate. The following two expressions are equivalent:

    - + @@ -7132,14 +7132,14 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    - +
    NULL predicate

    In SQL, you cannot compare NULL with any value using , as the result would yield NULL again, which is neither TRUE nor FALSE (see also the manual's section about ). In order to test a for NULL, use the NULL predicate as such:

    - + @@ -7177,7 +7177,7 @@ NOT((A, B) IS NOT NULL)]]>

    The SQL standard contains a nice truth table for the above rules:

    - + +-----------------------+-----------+---------------+---------------+-------------------+ | Expression | R IS NULL | R IS NOT NULL | NOT R IS NULL | NOT R IS NOT NULL | +-----------------------+-----------+---------------+---------------+-------------------+ @@ -7191,13 +7191,13 @@ NOT((A, B) IS NOT NULL)]]>

    In jOOQ, you would simply use the isNull() and isNotNull() methods on row value expressions. Again, as with the , the row value expression NULL predicate is emulated by jOOQ, if your database does not natively support it:

    - +
    - +
    DISTINCT predicate @@ -7224,7 +7224,7 @@ BOOK.TITLE.isNotDistinctFrom(BOOK.SUB_TITLE)]]>

    If your database does not natively support the DISTINCT predicate, jOOQ emulates it with an equivalent , modelling the above truth table:

    - + The BETWEEN predicate can be seen as syntactic sugar for a pair of . According to the SQL standard, the following two predicates are equivalent:

    - + = [B] AND [A] <= [C]]]> @@ -7273,7 +7273,7 @@ BOOK.PUBLISHED_IN.notBetween(1920).and(1940)]]>

    The SQL standard defines the SYMMETRIC keyword to be used along with BETWEEN to indicate that you do not care which bound of the range is larger than the other. A database system should simply swap range bounds, in case the first bound is greater than the second one. jOOQ supports this keyword as well, emulating it if necessary.

    - + @@ -7284,7 +7284,7 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The emulation is done trivially:

    - + @@ -7299,27 +7299,27 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The SQL BETWEEN predicate also works well for . Much like the , it is defined in terms of a pair of regular :

    - + = [B] AND [A] <= [C] ([A] >= [B] AND [A] <= [C]) OR ([A] >= [C] AND [A] <= [B])]]> - +

    The above can be factored out according to the rules listed in the manual's section about .

    - +

    jOOQ supports the BETWEEN [SYMMETRIC] predicate and emulates it in all SQL dialects where necessary. An example is given here:

    - + - +
    - +
    LIKE predicate @@ -7340,7 +7340,7 @@ TITLE NOT LIKE '%abc%']]> - +

    Escaping operands with the LIKE predicate

    Often, your pattern may contain any of the wildcard characters "_" and "%", in case of which you may want to escape them. jOOQ does not automatically escape patterns in like() and notLike() methods. Instead, you can explicitly define an escape character as such: @@ -7359,12 +7359,12 @@ BOOK.TITLE.notLike("%The !%-Sign Book%", '!')]]>

    Please refer to your database manual for more details about escaping patterns with the LIKE predicate.

    - +

    jOOQ's convenience methods using the LIKE predicate

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using the LIKE predicate. Typical operations are "contains predicates", "starts with predicates", "ends with predicates", etc. Here is the full convenience API wrapping LIKE predicates:

    - + >) // Construct a NOT IN predicate from a subse

    A sample IN predicate might look like this:

    - + @@ -7417,12 +7417,12 @@ TITLE NOT IN ('Animal Farm', '1984')]]>
    BOOK.TITLE.notIn("Animal Farm", "1984")]]>
    - +

    NOT IN and NULL values

    Beware that you should probably not have any NULL values in the right hand side of a NOT IN predicate, as the whole expression would evaluate to NULL, which is rarely desired. This can be shown informally using the following reasoning:

    - + -- The following conditional expressions are formally or informally equivalent A NOT IN (B, C) A != ANY(B, C) @@ -7463,7 +7463,7 @@ NULL -- [ANY] AND NULL yields NULL -- Using a subselect (BOOK.ID, BOOK.TITLE) IN ( SELECT T.ID, T.TITLE - FROM T + FROM T )]]> - +

    In both cases, i.e. when using an IN list or when using a subselect, the type of the predicate is checked. Both sides of the predicate must be of equal degree and row type.

    - +

    - Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value. + Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value.

    - +
    EXISTS predicate @@ -7497,7 +7497,7 @@ row(BOOK.ID, BOOK.TITLE).in(
  • From a using
  • From a using , and from other clauses
  • - +

    An example of an EXISTS predicate can be seen here:

    @@ -7516,7 +7516,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

    - +

    Performance of IN vs. EXISTS

    In theory, the two types of predicates can perform equally well. If your database system ships with a sophisticated cost-based optimiser, it will be able to transform one predicate into the other, if you have all necessary constraints set (e.g. referential constraints, not null constraints). However, in reality, performance between the two might differ substantially. An interesting blog post investigating this topic on the MySQL database can be seen here:
    @@ -7524,7 +7524,7 @@ notExists(create.selectOne().from(BOOK)

    - +
    OVERLAPS predicate @@ -7562,7 +7562,7 @@ row(Date.valueOf('2010-01-01'), new DayToSecond(2)).overlaps(Date.valueOf('2010-

    Unlike the standard (or any database implementing the standard), jOOQ also supports the OVERLAPS predicate for comparing arbitrary . For instance, (1, 3) OVERLAPS (2, 4) will yield true in jOOQ. This is emulated as such

    - +
    - +
    Dynamic SQL

    In most cases, , , and as introduced in the previous chapters will be embedded into different SQL statement clauses as if the statement were a static SQL statement (e.g. in a view or stored procedure):

    - + - +

    It is, however, interesting to think of all of the above expressions as what they are: expressions. And as such, nothing keeps users from extracting expressions and referencing them from outside the statement. The following statement is exactly equivalent:

    @@ -7606,26 +7606,26 @@ create.select(select) .groupBy(groupBy) .orderBy() .fetch();]]> - +

    Each individual expression, and collection of expressions can be seen as an independent entity that can be

    - +
    1. Constructed dynamically
    2. Reused across queries
    - +

    Dynamic construction is particularly useful in the case of the , for dynamic predicate building. For instance:

    - +

    The dynamic SQL building power may be one of the biggest advantages of using a runtime query model like the one offered by jOOQ. Queries can be created dynamically, of arbitrary complexity. In the above example, we've just constructed a dynamic . The same can be done for any other clauses, including dynamic , or adding additional as needed.

    @@ -7661,7 +7661,7 @@ create.select()
  • - +

    You'll probably find other examples. If verbosity scares you off, don't worry. The verbose use-cases for jOOQ are rather rare, and when they come up, you do have an option. Just write SQL the way you're used to!

    @@ -7691,7 +7691,7 @@ Condition condition(String sql, Object... bindings); // Construct a condition taking other jOOQ object arguments // Example: condition("a = {0}", val(1)); 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 DSL:

    @@ -7749,7 +7749,7 @@ Result fetch(String sql, QueryPart... parts);]]>

    Apart from the general factory methods, plain SQL is also available in various other contexts. For instance, when adding a .where("a = b") clause to a query. Hence, there exist several convenience methods where plain SQL can be inserted usefully. This is an example displaying all various use-cases in one single query:

    - + LAST_NAME = create.field("a.LAST_NAME"); @@ -7870,7 +7870,7 @@ Name name = name("AUTHOR", "TITLE");]]> On a JDBC level, you can also reuse the SQL string and prepared statement object instead of constructing it again, as you can bind new values to the prepared statement. jOOQ currently does not cache prepared statements, internally. - +

    The following sections explain how you can introduce bind values in jOOQ, and how you can control the way they are rendered and bound to SQL.

    @@ -7883,7 +7883,7 @@ Name name = name("AUTHOR", "TITLE");]]>

    JDBC only knows indexed bind values. A typical example for using bind values with JDBC is this:

    - + With dynamic SQL, keeping track of the number of question marks and their corresponding index may turn out to be hard. jOOQ abstracts this and lets you provide the bind value right where it is needed. A trivial example is this:

    - + 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

    Should you decide to run the above query outside of jOOQ, using your own , you can do so as follows:

    - + select = create.select().from(BOOK).where(BOOK.ID.equal(5)).and(BOOK.TITLE.equal("Animal Farm")); // Render the SQL statement: @@ -8038,7 +8038,7 @@ create.select()

    Special care needs to be taken when using . While jOOQ's API allows you to specify bind values for use with plain SQL, you're not forced to do that. For instance, both of the following queries will lead to the same, valid result:

    - +

    A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] FROM AUTHOR JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID @@ -8181,15 +8181,15 @@ public final void accept(Context context) {

    As mentioned in the previous chapter about , there are some elements in the that are used for formatting / pretty-printing rendered SQL. In order to obtain pretty-printed SQL, just use the following :

    - - + +

    And then, use the above DSLContext to render pretty-printed SQL:

    - + A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] WHERE AUTHOR.ID = ? -- [...] @@ -8278,7 +8278,7 @@ public final void bind(BindContext context) throws DataAccessException {

    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:

    - + extends AbstractField {} public abstract class CustomCondition extends AbstractCondition {} public abstract class CustomTable> extends TableImpl {} @@ -8287,7 +8287,7 @@ public abstract class CustomRecord> extends TableRecord

    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 method, as discussed before:

    - + 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 showing how to create a field multiplying another field by 2

    - + IDx2 = new CustomField(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(" * ?"); @@ -8327,10 +8327,10 @@ final Field IDx2 = new CustomField(BOOK.ID.getName(), BOOK.ID. @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(DSL.val(2)); } @@ -8349,7 +8349,7 @@ create.select(IDx2).from(BOOK).fetch();]]>

    Many vendor-specific functions are not officially supported by jOOQ, but you can implement such support yourself using CustomField, for instance. Here's an example showing how to implement Oracle's TO_CHAR() function, emulating it in SQL Server using CONVERT():

    - + { @@ -8386,7 +8386,7 @@ class ToChar extends CustomField {

    The above CustomField implementation can be exposed from your own custom DSL class:

    - + toChar(Field field, String format) { return new ToChar(field, DSL.inline(format)); @@ -8394,7 +8394,7 @@ class ToChar extends CustomField { }]]>
    - +
    Plain SQL QueryParts @@ -8408,7 +8408,7 @@ class ToChar extends CustomField {

    The above distinction is best explained using an example:

    - +

    - +
    Custom SQL transformation @@ -8456,7 +8456,7 @@ create.attach(select);]]> With jOOQ 3.2's SPI, it is possible to perform custom SQL transformation to implement things like shared-schema multi-tenancy, or a security layer centrally preventing access to certain data. This SPI is extremely powerful, as you can make ad-hoc decisions at runtime regarding local or global transformation of your SQL statement. The following sections show a couple of simple, yet real-world use-cases.

    - +
    Logging abbreviated bind values @@ -8464,7 +8464,7 @@ create.attach(select);]]>

    When implementing a logger, one needs to carefully assess how much information should really be disclosed on what logger level. In log4j and similar frameworks, we distinguish between FATAL, ERROR, WARN, INFO, DEBUG, and TRACE. In DEBUG level, jOOQ's logs all executed statements including inlined bind values as such:

    - + with bind values : select * from "BOOK" where "BOOK"."TITLE" like 'How I stopped worrying%']]> @@ -8480,7 +8480,7 @@ public class BindValueAbbreviator extends DefaultVisitListener { @Override public void visitStart(VisitContext context) { - + // Transform only when rendering values if (context.renderContext() != null) { QueryPart part = context.queryPart(); @@ -8494,16 +8494,16 @@ public class BindValueAbbreviator extends DefaultVisitListener { // e.g. using commons-lang's StringUtils.abbreviate() if (value instanceof String && ((String) value).length() > maxLength) { anyAbbreviations = true; - + // ... and replace it in the current rendering context (not in the Query) context.queryPart(val(abbreviate((String) value, maxLength))); } - + // If the bind value is a byte[] (or Blob) of a given length, abbreviate it // e.g. by removing bytes from the array else if (value instanceof byte[] && ((byte[]) value).length > maxLength) { anyAbbreviations = true; - + // ... and replace it in the current rendering context (not in the Query) context.queryPart(val(Arrays.copyOf((byte[]) value, maxLength))); } @@ -8513,10 +8513,10 @@ public class BindValueAbbreviator extends DefaultVisitListener { @Override public void visitEnd(VisitContext context) { - + // If any abbreviations were performed before... if (anyAbbreviations) { - + // ... and if this is the top-level QueryPart, then append a SQL comment to indicate the abbreviation if (context.queryPartsLength() == 1) { context.renderContext().sql(" -- Bind values may have been abbreviated"); @@ -8541,14 +8541,14 @@ public class BindValueAbbreviator extends DefaultVisitListener {
    - +
    SQL building in Scala

    jOOQ-Scala is a maven module used for leveraging some advanced Scala features for those users that wish to use jOOQ with Scala.

    - +

    Using Scala's implicit defs to allow for operator overloading

    The most obvious Scala feature to use in jOOQ are implicit defs for implicit conversions in order to enhance the type with SQL-esque operators. @@ -8556,7 +8556,7 @@ public class BindValueAbbreviator extends DefaultVisitListener {

    The following depicts a trait which wraps all fields:

    - + The following depicts a trait which wraps numeric fields:

    - + An example query using such overloaded operators would then look like this:

    - +

    In a previous section of the manual, we've seen how jOOQ can be used to that can be executed with any API including JDBC or ... jOOQ. This section of the manual deals with various means of actually executing SQL with jOOQ.

    - +

    SQL execution with JDBC

    JDBC calls executable objects "". It distinguishes between three types of statements: @@ -8696,7 +8696,7 @@ fetch]]>

    Today, the JDBC API may look weird to users being used to object-oriented design. While statements hide a lot of SQL dialect-specific implementation details quite well, they assume a lot of knowledge about the internal state of a statement. For instance, you can use the method, to add a the prepared statement being created to an "internal list" of batch statements. Instead of returning a new type, this method forces user to reflect on the prepared statement's internal state or "mode".

    - +

    jOOQ is wrapping JDBC

    These things are abstracted away by jOOQ, which exposes such concepts in a more object-oriented way. For more details about jOOQ's batch query execution, see the manual's section about . @@ -8718,7 +8718,7 @@ fetch]]>

  • Both APIs return the number of affected records in non-result queries. JDBC: , jOOQ:
  • Both APIs return a scrollable result set type from result queries. JDBC: , jOOQ:
  • - +

    Differences to JDBC

    Some of the most important differences between JDBC and jOOQ are listed here: @@ -8734,14 +8734,14 @@ fetch]]>

    - +
    Query vs. ResultQuery

    Unlike JDBC, jOOQ has a lot of knowledge about a SQL query's structure and internals (see the manual's section about ). Hence, jOOQ distinguishes between these two fundamental types of queries. While every can be executed, only can return results (see the manual's section about to learn more about fetching results). With plain SQL, the distinction can be made clear most easily:

    - + result = resultQuery.fetch();]]>
  • : Some databases allow for returning many result sets from a single query. JDBC can handle this but it's very verbose. A list of results should be returned instead.
  • : Some queries take too long to execute to wait for their results. You should be able to spawn query execution in a separate process.
  • - +

    Convenience and how ResultQuery, Result, and Record share API

    The term "fetch" is always reused in jOOQ when you can fetch data from the database. An provides many overloaded means of fetching data:

    - +

    Various modes of fetching

    These modes of fetching are also documented in subsequent sections of the manual

    - + fetch(); @@ -8803,7 +8803,7 @@ List> fetchMany(); // Execute a ResultQuery with jOOQ, but return a JDBC ResultSet, not a jOOQ object ResultSet fetchResultSet();]]> - +

    Fetch convenience

    These means of fetching are also available from and APIs @@ -8849,11 +8849,11 @@ ResultSet fetchResultSet();]]>

    These means of fetching are also available from and APIs

    - + Map fetchMap(Field key); Map fetchMap(Field key, Field value); @@ -8890,7 +8890,7 @@ ResultSet fetchResultSet();]]>

    jOOQ understands that SQL is much more expressive than Java, when it comes to the declarative typing of . As a declarative language, SQL allows for creating ad-hoc row value expressions (records with indexed columns, or tuples) and records (records with named columns). In Java, this is not possible to the same extent. Yet, still, sometimes you wish to use strongly typed records, when you know that you're selecting only from a single table

    - +

    Fetching strongly or weakly typed records

    When fetching data only from a single table, the type is known to jOOQ if you use jOOQ's to generate for your database tables. In order to fetch such strongly typed records, you will have to use the : @@ -8902,7 +8902,7 @@ BookRecord book = create.selectFrom(BOOK).where(BOOK.ID.equal(1)).fetchOne(); // Typesafe field access is now possible: 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:

    @@ -8948,7 +8948,7 @@ System.out.println("Published in: " + book.getPublishedIn());]]>

    By default, jOOQ returns an object, which is essentially a of . Often, you will find yourself wanting to transform this result object into a type that corresponds more to your specific needs. Or you just want to list all values of one specific column. Here are some examples to illustrate those use cases:

    - + titles1 = create.select().from(BOOK).fetch().getValues(BOOK.TITLE); List titles2 = create.select().from(BOOK).fetch(BOOK.TITLE); @@ -8983,7 +8983,7 @@ Map> group4 = create.selectFrom(BOOK).fetchGroups(BO

    In a more functional operating mode, you might want to write callbacks that receive records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + () {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -9018,7 +9018,7 @@ create.selectFrom(BOOK)

    In a more functional operating mode, you might want to write callbacks that map records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + ids = create.selectFrom(BOOK) @@ -9030,12 +9030,12 @@ create.selectFrom(BOOK) return book.getId(); } }); - + // Or more concisely create.selectFrom(BOOK) .orderBy(BOOK.ID) .fetch(new RecordMapper() {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -9061,7 +9061,7 @@ create.selectFrom(BOOK)

    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. See the manual's section about to see how to modify jOOQ's standard POJO mapping behaviour.

    - +

    Using JPA-annotated POJOs

    jOOQ tries to find JPA annotations on your POJO types. If it finds any, they are used as the primary source for mapping meta-information. Only the annotation is used and understood by jOOQ. An example: @@ -9071,7 +9071,7 @@ create.selectFrom(BOOK) public class MyBook { @Column(name = "ID") public int myId; - + @Column(name = "TITLE") public String myTitle; } @@ -9080,16 +9080,16 @@ public class MyBook { MyBook myBook = create.select().from(BOOK).fetchAny().into(MyBook.class); List myBooks = create.select().from(BOOK).fetch().into(MyBook.class); List myBooks = create.select().from(BOOK).fetchInto(MyBook.class);]]> - +

    Just as with any other JPA implementation, you can put the annotation on any class member, including attributes, setters and getters. Please refer to the Javadoc for more details.

    - +

    Using simple POJOs

    If jOOQ does not find any JPA-annotations, columns are mapped to the "best-matching" constructor, attribute or setter. An example illustrates this:

    - + myBooks = create.select().from(BOOK).fetchInto(MyBook1.class);]]><

    Please refer to the Javadoc for more details.

    - +

    Using "immutable" POJOs

    If jOOQ does not find any default constructor, columns are mapped to the "best-matching" constructor. This allows for using "immutable" POJOs with jOOQ. An example illustrates this:

    - + myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchInto( public class MyBook3 { public final String title; public final int id; - + @ConstructorProperties({ "title", "id"}) public MyBook2(String title, int id) { this.title = title; @@ -9144,7 +9144,7 @@ MyBook3 myBook = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchA List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetch().into(MyBook3.class); List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchInto(MyBook3.class); ]]> - +

    Please refer to the Javadoc for more details.

    @@ -9153,12 +9153,12 @@ List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchI

    jOOQ also allows for fetching data into abstract classes or interfaces, or in other words, "proxyable" types. This means that jOOQ will return a wrapped in a implementing your custom type. An example of this is given here:

    - + - +

    Note: Because of your manual setting of ID = 10, jOOQ's store() method will asume that you want to insert a new record. See the manual's section about for more details on this.

    - +

    Interaction with DAOs

    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: @@ -9225,21 +9225,21 @@ bookDao.update(book); // Delete it again bookDao.delete(book);]]> - +

    More complex data structures

    jOOQ currently doesn't support more complex data structures, the way Hibernate/JPA attempt to map relational data onto POJOs. While future developments in this direction are not excluded, jOOQ claims that generic mapping strategies lead to an enormous additional complexity that only serves very few use cases. You are likely to find a solution using any of jOOQ's various , with only little boiler-plate code on the client side.

    - +
    POJOs with RecordMappers

    In the previous sections we have seen how to create types to map jOOQ records onto arbitrary objects. We have also seen how jOOQ provides default algorithms to map jOOQ records onto . Your own custom domain model might be much more complex, but you want to avoid looking up the most appropriate RecordMapper every time you need one. For this, you can provide jOOQ's with your own implementation of the interface. An example is given here:

    - + } } } - + // Books might be joined with their authors, create a 1:1 mapping if (type == Book.class) { return new BookMapper(); @@ -9276,7 +9276,7 @@ bookDao.delete(book);]]>

    The above is a very simple example showing that you will have complete flexibility in how to override jOOQ's record to POJO mapping mechanisms.

    - +

    If you're looking into a generic, third-party mapping utility, have a look at ModelMapper, or Orika Mapper, which can both be easily integrated with jOOQ.

    @@ -9289,7 +9289,7 @@ bookDao.delete(book);]]>

    Unlike JDBC's , jOOQ's does not represent an open database cursor with various fetch modes and scroll modes, that needs to be closed after usage. jOOQ's results are simple in-memory Java objects, containing all of the result values. If your result sets are large, or if you have a lot of network latency, you may wish to fetch records one-by-one, or in small chunks. jOOQ supports a type for that purpose. In order to obtain such a reference, use the method. An example is given here:

    - + cursor = null; @@ -9299,7 +9299,7 @@ try { // Cursor has similar methods as Iterator while (cursor.hasNext()) { BookRecord book = cursor.fetchOne(); - + Util.doThingsWithBook(book); } } @@ -9314,7 +9314,7 @@ finally {

    As a holds an internal reference to an open , it may need to be closed at the end of iteration. If a cursor is completely scrolled through, it will conveniently close the underlying ResultSet. However, you should not rely on that.

    - +

    Cursors ship with all the other fetch features

    Like or , gives access to all of the other fetch features that we've seen so far, i.e. @@ -9356,7 +9356,7 @@ finally {

    The correct (and verbose) way to do this with JDBC is as follows:

    - +

    As previously discussed in the chapter about , jOOQ does not rely on an internal state of any JDBC object, which is "externalised" by Javadoc. Instead, it has a straight-forward API allowing you to do the above in a one-liner:

    - + > results = create.fetchMany("sp_help 'author'");]]> @@ -9397,22 +9397,22 @@ List> results = create.fetchMany("sp_help 'author'");]]>
    Later fetching

    Using Java 8 CompletableFutures

    - +

    Java 8 has introduced the new type, which allows for functional composition of asynchronous execution units. When applying this to SQL and jOOQ, you might be writing code as follows:

    - + + .supplyAsync(() -> DSL.using(configuration) .insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .values(3, "Hitchcock") .execute() ) - + // This will supply an AuthorRecord value for the newly inserted author .handleAsync((rows, throwable) -> DSL.using(configuration) @@ -9425,30 +9425,30 @@ CompletableFuture record.changed(true); return record.insert(); }) - + // This will supply an int value indicating the number of deleted rows - .handleAsync((rows, throwable) -> + .handleAsync((rows, throwable) -> DSL.using(configuration) .delete(AUTHOR) .where(AUTHOR.ID.eq(3)) .execute() ) .join();]]> - +

    The above example will execute four actions one after the other, but asynchronously in the JDK's default or common . -

    - +

    +

    For more information, please refer to the Javadoc and official documentation. -

    - +

    +

    Using deprecated API

    - +

    Some queries take very long to execute, yet they are not crucial for the continuation of the main program. For instance, you could be generating a complicated report in a Swing application, and while this report is being calculated in your database, you want to display a background progress bar, allowing the user to pursue some other work. This can be achived simply with jOOQ, by creating a , a type that extends . An example is given here:

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(); @@ -9464,7 +9464,7 @@ Result result = future.get();]]>

    Note, that instead of letting jOOQ spawn a new thread, you can also provide jOOQ with your own :

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(service);]]> @@ -9478,7 +9478,7 @@ FutureResult future = create.selectFrom(BOOK).where(... complex pred

    When interacting with legacy applications, you may prefer to have jOOQ return a , rather than jOOQ's own types. This can be done simply, in two ways:

    - + cursor = create.fetchLazy(rs);]]>

    You can also tighten the interaction with jOOQ's data type system and features, by passing the record type to the above fetch methods:

    - + result = create.fetch (rs, Integer.class, String.class); Cursor result = create.fetchLazy(rs, Integer.class, String.class); @@ -9540,7 +9540,7 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Apart from a few extra features (), jOOQ only supports basic types as supported by the JDBC API. In your application, you may choose to transform these data types into your own ones, without writing too much boiler-plate code. This can be done using jOOQ's types. A converter essentially allows for two-way conversion between two Java data types <T> and <U>. By convention, the <T> type corresponds to the type in your database whereas the <U> type corresponds to your own user type. The Converter API is given here:

    - + extends Serializable { /** @@ -9567,12 +9567,12 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Such a converter can be used in many parts of the jOOQ API. Some examples have been illustrated in the manual's section about .

    - +

    A Converter for GregorianCalendar

    Here is a some more elaborate example involving a Converter for :

    - + { @@ -9603,12 +9603,12 @@ public class CalendarConverter implements Converter dates1 = create.selectFrom(BOOK).fetch().getValues(BOOK.PUBLISHING_DATE, new CalendarConverter()); List dates2 = create.selectFrom(BOOK).fetch(BOOK.PUBLISHING_DATE, new CalendarConverter()); ]]> - +

    Enum Converters

    jOOQ ships with a built-in default , that you can use to map VARCHAR values to enum literals or NUMBER values to enum ordinals (both modes are supported). Let's say, you want to map a YES / NO / MAYBE column to a custom Enum:

    - + - +

    Using Converters in generated source code

    jOOQ also allows for generated source code to reference your own custom converters, in order to permanently replace a <T> type by your own, custom <U> type. See the manual's section about for details. @@ -9670,20 +9670,20 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE) .join(AUTHOR).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) .intern(BOOK.AUTHOR_ID) .fetch();]]> - +

    You can specify as many fields as you want for interning. The above has the following effect:

    - +
    • If the interned Field is of type , then is called upon each string
    • If the interned Field is of any other type, then the call is ignored
    - +

    Future versions of jOOQ will implement interning of data for non-String data types by collecting values in , removing duplicate instances.

    - +

    Note, that jOOQ will not use interned data for identity comparisons: string1 == string2. Interning is used only to reduce the memory footprint of objects.

    @@ -9691,7 +9691,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)
    - +
    Static statements vs. Prepared Statements @@ -9701,7 +9701,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)

    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:

    - + @@ -9731,7 +9731,7 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    Whichever aproach is more optimal for you cannot be decided by jOOQ. In most cases, prepared statements are probably better. But you always have the option of forcing jOOQ to render inlined bind values.

    - +

    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 @@ -9745,15 +9745,15 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    As previously discussed in the chapter about , reusing PreparedStatements is handled a bit differently in jOOQ from how it is handled in JDBC

    - +

    Keeping open PreparedStatements with JDBC

    With JDBC, you can easily reuse a by not closing it between subsequent executions. An example is given here:

    - + The above technique can be quite useful when you want to reuse expensive database resources. This can be the case when your statement is executed very frequently and your database would take non-negligible time to soft-parse the prepared statement and generate a new statement / cursor resource.

    - +

    Keeping open PreparedStatements with jOOQ

    This is also modeled in jOOQ. However, the difference to JDBC is that closing a statement is the default action, whereas keeping it open has to be configured explicitly. This is better than JDBC, because the default action should be the one that is used most often. Keeping open statements is rarely done in average applications. Here's an example of how to keep open PreparedStatements with jOOQ:

    - + query = create.selectOne().keepStatement(true); @@ -9787,7 +9787,7 @@ finally {

    The above example shows how a query can be executed twice against the same underlying PreparedStatement. Unlike in other execution scenarios, you must not forget to close this query now

    - +

    Beware of resource leaks

    While jOOQ allows for explicitly keeping open PreparedStatement references in Query instances, the JDBC Connection may still be closed independently without jOOQ or the PreparedStatement noticing. It is the user's responsibility to close all resources according to the specification and behaviour of the concrete JDBC driver and the underlying database. @@ -9801,7 +9801,7 @@ finally {

    JDBC knows a couple of execution flags and modes, which can be set through the jOOQ API as well. jOOQ essentially supports these flags and execution modes:

    - + - + extends Query { // [...] @@ -9834,25 +9834,25 @@ finally { // The maximum number of rows to be fetched by JDBC // ----------------------------------------------------------- ResultQuery maxRows(int rows); - + }]]>

    Using ResultSet concurrency with ExecuteListeners

    An example of why you might want to manually set a ResultSet's concurrency flag to something non-default is given here:

    - + - +

    In the above example, your custom is triggered before jOOQ loads a new Record from the JDBC ResultSet. With the concurrency being set to ResultSet.CONCUR_UPDATABLE, you can now modify the database cursor through the standard JDBC ResultSet API.

    @@ -9970,18 +9970,18 @@ create.batch(create.insertInto(AUTHOR, ID, FIRST_NAME, LAST_NAME ).values((Inte

    Instead of actually phrasing a select statement, you can also use the convenience methods:

    - + - +

    Inlining sequence references in SQL

    You can inline sequence references in jOOQ SQL statements. The following are examples of how to do that:

    - + The general distinction between (stored) procedures and (stored) functions can be summarised like this:

    - +

    Procedures

    • Are called using JDBC CallableStatement
    • Have no return value
    • Usually support OUT parameters
    - +

    Functions

    • Can be used in SQL statements
    • Have a return value
    • Usually don't support OUT parameters
    - +

    Exceptions to these rules

    • DB2, H2, and HSQLDB don't allow for JDBC escape syntax when calling functions. Functions must be used in a SELECT statement
    • @@ -10042,19 +10042,19 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

      To simplify things a little bit, jOOQ handles both procedures and functions the same way, using a more general type.

      - +

      Using jOOQ for standalone calls to stored procedures and functions

      If you're using jOOQ's , it will generate objects for you. Let's consider the following example:

      - +

      The generated artefacts can then be used as follows:

      - + - +

      But you can also call the procedure using a generated convenience method in a global Routines class:

      @@ -10081,7 +10081,7 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]>

      For more details about for procedures, see the manual's section about .

      - +

      Inlining stored function references in SQL

      Unlike procedures, functions can be inlined in SQL statements to generate or , if you're using . Assume you have a function like this: @@ -10089,11 +10089,11 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]> - +

      The generated artefacts can then be used as follows:

      - + boolean exists = create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]> - +

      For more info about inlining stored function references in SQL statements, please refer to the manual's section about .

      @@ -10134,7 +10134,7 @@ create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]>

      Oracle UDTs can have object-oriented structures including member functions and procedures. With Oracle, you can do things like this:

      - + {"name":"field-n","type":"type-n"}], "records":[[value-1-1,value-1-2,...,value-1-n], [value-2-1,value-2-2,...,value-2-n]]} - +

      Note: This format has changed in jOOQ 2.6.0

      @@ -10449,7 +10449,7 @@ Query query = error.query();]]>
    - +
    Importing JSON @@ -10508,12 +10508,12 @@ create.loadInto(BOOK)

    CRUD always uses the same patterns, regardless of the nature of underlying tables. This again, leads to a lot of boilerplate code, if you have to issue your statements yourself. Like Hibernate / JPA and other ORMs, jOOQ facilitates CRUD using a specific API involving types.

    - +

    Primary keys and updatability

    In normalised databases, every table has a primary key by which a tuple/record within that table can be uniquely identified. In simple cases, this is a (possibly auto-generated) number called ID. But in many cases, primary keys include several non-numeric columns. An important feature of such keys is the fact that in most databases, they are enforced using an index that allows for very fast random access to the table. A typical way to access / modify / delete a book is this:

    - + - +

    Normalised databases assume that a primary key is unique "forever", i.e. that a key, once inserted into a table, will never be changed or re-inserted after deletion. In order to use jOOQ's operations correctly, you should design your database accordingly.

    @@ -10534,7 +10534,7 @@ DELETE FROM BOOK WHERE ID = 5;]]>

    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:

    - + - +

    See the manual's section about for some more insight on "attached" objects.

    - +

    Storing

    Storing a record will perform an or an . In general, new records are always inserted, whereas records loaded from the database are always updated. This is best visualised in code: @@ -10573,7 +10573,7 @@ BookRecord book2 = create.fetchOne(BOOK, BOOK.ID.equal(id)); // Update the record: UPDATE BOOK SET TITLE = 'Animal Farm' WHERE ID = [id] book2.setTitle("Animal Farm"); book2.store();]]> - +

    Some remarks about storing:

    @@ -10583,18 +10583,18 @@ book2.store();]]>
  • When loading records from , jOOQ will assume the record is a new record. It will hence attempt to INSERT it.
  • When you activate , storing a record may fail, if the underlying database record has been changed in the mean time.
  • - +

    Deleting

    Deleting a record will remove it from the database. Here's how you delete records:

    - + - +

    Refreshing

    Refreshing a record from the database means that jOOQ will issue a to refresh all record values that are not the primary key. This is particularly useful when you use jOOQ's feature, in case a modified record is "stale" and cannot be stored to the database, because the underlying database record has changed in the mean time. @@ -10613,7 +10613,7 @@ book.refresh();]]>

    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 :

    - + The "original" value, i.e. the value as it was originally fetched from the database or null, if the record was never in the database
  • The "changed" flag, indicating if the value was ever changed through the Record API.
  • - +

    The purpose of the above information is for jOOQ's to know, which values need to be stored to the database, and which values have been left untouched.

    @@ -10649,19 +10649,19 @@ for (BookRecord book : create.fetch(BOOK, BOOK.PUBLISHED_IN.equal(1948))) {

    Many databases support the concept of IDENTITY values, or key values. This is reflected by JDBC's method. jOOQ abstracts using this method as many databases and JDBC drivers behave differently with respect to generated keys. Let's assume the following SQL Server BOOK table:

    - +

    If you're using jOOQ's , the above table will generate a with an IDENTITY column. This information is used by jOOQ internally, to update IDs after calling :

    - +

    and contain foreign key navigation methods. These navigation methods allow for "navigating" inbound or outbound foreign key references by executing an appropriate query. An example is given here:

    - + books = author.fetchChildren(FK_BOOK_AUTHOR);]]>

    Tables without a PRIMARY KEY are considered non-updatable by jOOQ, as jOOQ has no way of uniquely identifying such a record within the database. If you're using jOOQ's , such tables will generate classes, instead of classes. When you fetch from such a table, the returned records will not allow for calling any of the methods.

    - +

    Note, that some databases use internal rowid or object-id values to identify such records. jOOQ does not support these vendor-specific record meta-data.

    @@ -10792,7 +10792,7 @@ Result books = author.fetchChildren(FK_BOOK_AUTHOR);]]>
    - +

    Optimised optimistic locking using TIMESTAMP fields

    If you're using jOOQ's , you can take indicate TIMESTAMP or UPDATE COUNTER fields for every generated table in the . Let's say we have this table:

    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:

    - +

    As before, without the added TIMESTAMP column, optimistic locking is transparent to the API.

    - +

    Optimised optimistic locking using VERSION fields

    Instead of using TIMESTAMPs, you may also use numeric VERSION fields, containing version numbers that are incremented by jOOQ upon store() calls. @@ -10861,7 +10861,7 @@ book2.store();]]>

    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:

    - + books = create.fetch(BOOK); @@ -10877,7 +10877,7 @@ create.batchStore(books);]]>

    - +
    CRUD SPI: RecordListener @@ -10888,11 +10888,11 @@ create.batchStore(books);]]>
  • Adding a central ID generation algorithm, generating UUIDs for all of your records.
  • Adding a central record initialisation mechanism, preparing the database prior to inserting a new record.
  • - +

    An example of such a RecordListener is given here:

    - + - +

    Now, configure jOOQ's runtime to load your listener

    @@ -10932,7 +10932,7 @@ DSLContext create = DSL.using(configuration);]]>

    If you're using jOOQ's , you can configure it to generate and DAOs for you. jOOQ then generates one DAO per , i.e. per table with a single-column primary key. Generated DAOs implement a common jOOQ type called . This type contains the following methods:

    - + corresponds to the DAO's related table //

    corresponds to the DAO's related generated POJO type // corresponds to the DAO's related table's primary key type. @@ -10943,23 +10943,23 @@ public interface DAO, P, T> { void insert(P object) throws DataAccessException; void insert(P... objects) throws DataAccessException; void insert(Collection

    objects) throws DataAccessException; - + // These methods allow for updating POJOs based on their primary key void update(P object) throws DataAccessException; void update(P... objects) throws DataAccessException; void update(Collection

    objects) throws DataAccessException; - + // These methods allow for deleting POJOs based on their primary key void delete(P... objects) throws DataAccessException; void delete(Collection

    objects) throws DataAccessException; void deleteById(T... ids) throws DataAccessException; void deleteById(Collection ids) throws DataAccessException; - + // These methods allow for checking record existence boolean exists(P object) throws DataAccessException; boolean existsById(T id) throws DataAccessException; long count() throws DataAccessException; - + // These methods allow for retrieving POJOs by primary key or by some other field List

    findAll() throws DataAccessException; P findById(T id) throws DataAccessException; @@ -10988,7 +10988,7 @@ public class BookDao extends DAOImpl {

    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:

    - +

    Note how the lambda expression receives a new, derived configuration that should be used within the local scope:

    - + { // Wrap configuration in a new DSLContext: DSL.using(configuration).insertInto(...); DSL.using(configuration).insertInto(...); - + // Or, reuse the new DSLContext within the transaction scope: DSLContext ctx = DSL.using(configuration); ctx.insertInto(...); ctx.insertInto(...); - + // ... but avoid using the scope from outside the transaction: create.insertInto(...); create.insertInto(...); }); ]]> - +

    - While some implementations (e.g. ones based on ThreadLocals, e.g. Spring or JTA) may allow you to reuse the globally scoped reference, the jOOQ transaction API design allows for TransactionProvider implementations that require your transactional code to use the new, locally scoped Configuration, instead. + While some implementations (e.g. ones based on ThreadLocals, e.g. Spring or JTA) may allow you to reuse the globally scoped reference, the jOOQ transaction API design allows for TransactionProvider implementations that require your transactional code to use the new, locally scoped Configuration, instead.

    @@ -11209,7 +11209,7 @@ class SpringTransaction implements Transaction {

    With jOOQ, it's simple. All of jOOQ's exceptions are "system exceptions", hence they are all unchecked.

    - +

    jOOQ's DataAccessException

    jOOQ uses its own to wrap any underlying that might have occurred. Note that all methods in jOOQ that may cause such a DataAccessException document this both in the Javadoc as well as in their method signature. @@ -11225,7 +11225,7 @@ class SpringTransaction implements Transaction {

  • InvalidResultException: An operation was performed expecting only one result, but several results were returned.
  • MappingException: Something went wrong when loading a record from a or when mapping a record into a POJO
  • - +

    Override jOOQ's exception handling

    The following section about documents means of overriding jOOQ's exception handling, if you wish to deal separately with some types of constraint violations, or if you raise business errors from your database, etc. @@ -11242,7 +11242,7 @@ class SpringTransaction implements Transaction {

    For convenience and better backwards-compatibility, consider extending instead of implementing this interface.

    - +

    Example: Query statistics ExecuteListener

    Here is a sample implementation of an ExecuteListener, that is simply counting the number of queries per type that are being executed using jOOQ: @@ -11259,11 +11259,11 @@ public class StatisticsListener extends DefaultExecuteListener { public void start(ExecuteContext ctx) { synchronized (STATISTICS) { Integer count = STATISTICS.get(ctx.type()); - + if (count == null) { count = 0; } - + STATISTICS.put(ctx.type(), count + 1); } } @@ -11306,7 +11306,7 @@ for (ExecuteType type : ExecuteType.values()) {

    Please read the for more details

    - +

    Example: Custom Logging ExecuteListener

    The following depicts an example of a custom ExecuteListener, which pretty-prints all queries being executed by jOOQ to stdout: @@ -11329,7 +11329,7 @@ public class PrettyPrinter extends DefaultExecuteListener { // Create a new DSLContext for logging rendering purposes // This DSLContext doesn't need a connection, only the SQLDialect... DSLContext create = DSL.using(ctx.configuration().dialect(), - + // ... and the flag for pretty-printing new Settings().withRenderFormatted(true)); @@ -11337,12 +11337,12 @@ public class PrettyPrinter extends DefaultExecuteListener { if (ctx.query() != null) { System.out.println(create.renderInlined(ctx.query())); } - + // If we're executing a routine else if (ctx.routine() != null) { System.out.println(create.renderInlined(ctx.routine())); } - + // If we're executing anything else (e.g. plain SQL) else if (!StringUtils.isBlank(ctx.sql())) { System.out.println(ctx.sql()); @@ -11352,12 +11352,12 @@ public class PrettyPrinter extends DefaultExecuteListener {

    See also the manual's sections about for more sample implementations of actual ExecuteListeners.

    - +

    Example: Bad query execution ExecuteListener

    You can also use ExecuteListeners to interact with your SQL statements, for instance when you want to check if executed or statements contain a WHERE clause. This can be achieved trivially with the following sample ExecuteListener:

    - + 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:

    - + @@ -11409,7 +11409,7 @@ public class DeleteOrUpdateWithoutWhereException extends RuntimeException {}

    With the above configuration, let's fetch some data with jOOQ

    - +

    @@ -11457,7 +11457,7 @@ Finishing : Total: 4.814ms, +3.375ms

  • 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
  • - +

    Optimise wisely

    Don't be put off by the above paragraphs. You should optimise wisely, i.e. only in places where you really need very high throughput to your database. jOOQ's overhead compared to plain JDBC is typically less than 1ms per query. @@ -11514,7 +11514,7 @@ Finishing : Total: 4.814ms, +3.375ms

    You need to tell jOOQ some things about your database connection. Here's an example of how to do it for an Oracle database

    - + @@ -11523,7 +11523,7 @@ Finishing : Total: 4.814ms, +3.375ms jdbc:oracle:thin:@[your jdbc connection parameters] [your database user] [your database password] - + user[db-user] @@ -11559,9 +11559,9 @@ Finishing : Total: 4.814ms, +3.375ms Use the pipe to separate several expressions) Watch out for case-sensitivity. Depending on your database, this might be important! - + You can create case-insensitive regular expressions using this syntax: (?i:expr) - + Whitespace is ignored and comments are possible. --> .* @@ -11592,7 +11592,7 @@ Finishing : Total: 4.814ms, +3.375ms @@ -11613,13 +11613,13 @@ Finishing : Total: 4.814ms, +3.375ms

    Code generation works by calling this class with the above property file as argument.

    - + org.jooq.util.GenerationTool /jooq-config.xml

    Be sure that these elements are located on the classpath:

    - +
    • The XML configuration file
    • jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar
    • @@ -11644,7 +11644,7 @@ Finishing : Total: 4.814ms, +3.375ms
    • this example uses jOOQ's log4j support by adding log4j.xml and log4j.jar to the project classpath.
    • the actual jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar artefacts may contain version numbers in the file names.
    - +
    Eclipse configuration
    @@ -11746,7 +11746,7 @@ Finishing : Total: 4.814ms, +3.375ms

    - +
    Running the code generator with Ant @@ -11757,14 +11757,14 @@ Finishing : Total: 4.814ms, +3.375ms - - + ]]> @@ -11783,7 +11783,7 @@ Finishing : Total: 4.814ms, +3.375ms generate-sources - @@ -11795,7 +11795,7 @@ Finishing : Total: 4.814ms, +3.375ms - + @@ -11809,7 +11809,7 @@ Finishing : Total: 4.814ms, +3.375ms ]]>
    - +
    Running the code generator with Gradle @@ -11817,7 +11817,7 @@ Finishing : Total: 4.814ms, +3.375ms

    We recommend using the Gradle plugin by Etienne Studer (from Gradle Inc.). It provides a concise DSL that allows you to tune all configuration properties supported by each jOOQ version. Please direct any support questions or issues you may find directly to the third party plugin vendor.

    - +

    Alternatively, the XML MarkupBuilder can be used

    If you don't want to use the above third party plugin, there's also the possibility to use jOOQ's standalone code generator for simplicity. The following working example build.gradle script should work out of the box: @@ -11961,7 +11961,7 @@ org.jooq.util.GenerationTool.generate( production schema. Use this to override your local development schema name for source code generation. If not specified, this will be the same as the input-schema. - + This will be ignored if outputSchemaToDefault is set to true --> [your database schema / owner / name] @@ -12055,30 +12055,30 @@ org.jooq.util.GenerationTool.generate( false - + true - + false ]]> @@ -12087,7 +12087,7 @@ org.jooq.util.GenerationTool.generate(

    Some of the above properties depend on other properties to work correctly. For instance, when generating immutable pojos, pojos must be generated. jOOQ will enforce such properties even if you tell it otherwise. Here is a list of property interdependencies:

    - +
    • When daos = true, then jOOQ will set relations = true
    • When daos = true, then jOOQ will set records = true
    • @@ -12096,7 +12096,7 @@ org.jooq.util.GenerationTool.generate(
    - +
    Programmatic generator configuration @@ -12104,7 +12104,7 @@ org.jooq.util.GenerationTool.generate(

    In the previous sections, we have covered how to set up jOOQ's code generator using XML, either by running a standalone Java application, or by using Maven. However, it is also possible to use jOOQ's GenerationTool programmatically. The XSD file used for the configuration (http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd) is processed using XJC to produce Java artefacts. The below example uses those artefacts to produce the equivalent configuration of the previous :

    - +

    - +
    Custom generator strategies @@ -12141,7 +12141,7 @@ GenerationTool.main(configuration);]]>

    jOOQ allows you to override default implementations of the code generator or the generator strategy. Specifically, the latter can be very useful if you want to inject custom behaviour into jOOQ's code generator with respect to naming classes, members, methods, and other Java objects.

    - + @@ -12366,58 +12366,58 @@ public class Book implements java.io.Serializable { - + MY_SCHEMA - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + - + MY_TABLE - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomBaseClasscom.example.MyOptionalCustomInterface
    - + - + MY_FIELD - + --> MatcherRule --> MatcherRule @@ -12425,30 +12425,30 @@ public class Book implements java.io.Serializable { --> MatcherRule - + - + MY_ROUTINE - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + - + MY_SEQUENCE - + --> MatcherRule @@ -12464,19 +12464,19 @@ public class Book implements java.io.Serializable { CAMEL - + PREFIX_$0_SUFFIX ]]> - +

    Some examples

    The following example shows a matcher strategy that adds a "T_" prefix to all table classes and to table identifiers: @@ -12487,7 +12487,7 @@ public class Book implements java.io.Serializable { - + UPPER @@ -12522,13 +12522,13 @@ public class Book implements java.io.Serializable { ]]> - +

    For more information about each XML tag, please refer to the http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd XSD file.

    - +
    Custom code sections @@ -12551,11 +12551,11 @@ public class Book implements java.io.Serializable {

    The above example simply adds a class footer to , in this case, overriding the default toString() implementation.

    - +

    Any of the below methods can be overridden:

    - + Tables.java: This file contains all table objects in the form of static member references to the actual singleton object
  • UDTs.java: This file contains all UDT objects in the form of static member references to the actual singleton object
  • - +

    Referencing global artefacts

    When referencing global artefacts from your client application, you would typically static import them as such:

    - + @@ -12639,7 +12639,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate a implementation that looks like this:

    - + { // The singleton instance @@ -12655,7 +12655,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE) public Book as(java.lang.String alias) { return new Book(alias); } - + // [...] }]]> @@ -12674,7 +12674,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)
  • instanceFields: This flag controls the "static" keyword on table columns, as well as aliasing convenience
  • records: The generated record type is referenced from tables allowing for type-safe single-table record fetching
  • - +

    Flags controlling table generation

    Table generation cannot be deactivated @@ -12688,7 +12688,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate an implementation that looks like this:

    - + - +

    Flags influencing generated records

    These flags from the influence generated records: @@ -12746,7 +12746,7 @@ implements IBook {

  • interfaces: If interfaces are generated, records will implement them
  • jpaAnnotations: JPA annotations are used on generated records
  • - +

    Flags controlling record generation

    Record generation can be deactivated using the records flag @@ -12760,7 +12760,7 @@ implements IBook {

    Every table in your database will generate a POJO implementation that looks like this:

    - + - +

    Flags influencing generated POJOs

    These flags from the influence generated POJOs: @@ -12809,7 +12809,7 @@ public class Book implements java.io.Serializable

  • jpaAnnotations: JPA annotations are used on generated records
  • validationAnnotations: JSR-303 validation annotations are used on generated records
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the pojos flag @@ -12823,16 +12823,16 @@ public class Book implements java.io.Serializable

    Every table in your database will generate an interface that looks like this:

    - + - +

    Flags influencing generated interfaces

    These flags from the influence generated interfaces: @@ -12841,7 +12841,7 @@ public class Book implements java.io.Serializable

  • dateAsTimestamp: This influences all relevant getters and setters
  • unsignedTypes: This influences all relevant getters and setters
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the interfaces flag @@ -12856,7 +12856,7 @@ public class Book implements java.io.Serializable

    Every table in your database will generate a implementation that looks like this:

    - + { // Generated constructors @@ -12880,10 +12880,10 @@ public class Book implements java.io.Serializable public List fetchByAuthorId(Integer... values) { return fetch(BOOK.AUTHOR_ID, values); } - + // [...] }]]> - +

    Flags controlling DAO generation

    DAO generation can be activated using the daos flag @@ -12897,13 +12897,13 @@ public class Book implements java.io.Serializable

    Every sequence in your database will generate a implementation that looks like this:

    - + S_AUTHOR_ID = new SequenceImpl("S_AUTHOR_ID", TEST, SQLDataType.INTEGER); }]]> - +

    Flags controlling sequence generation

    Sequence generation cannot be deactivated @@ -12941,7 +12941,7 @@ public class Book implements java.io.Serializable public BigDecimal getResult() { return getValue(RESULT); } - + // [...] }]]> @@ -12963,7 +12963,7 @@ public class Book implements java.io.Serializable

    Every UDT in your database will generate a implementation that looks like this:

    - + { // The singleton UDT instance @@ -12976,10 +12976,10 @@ public class Book implements java.io.Serializable createField("CITY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); public static final UDTField COUNTRY = createField("COUNTRY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); - + // [...] }]]> - +

    Besides the implementation, a implementation is also generated

    @@ -12994,7 +12994,7 @@ public class Book implements java.io.Serializable public String getCity() {...} public void setCountry(String value) {...} public String getCountry() {...} - + // [...] }]]>
    @@ -13023,12 +13023,12 @@ public class Book implements java.io.Serializable BOOLEAN .*\.IS_VALID - + .* @@ -13059,7 +13059,7 @@ public class Book implements java.io.Serializable GregorianCalendar - + java.util.GregorianCalendar @@ -13075,12 +13075,12 @@ public class Book implements java.io.Serializable GregorianCalendar .*\.DATE_OF_.* - + .* @@ -13134,23 +13134,23 @@ create.selectFrom(AUTHOR)
    - +
    Code generation for large schemas

    Databases can become very large in real-world applications. This is not a problem for jOOQ's code generator, but it can be for the Java compiler. jOOQ generates some classes for . These classes can hit two sorts of limits of the compiler / JVM:

    - +
    • Methods (including static / instance initialisers) are allowed to contain only 64kb of bytecode.
    • Classes are allowed to contain at most 64k of constant literals
    - +

    While there exist workarounds for the above two limitations (delegating initialisations to nested classes, inheriting constant literals from implemented interfaces), the preferred approach is either one of these:

    - +
    • Distribute your database objects in several schemas. That is probably a good idea anyway for such large databases
    • to exclude excess database objects
    • @@ -13233,11 +13233,11 @@ create.selectFrom(AUTHOR)

      When writing unit tests for your data access layer, you have probably used some generic mocking tool offered by popular providers like Mockito, jmock, mockrunner, or even DBUnit. With jOOQ, you can take advantage of the built-in JDBC mock API that allows you to emulate a simple database on the JDBC level for precisely those SQL/JDBC use cases supported by jOOQ.

      - +

      - Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider. + Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider.

      - +

      Mocking the JDBC API

      JDBC is a very complex API. It takes a lot of time to write a useful and correct mock implementation, implementing at least these interfaces: @@ -13250,16 +13250,16 @@ create.selectFrom(AUTHOR)

    - +

    Optionally, you may even want to implement interfaces, such as , , , and many others. In addition to the above, you might need to find a way to simultaneously support incompatible JDBC minor versions, such as 4.0, 4.1

    - +

    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 :

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    As you can see, the configuration setup is simple. Now, the MockDataProvider acts as your single point of contact with JDBC / jOOQ. It unifies any of these execution modes, transparently:

    - +
    • Statements without results
    • Statements without results but with generated keys
    • @@ -13282,16 +13282,16 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
    • Batch statements with single queries and multiple bind value sets
    • Batch statements with multiple queries and no bind values
    - +

    The above are the execution modes supported by jOOQ. Whether you're using any of jOOQ's various fetching modes (e.g. , , , ) is irrelevant, as those modes are all built on top of the standard JDBC API.

    - +

    Implementing MockDataProvider

    Now, here's how to implement MockDataProvider:

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc // 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 String sql = ctx.sql(); - + // Exceptions are propagated through the JDBC and jOOQ APIs if (sql.toUpperCase().startsWith("DROP")) { throw new SQLException("Statement not supported: " + sql); } - + // You decide, whether any given statement returns results, and how many else if (sql.toUpperCase().startsWith("SELECT")) { - + // Always return one author record Result result = create.newResult(AUTHOR); result.add(create.newRecord(AUTHOR)); @@ -13319,12 +13319,12 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc result.get(0).setValue(AUTHOR.LAST_NAME, "Orwell"); mock[0] = new MockResult(1, result); } - + // You can detect batch statements easily else if (ctx.batch()) { // [...] } - + return mock; } }]]> @@ -13336,17 +13336,17 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • : The number of affected rows
  • : The result set
  • - +

    You should return as many MockResult objects as there were query executions (in ) or results (in ). Instead of an awkward JDBC ResultSet, however, you can construct a "friendlier" with your own record types. The jOOQ mock API will use meta data provided with this Result in order to create the necessary JDBC

    - +

    See the for a list of rules that you should follow.

    - +
    SQL 2 jOOQ Parser @@ -13356,20 +13356,20 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    Gudu Software Ltd has been selling enterprise quality SQL software to hundreds of customers to help them migrate from one database to another using the General SQL Parser. Now you can take advantage of their knowledge to parse your SQL statements and transform them directly into jOOQ statements using a free trial version of SQL 2 jOOQ!

    - +

    It's as simple as this!

    - +
    • Create a JDBC connection
    • Create a new SQL2jOOQ converter object
    • Convert your SQL code
    • Get the result
    - +

    See it in action:

    - + If all goes well, the above program yields:

    - + > result = create.select( Actor.ACTOR.FIRST_NAME, Actor.ACTOR.LAST_NAME ) @@ -13433,21 +13433,21 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    Please take note of the fact that the sql2jooq library is Open Source, but it depends on the commercial gsp.jar parser, whose trial licensing terms can be seen here:

    - +

    https://github.com/sqlparser/sql2jooq/blob/master/sql2jooq/LICENSE-GSQLPARSER.txt

    - +

    For more information about the General SQL Parser, please refer to the product blog.

    - +

    Please report any issues, ideas, wishes to the jOOQ user group or the sql2jooq GitHub project.

    - +
    jOOQ Console @@ -13494,7 +13494,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • Sybase Adaptive Server Enterprise 15.5
  • Sybase SQL Anywhere 12
  • - +

    For an up-to-date list of currently supported RDBMS, please refer to http://www.jooq.org/legal/licensing/#databases.

    @@ -13515,7 +13515,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME, This chapter should document the most important notes about SQL, JDBC and jOOQ data types.

    - +
    BLOBs and CLOBs @@ -13525,7 +13525,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    Unsigned integer types @@ -13549,7 +13549,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
    - +
    INTERVAL data types @@ -13560,11 +13560,11 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • YEAR TO MONTH: This interval type models a number of months and years
  • DAY TO SECOND: This interval type models a number of days, hours, minutes, seconds and milliseconds
  • - +

    Both interval types ship with a variant of subtypes, such as DAY TO HOUR, HOUR TO SECOND, etc. jOOQ models these types as Java objects extending : (where Number.intValue() corresponds to the absolute number of months) and (where Number.intValue() corresponds to the absolute number of milliseconds)

    - +

    Interval arithmetic

    In addition to the documented previously, interval arithmetic is also supported by jOOQ. Essentially, the following operations are supported: @@ -13579,7 +13579,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    XML data types @@ -13588,7 +13588,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    Geospacial data types @@ -13598,7 +13598,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    CURSOR data types @@ -13607,22 +13607,22 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    > cursor;]]> - +

    In fact, such a cursor will be fetched immediately by jOOQ and wrapped in an object.

    - +
    ARRAY and TABLE data types

    The SQL standard specifies ARRAY data types, that can be mapped to Java arrays as such:

    - + intArray;]]> - +

    The above array type is supported by these SQL dialects:

    @@ -13631,7 +13631,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • HSQLDB
  • Postgres
  • - +

    Oracle typed arrays

    Oracle has strongly-typed arrays and table types (as opposed to the previously seen anonymously typed arrays). These arrays are wrapped by types. @@ -13647,12 +13647,12 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    jOOQ takes SQL as an external domain-specific language and maps it onto Java, creating an internal domain-specific language. Internal DSLs cannot 100% implement their external language counter parts, as they have to adhere to the syntax rules of their host or target language (i.e. Java). This section explains the various problems and workarounds encountered and implemented in jOOQ.

    - +

    SQL allows for "keywordless" syntax

    SQL syntax does not always need keywords to form expressions. The clause takes various argument assignments:

    - + UPDATE t SET a = 1, b = 2 update(t).set(a, 1).set(b, 2) @@ -13670,12 +13670,12 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    In this case, ROW is an actual (optional) SQL keyword, implemented by at least PostgreSQL.

    - +

    SQL contains "composed" keywords

    As most languages, SQL does not attribute any meaning to whitespace. However, whitespace is important when forming "composed" keywords, i.e. SQL clauses composed of several keywords. jOOQ follows standard Java method naming conventions to map SQL keywords (case-insensitive) to Java methods (case-sensitive, camel-cased). Some examples:

    - + GROUP BY ORDER BY @@ -13688,7 +13688,7 @@ whenMatchedThenUpdate()

    Future versions of jOOQ may use all-uppercased method names in addition to the camel-cased ones (to prevent collisions with Java keywords):

    - + GROUP BY ORDER BY @@ -13719,7 +13719,7 @@ WHEN_MATCHED_THEN_UPDATE()

    The above example omits THEN and END keywords in Java. Future versions of jOOQ may comprise a more complete DSL, including such keywords again though, to provide a more 1:1 match for the SQL language.

    - +

    SQL contains "superfluous" syntactic elements

    Some SQL constructs are hard to map to Java, but they are also not really necessary. SQL often expects syntactic parentheses where they wouldn't really be needed, or where they feel slightly inconsistent with the rest of the SQL language. @@ -13756,7 +13756,7 @@ WHEN_MATCHED_THEN_UPDATE()

    jOOQ replaces those keywords by "synonyms":

    - + CASE .. ELSE PIVOT .. FOR .. IN .. @@ -13784,7 +13784,7 @@ pivot(..).on(..).in(..)

    Most SQL operators have to be mapped to descriptive method names in Java, as Java does not allow operator overloading:

    - + , != @@ -13813,7 +13813,7 @@ set(a, b)

    This is less of a syntactic SQL feature than a semantic one. In SQL, objects can be referenced before (i.e. "lexicographically before") they are declared. This is particularly true for

    - + @@ -13824,7 +13824,7 @@ select(t.a).from(t)]]>

    A more sophisticated example are common table expressions (CTE), which are currently not supported by jOOQ:

    - + WITH t(a, b) AS ( SELECT 1, 2 FROM DUAL ) @@ -13836,7 +13836,7 @@ FROM t

    - +
    jOOQ's BNF pseudo-notation @@ -13845,7 +13845,7 @@ FROM t

    - +
    Quality Assurance @@ -13857,16 +13857,16 @@ FROM t
  • To add lots of type-safety to your inline SQL
  • To increase productivity when writing inline SQL using your favourite IDE's autocompletion capabilities
  • - +

    With jOOQ being in the core of your application, you want to be sure that you can trust jOOQ. That is why jOOQ is heavily unit and integration tested with a strong focus on integration tests:

    - +

    Unit tests

    Unit tests are performed against dummy JDBC interfaces using http://jmock.org/. These tests verify that various implementations render correct SQL and bind variables correctly.

    - +

    Integration tests

    This is the most important part of the jOOQ test suites. Some 1500 queries are currently run against a standard integration test database. Both the test database and the queries are translated into every one of the 14 supported SQL dialects to ensure that regressions are unlikely to be introduced into the code base. @@ -13877,17 +13877,17 @@ FROM t

    jOOQ integration tests run the weirdest and most unrealistic queries. As a side-effect of these extensive integration test suites, many corner-case bugs for JDBC drivers and/or open source databases have been discovered, feature requests submitted through jOOQ and reported mainly to CUBRID, Derby, H2, HSQLDB.

    - +

    Code generation tests

    For every one of the 14 supported integration test databases, source code is generated and the tiniest differences in generated source code can be discovered. In case of compilation errors in generated source code, new test tables/views/columns are added to avoid regressions in this field.

    - +

    API Usability tests and proofs of concept

    jOOQ is used in jOOQ-meta as a proof of concept. This includes complex queries such as the following Postgres query

    - + These rather complex queries show that the jOOQ API is fit for advanced SQL use-cases, compared to the rather simple, often unrealistic queries in the integration test suite.

    - +

    Clean API and implementation. Code is kept DRY

    As a general rule of thumb throughout the jOOQ code, everything is kept DRY. Some examples: @@ -13953,19 +13953,19 @@ for (Record record : create.select(

    - +
    Migrating to jOOQ 3.0

    This section is for all users of jOOQ 2.x who wish to upgrade to the next major release. In the next sub-sections, the most important changes are explained. Some code hints are also added to help you fix compilation errors.

    - +

    Type-safe row value expressions

    Support for has been added in jOOQ 2.6. In jOOQ 3.0, many API parts were thoroughly (but often incompatibly) changed, in order to provide you with even more type-safety.

    - +

    Here are some affected API parts:

    @@ -13975,11 +13975,11 @@ for (Record record : create.select(
  • IN predicates and comparison predicates taking subselects changed incompatibly
  • INSERT and MERGE statements now take typesafe VALUES() clauses
  • - +

    Some hints related to row value expressions:

    - + record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result> result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch(); @@ -13987,31 +13987,31 @@ Result> result = create.select(BOOK.TITLE, BOOK.ID).fro // But Record2 extends Record. You don't have to use the additional typesafety: Record record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch();]]> - +

    SelectQuery and SelectXXXStep are now generic

    In order to support type-safe row value expressions and type-safe Record[N] types, SelectQuery is now generic: SelectQuery<R>

    - +

    SimpleSelectQuery and SimpleSelectXXXStep API were removed

    The duplication of the SELECT API is no longer useful, now that SelectQuery and SelectXXXStep are generic.

    - +

    Factory was split into DSL (query building) and DSLContext (query execution)

    The pre-existing Factory class has been split into two parts:

    - +
    1. 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
    2. 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 renamed to DSLContext. An example:

    - + - +

    Quantified comparison predicates

    Field.equalAny(...) and similar methods have been removed in favour of Field.equal(any(...)). This greatly simplified the Field API. An example:

    - + > subselect = any(select(BOOK.ID).from(BOOK)); Condition condition = BOOK.ID.equal(subselect);]]> - +

    FieldProvider

    The FieldProvider marker interface was removed. Its methods still exist on FieldProvider subtypes. Note, they have changed names from getField() to field() and from getIndex() to indexOf()

    - +

    GroupField

    GroupField has been introduced as a DSL marker interface to denote fields that can be passed to GROUP BY clauses. This includes all org.jooq.Field types. However, fields obtained from ROLLUP(), CUBE(), and GROUPING SETS() functions no longer implement Field. Instead, they only implement GroupField. An example:

    - + field1a = Factory.rollup(...); // OK Field field2a = Factory.one(); // OK @@ -14057,19 +14057,19 @@ GroupField field1b = DSL.rollup(...); // OK Field field1c = DSL.rollup(...); // Compilation error GroupField field2b = DSL.one(); // OK Field field2c = DSL.one(); // OK]]> - +

    NULL predicate

    Beware! Previously, Field.equal(null) was translated internally to an IS NULL predicate. This is no longer the case. Binding Java "null" to a comparison predicate will result in a regular comparison predicate (which never returns true). This was changed for several reasons:

    - +
    • To most users, this was a surprising "feature".
    • Other predicates didn't behave in such a way, e.g. the IN predicate, the BETWEEN predicate, or the LIKE predicate.
    • Variable binding behaved unpredictably, as IS NULL predicates don't bind any variables.
    • The generated SQL depended on the possible combinations of bind values, which creates unnecessary hard-parses every time a new unique SQL statement is rendered.
    - +

    Here is an example how to check if a field has a given value, without applying SQL's ternary NULL logic:

    @@ -14082,7 +14082,7 @@ Condition condition1 = BOOK.TITLE.equal(possiblyNull); // jOOQ 3.0 Condition condition2 = BOOK.TITLE.equal(possiblyNull).or(BOOK.TITLE.isNull().and(val(possiblyNull).isNull())); Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    Configuration

    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 @@ -14096,7 +14096,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> In order to resolve confusion that used to arise because of different lifecycle durations, these types are now no longer formally connected through inheritance.

    - +

    ConnectionProvider

    In order to allow for simpler connection / data source management, jOOQ externalised connection handling in a new ConnectionProvider type. The previous two connection modes are maintained backwards-compatibly (JDBC standalone connection mode, pooled DataSource mode). Other connection modes can be injected using: @@ -14106,24 +14106,24 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    These are some side-effects of the above change

    - +
    • 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. This resolves many class loader issues that were encountered before. It also helps listener implementations control their lifecycles themselves.

    - +

    Data type API

    The data type API has been changed drastically in order to enable some new DataType-related features. These changes include: @@ -14133,16 +14133,16 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]>[SQLDialect]DataType and SQLDataType no longer implement DataType. They're mere constant containers

  • Various minor API changes have been done.
  • - +

    Object renames

    These objects have been moved / renamed:

    - +
    • jOOU: a library used to represent unsigned integer types was moved from org.jooq.util.unsigned to org.jooq.util.types (which already contained INTERVAL data types)
    - +

    Feature removals

    Here are some minor features that have been removed in jOOQ 3.0 @@ -14236,7 +14236,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> --> diff --git a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.5.xml b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.5.xml index 6f50dc047a..efafe62351 100644 --- a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.5.xml +++ b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.5.xml @@ -126,7 +126,7 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ's reason for being - compared to SQL / JDBC

    So why not just use SQL? @@ -149,14 +149,14 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ is different

    SQL was never meant to be abstracted. To be confined in the narrow boundaries of heavy mappers, hiding the beauty and simplicity of relational data. SQL was never meant to be object-oriented. SQL was never meant to be anything other than... SQL!

    - + - +
    Getting started with jOOQ @@ -344,12 +344,12 @@ limitations under the License.

    This section helps you correctly interpret this manual in the context of jOOQ.

    - +

    Code blocks

    The following are code blocks:

    - + @@ -365,7 +365,7 @@ org.jooq.property=value]]>

    These are useful to provide examples in code. Often, with jOOQ, it is even more useful to compare SQL code with its corresponding Java/jOOQ code. When this is done, the blocks are aligned side-by-side, with SQL usually being on the left, and an equivalent jOOQ DSL query in Java usually being on the right:

    - + @@ -377,17 +377,17 @@ create.selectOne().fetch()]]>

    The contents of code blocks follow conventions, too. If nothing else is mentioned next to any given code block, then the following can be assumed:

    - - + + - +

    Your naming may differ, of course. For instance, you could name the "create" instance "db", instead.

    - +

    Execution

    - +

    When you're coding PL/SQL, T-SQL or some other procedural SQL language, SQL statements are always executed immediately at the semi-colon. This is not the case in jOOQ, because as an internal DSL, jOOQ can never be sure that your statement is complete until you call fetch() or execute(). The manual tries to apply fetch() and execute() as thoroughly as possible. If not, it is implied:

    @@ -427,7 +427,7 @@ create.update(T).set(T.V, 1).execute();]]>

    jOOQ allows to override runtime behaviour using . If nothing is specified, the default runtime settings are assumed.

    - +

    Sample database

    jOOQ query examples run against the sample database. See the manual's section about to learn more about the sample database. @@ -462,7 +462,7 @@ CREATE TABLE book ( title VARCHAR2(400) NOT NULL, published_in NUMBER(7) NOT NULL, language_id NUMBER(7) NOT NULL, - + CONSTRAINT fk_book_author FOREIGN KEY (author_id) REFERENCES author(id), CONSTRAINT fk_book_language FOREIGN KEY (language_id) REFERENCES language(id) ); @@ -475,7 +475,7 @@ CREATE TABLE book_to_book_store ( name VARCHAR2(400) NOT NULL, book_id INTEGER NOT NULL, stock INTEGER, - + PRIMARY KEY(name, book_id), CONSTRAINT fk_b2bs_book_store FOREIGN KEY (name) REFERENCES book_store (name) ON DELETE CASCADE, CONSTRAINT fk_b2bs_book FOREIGN KEY (book_id) REFERENCES book (id) ON DELETE CASCADE @@ -486,7 +486,7 @@ CREATE TABLE book_to_book_store (

    In addition to the above, you may assume the following sample data:

    - + Effectively, jOOQ was originally designed to replace any other database abstraction framework short of the ones handling connection pooling (and more sophisticated )

    - +

    Use jOOQ the way you prefer

    ... but open source is community-driven. And the community has shown various ways of using jOOQ that diverge from its original intent. Some use cases encountered are: @@ -545,7 +545,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]>Using jOOQ for SQL building and Spring Data for SQL execution

  • Using jOOQ without the to build the basis of a framework for dynamic SQL execution.
  • - +

    The following sections explain about various use cases for using jOOQ in your application.

    @@ -558,7 +558,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]> This is the most simple of all use cases, allowing for construction of valid SQL for any database. In this use case, you will not use and probably not even . Instead, you'll use to wrap strings, literals and other user-defined objects into an object-oriented, type-safe AST modelling your SQL statements. An example is given here:

    - + - +

    The SQL string built with the jOOQ query DSL can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools (note that since jOOQ uses PreparedStatement by default, this will generate a bind variable for "1948". ).

    @@ -595,7 +595,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID)) .where(BOOK.PUBLISHED_IN.equal(1948)) .getSQL();]]> - +

    The SQL string that you can generate as such can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools.

    @@ -615,7 +615,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    Instead of any tool mentioned in the previous chapters, you can also use jOOQ directly to execute your jOOQ-generated SQL statements. This will add a lot of convenience on top of the previously discussed API for typesafe SQL construction, when you can re-use the information from generated classes to fetch records and custom data types. An example is given here:

    - + > result = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) @@ -669,10 +669,10 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { // Skip previously distinguished authors if ((int) author.getDistinguished() == 1) continue; - + // Check if the author has written more than 5 books if (author.fetchChildren(Keys.FK_BOOK_AUTHOR).size() > 5) { - + // Mark the author as a "distinguished" author author.setDistinguished(1); author.store(); @@ -689,7 +689,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {
    - +
    jOOQ for PROs @@ -727,7 +727,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { This manual section is intended for new users, to help them get a running application with jOOQ, quickly.

    - +
    Step 1: Preparation @@ -736,7 +736,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { If you haven't already downloaded it, download jOOQ:
    http://www.jooq.org/download

    - +

    Alternatively, you can create a Maven dependency to download jOOQ artefacts:

    @@ -759,7 +759,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    Note that only the jOOQ Open Source Edition is available from Maven Central. If you're using the jOOQ Professional Edition or the jOOQ Enterprise Edition, you will have to manually install jOOQ in your local Nexus, or in your local Maven cache. For more information, please refer to the licensing pages.

    - +

    Please refer to the manual's section about to learn how to use jOOQ's code generator with Maven.

    @@ -774,14 +774,14 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    - +
    Step 2: Your database

    We're going to create a database called "library" and a corresponding "author" table. Connect to MySQL via your command line client and type the following:

    - + CREATE DATABASE `library`; USE `library`; @@ -795,7 +795,7 @@ CREATE TABLE `author` (
    - +
    Step 3: Code generation @@ -807,7 +807,7 @@ CREATE TABLE `author` (

    The easiest way to generate a schema is to copy the jOOQ jar files (there should be 3) and the MySQL Connector jar file to a temporary directory. Then, create a library.xml that looks like this:

    - + @@ -861,7 +861,7 @@ CREATE TABLE `author` (

    generator.target.directory - the directory to output to.

    - +

    Once you have the JAR files and library.xml in your temp directory, type this on a Windows machine:

    @@ -881,7 +881,7 @@ CREATE TABLE `author` (

    Note: jOOQ will try loading the library.xml from your classpath. This is also why there is a trailing period (.) on the classpath. If the file cannot be found on the classpath, jOOQ will look on the file system from the current working directory.

    - +

    Replace the filenames with your actual filenames. In this example, jOOQ {jooq-version} is being used. If everything has worked, you should see this in your console output:

    @@ -943,17 +943,17 @@ INFO: Packages fetched : 0 (0 included, 0 excluded) Nov 1, 2011 7:25:08 PM org.jooq.impl.JooqLogger info INFO: GENERATION FINISHED! : Total: 791.688ms, +9.143ms - +
    - +
    Step 4: Connect to your database

    Let's just write a vanilla main class in the project containing the generated classes:

    - +
    - +
    Step 5: Querying

    Let's add a simple query constructed with jOOQ's query DSL:

    - + result = create.select().from(AUTHOR).fetch();]]> @@ -1003,7 +1003,7 @@ Result result = create.select().from(AUTHOR).fetch();]]>

    - +
    Step 6: Iterating @@ -1022,7 +1022,7 @@ Result result = create.select().from(AUTHOR).fetch();]]>

    The full program should now look like this:

    - +
    - +
    Step 7: Explore! @@ -1118,7 +1118,7 @@ public class Main {
  • Another example using Spring and Guice for transaction management can be downloaded from GitHub.
  • Another, excellent tutorial by Petri Kainulainen can be found here.
  • - +

    Add the required Maven dependencies

    For this example, we'll create the following Maven dependencies @@ -1197,7 +1197,7 @@ public class Main {

    The above dependencies are configured together using a Spring Beans configuration:

    - + - + - + @@ -1255,7 +1255,7 @@ public class Main { - + ]]> @@ -1306,7 +1306,7 @@ public class QueryTest {

    The following example shows how you can use Spring's TransactionManager to explicitly handle transactions:

    - +
    - +
    Using jOOQ with Flyway

    Flyway - Database Migrations Made EasyWhen performing database migrations, we at Data Geekery recommend using jOOQ with Flyway - Database Migrations Made Easy. In this chapter, we're going to look into a simple way to get started with the two frameworks.

    - +

    Philosophy

    - +

    There are a variety of ways how jOOQ and Flyway could interact with each other in various development setups. In this tutorial we're going to show just one variant of such framework team play - a variant that we find particularly compelling for most use cases.

    - +

    The general philosophy behind the following approach can be summarised as this:

    - +
    • 1. Database increment
    • 2. Database migration
    • 3. Code re-generation
    • 4. Development
    - +

    The four steps above can be repeated time and again, every time you need to modify something in your database. More concretely, let's consider:

    - +
    • 1. Database increment - You need a new column in your database, so you write the necessary DDL in a Flyway script
    • 2. Database migration - This Flyway script is now part of your deliverable, which you can share with all developers who can migrate their databases with it, the next time they check out your change
    • @@ -1452,15 +1452,15 @@ public class TransactionTest { ]]>

      0. Maven Project Configuration - Dependencies

      - +

      While jOOQ and Flyway could be used in standalone migration scripts, in this tutorial, we'll be using Maven for the standard project setup. You will also find the source code of this tutorial on GitHub at https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-flyway-example, and the full pom.xml file here.

      - +

      These are the dependencies that we're using in our Maven configuration:

      - + org.jooq @@ -1793,14 +1793,14 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre;

    - +
    Using jOOQ with JAX-RS

    In some use-cases, having a lean, single-tier server-side architecture is desirable. Typically, such architectures expose a RESTful API implementing client code and the UI using something like AngularJS.

    - +

    In Java, the standard API for RESTful applications is JAX-RS, which is part of JEE 7, along with a standard JSON implementation. But you can use JAX-RS also outside of a JEE container. The following example shows how to set up a simple license server using these technologies:

    @@ -1813,9 +1813,9 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre;

    For the example, we'll use a PostgreSQL database.

    - +

    Creating the license server database

    - +

    We'll keep the example simple and use a LICENSE table to store all license keys and associated information, whereas a LOG_VERIFY table is used to log access to the license server. Here's the DDL:

    @@ -1827,7 +1827,7 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre; LICENSEE TEXT NOT NULL, -- The e-mail address of the licensee LICENSE TEXT NOT NULL, -- The license key VERSION VARCHAR(50) NOT NULL DEFAULT '.*', -- The licensed version(s), a regular expression - + CONSTRAINT PK_LICENSE PRIMARY KEY (ID), CONSTRAINT UK_LICENSE UNIQUE (LICENSE) ); @@ -1840,7 +1840,7 @@ CREATE TABLE LICENSE_SERVER.LOG_VERIFY ( REQUEST_IP VARCHAR(50) NOT NULL, -- The request IP verifying the license VERSION VARCHAR(50) NOT NULL, -- The version that is being verified MATCH BOOLEAN NOT NULL, -- Whether the verification was successful - + CONSTRAINT PK_LOG_VERIFY PRIMARY KEY (ID) );]]> @@ -1862,13 +1862,13 @@ $$ LANGUAGE PLPGSQL;

    The actual algorithm might be using a secret salt to hash the function arguments. For the sake of a tutorial, a constant string will suffice.

    - +

    Setting up the project

    - +

    We're going to be setting up the

    - + 9966 - + org.jooq jooq-codegen-maven @@ -1934,7 +1934,7 @@ $$ LANGUAGE PLPGSQL; servlet-api 2.5 - + org.jooq jooq @@ -1956,13 +1956,13 @@ $$ LANGUAGE PLPGSQL;

    With the above setup, we're now pretty ready to start developing our license service as a JAX-RS service.

    - +

    The license service class

    - +

    Once we've run the , we can write the following service class:

    - + /license/verify checks if a given licensee has access to version using a license. * @@ -2022,7 +2022,7 @@ public class LicenseService { @Override public String run(DSLContext ctx) { String v = (version == null || version.equals("")) ? "" : version; - + // Use the jOOQ query DSL API to generate a log entry return ctx.insertInto(LOG_VERIFY) @@ -2043,10 +2043,10 @@ public class LicenseService { } }); } - + // [...] }]]> - +

    The INSERT INTO LOG_VERIFY query is actually rather interesting. In plain SQL, it would look like this:

    @@ -2071,7 +2071,7 @@ RETURNING MATCH;]]> */ private String run(CtxRunnable runnable) { Connection c = null; - + try { Class.forName("org.postgresql.Driver"); c = getConnection("jdbc:postgresql:postgres", "postgres", System.getProperty("pw", "test")); @@ -2079,7 +2079,7 @@ RETURNING MATCH;]]> .set(new DefaultConnectionProvider(c)) .set(SQLDialect.POSTGRES) .set(new Settings().withExecuteLogging(false))); - + return runnable.run(ctx); } catch (Exception e) { @@ -2091,13 +2091,13 @@ RETURNING MATCH;]]> JDBCUtils.safeClose(c); } } - + private interface CtxRunnable { String run(DSLContext ctx); }]]>

    Configuring Spring and Jetty

    - +

    All we need now is to configure Spring...

    @@ -2155,7 +2155,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/sch

    Using the license server

    - +

    You can now use the license server at the following URLs

    @@ -2172,7 +2172,7 @@ http://localhost:8088/jooq-jax-rs-example/license/verify?mail=test@example.com&l

    Let's verify what happened, in the database:

    - + - +

    Downloading the complete example

    - +

    The complete example can be downloaded for free and under the terms of the Apache Software License 2.0 from here:
    https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-jax-rs-example @@ -2202,21 +2202,21 @@ select * from license_server.log_verify

    - +
    jOOQ and Java 8

    Java 8 has introduced a great set of enhancements, among which lambda expressions and the new Streams API. These new constructs align very well with jOOQ's fluent API as can be seen in the following examples:

    - +

    jOOQ and lambda expressions

    jOOQ's API is fully Java-8-ready, which basically means that it is a SAM (Single Abstract Method) type, which can be instanciated using a lambda expression. Consider this example:

    - + - +

    The above example shows how jOOQ's method can receive a lambda expression that implements to map from jOOQ to your custom types.

    - +

    jOOQ and the Streams API

    @@ -2277,7 +2277,7 @@ select * from license_server.log_verify // Just emit a CREATE TABLE statement System.out.println( "CREATE TABLE " + table + " ("); - + // Map each "Column" type into a String // containing the column specification, // and join them using comma and @@ -2288,15 +2288,15 @@ select * from license_server.log_verify " " + col.type) .collect(Collectors.joining(",\n")) ); - + System.out.println(");"); } );]]> - +

    The above example is explained more in depth in this blog post: http://blog.jooq.org/2014/04/11/java-8-friday-no-more-need-for-orms/. For more information about Java 8, consider these resources:

    - +
    - +
    jOOQ and Nashorn

    With Java 8 and the new built-in JavaScript engine Nashorn, a whole new ecosystem of software can finally make easy use of jOOQ in server-side JavaScript. A very simple example can be seen here:

    - +

    - More details about how to use jOOQ, JDBC, and SQL with Nashorn can be seen here. + More details about how to use jOOQ, JDBC, and SQL with Nashorn can be seen here.

    - +
    jOOQ and Scala @@ -2529,7 +2529,7 @@ print(
  • Type inference using "var" and "val" keywords
  • Lambda expressions and for-comprehension syntax for record iteration and data type conversion
  • - +

    But jOOQ also leverages other useful Scala features, such as

    @@ -2537,15 +2537,15 @@ print(
  • implicit defs for operator overloading
  • Scala Macros (soon to come)
  • - +

    All of the above heavily improve jOOQ's querying DSL API experience for Scala developers.

    - +

    A short example jOOQ application in Scala might look like this:

    - +
    - - + +
    jOOQ and Groovy @@ -2611,7 +2611,7 @@ object Test { //

    A short example jOOQ application in Groovy might look like this:

    - +
    - +
    jOOQ and NoSQL @@ -2664,7 +2664,7 @@ DSL.using(sql.connection)

    - +
    Dependencies @@ -2682,7 +2682,7 @@ DSL.using(sql.connection)
    - +
    Build your own @@ -2711,7 +2711,7 @@ DSL.using(sql.connection)
    - +
    jOOQ and backwards-compatibility @@ -2723,7 +2723,7 @@ DSL.using(sql.connection)
  • If a minor release includes backwards-compatible, API-relevant new features, [Y] is incremented by one and [Z] is reset to zero.
  • If a major release includes backwards-incompatible, API-relevant new features, [X] is incremented by one and [Y], [Z] are reset to zero.
  • - +

    jOOQ's understanding of backwards-compatibility

    Backwards-compatibility is important to jOOQ. You've chosen jOOQ as a strategic SQL engine and you don't want your SQL to break. That is why there is at most one major release per year, which changes only those parts of jOOQ's API and functionality, which were agreed upon on the user group. During the year, only minor releases are shipped, adding new features in a backwards-compatible way @@ -2736,15 +2736,15 @@ DSL.using(sql.connection)

  • Overloading methods for convenience
  • Changing the type hierarchy of interfaces
  • - +

    It becomes obvious that it would be impossible to add new language elements (e.g. new , new ) to the API without breaking any client code that actually implements those interfaces. Hence, the following rule should be observed:

    - +

    jOOQ's DSL interfaces should not be implemented by client code! Extend only those extension points that are explicitly documented as "extendable" (e.g. )

    - +

    jOOQ-codegen and jOOQ-meta

    While a reasonable amount of care is spent to maintain these two modules under the rules of semantic versioning, it may well be that minor releases introduce backwards-incompatible changes. This will be announced in the respective release notes and should be the exception. @@ -2772,7 +2772,7 @@ DSL.using(sql.connection) - +

    The query DSL type @@ -2803,7 +2803,7 @@ DSL.using(sql.connection) // ... which is in fact the same as: DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    DSL subclasses @@ -2822,7 +2822,7 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME));
    - + @@ -2831,14 +2831,14 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    The DSLContext class

    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.

    - +

    Fluent creation of a DSLContext object

    The DSLContext object can be created fluently from the : @@ -2853,7 +2853,7 @@ DSLContext create = DSL.using(connection, dialect);]]>

    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

    A Configuration can be supplied with these objects: @@ -2872,7 +2872,7 @@ DSLContext create = DSL.using(connection, dialect);]]> - +

    Wrapping a Configuration object, a DSLContext can construct , for later . An example is given here:

    @@ -2914,7 +2914,7 @@ DSL.using(connection, dialect) CONNECT BY clause to the query */ -@Support({ SQLDialect.CUBRID, SQLDialect.}) +@Support({ SQLDialect.CUBRID, SQLDialect.ORACLE }) SelectConnectByConditionStep connectBy(Condition condition);]]>

    @@ -2936,7 +2936,7 @@ SelectSelectStep select(Field... fields);]]>

    Nevertheless, the IS DISTINCT FROM predicate is supported by jOOQ in all dialects, as its semantics can be expressed with an equivalent . For more details, see the manual's section about the .

    - +

    jOOQ and the Oracle SQL dialect

    Oracle SQL is much more expressive than many other SQL dialects. It features many unique keywords, clauses and functions that are out of scope for the SQL standard. Some examples for this are @@ -2960,13 +2960,13 @@ SelectSelectStep select(Field... fields);]]>

    In jOOQ 3.1, the notion of a SQLDialect.family() was introduced, in order to group several similar into a common family. An example for this is SQL Server, which is supported by jOOQ in various versions:

    - +
    • : The "version-less" SQL Server version. This always maps to the latest supported version of SQL Server
    • : The SQL Server version 2012
    • : The SQL Server version 2008
    - +

    In the above list, SQLSERVER is both a dialect and a family of three dialects. This distinction is used internally by jOOQ to distinguish whether to use the clause (SQL Server 2012), or whether to emulate it using ROW_NUMBER() OVER() (SQL Server 2008).

    @@ -2983,7 +2983,7 @@ SelectSelectStep select(Field... fields);]]>

    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.

    - +

    Interact with JDBC DataSources

    If you're in a J2EE or Spring context, however, you may wish to use a instead. Connections obtained from such a DataSource will be closed after query execution by jOOQ. The semantics of such a close operation should be the returning of the connection into a connection pool, not the actual closing of the underlying connection. Typically, this makes sense in an environment using distributed JTA transactions. An example of using DataSources with jOOQ can be seen in the tutorial section about . @@ -2991,17 +2991,17 @@ SelectSelectStep select(Field... fields);]]>

    Note, in this case, jOOQ will internally use a , which you can reference directly if you prefer that.

    - +

    Inject custom behaviour

    If your specific environment works differently from any of the above approaches, you can inject your own custom implementation of a ConnectionProvider into jOOQ. This is the API contract you have to fulfil:

    - + @@ -3011,19 +3011,19 @@ 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...

    - +
    - +

    Here is an example of how to use the custom data API. Let's assume that you have written an , that prevents INSERT statements, when a given flag is set to true:

    @@ -3033,10 +3033,10 @@ public class NoInsertListener extends DefaultExecuteListener { @Override public void start(ExecuteContext ctx) { - + // This listener is active only, when your custom flag is set to true 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) { throw new DataAccessException("No INSERT statements allowed"); @@ -3047,11 +3047,11 @@ public class NoInsertListener extends DefaultExecuteListener {

    See the manual's section about to learn more about how to implement an ExecuteListener.

    - +

    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:

    - + ExecuteListeners are a useful tool to...

    - +
    • implement custom logging
    • apply triggers written in Java
    • collect query execution statistics
    - +

    ExecuteListeners are hooked into your by returning them from an :

    @@ -3109,7 +3109,7 @@ configuration.set( new DefaultExecuteListenerProvider(new PerformanceLoggingListener()), new DefaultExecuteListenerProvider(new NoInsertListener()) );]]>
    - +

    See the manual's section about to see examples of such listener implementations.

    @@ -3153,22 +3153,22 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - +

    All Settings

    - +

    This section of the manual explains all the available Settings flags as available from the XSD specification.

    - + false - + ... @@ -3179,17 +3179,17 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - UPPER_CASED : UPPER - lower_cased : LOWER - CasedAsReportedByTheDatabase : AS_IS - + Defaults to "QUOTED" --> LOWER UPPER - + false @@ -3197,54 +3197,54 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - question marks : INDEXED - named parameters : NAMED - inlined values : INLINED - + Defaults to "INDEXED". - + This value is overridden by statementType == STATIC_STATEMENT, in case of which, this defaults to INLINED --> INDEXED - + PREPARED_STATEMENT - + true false true false ]]> - +

    More details

    - +

    Please refer to the jOOQ runtime configuration XSD for more details:
    http://www.jooq.org/xsd/jooq-runtime-{runtime-xsd-version}.xsd

    - +
    Runtime schema and table mapping @@ -3252,7 +3252,7 @@ DSLContext create = DSL.using(connection, dialect, settings);]]>

    You may wish to design your database in a way that you have several instances of your schema. This is useful when you want to cleanly separate data belonging to several customers / organisation units / branches / users and put each of those entities' data in a separate database or schema.

    - +

    In our AUTHOR example this would mean that you provide a book reference database to several companies, such as My Book World and Books R Us. In that case, you'll probably have a schema setup like this:

    @@ -3282,7 +3282,7 @@ create.selectFrom(AUTHOR).fetch();

    The query executed with a Configuration equipped with the above mapping will in fact produce this SQL statement:

    - + SELECT * FROM MY_BOOK_WORLD.AUTHOR

    Even if AUTHOR was generated from DEV. @@ -3357,7 +3357,7 @@ create.selectFrom(AUTHOR).fetch();

    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

    @@ -3391,7 +3391,7 @@ create.selectFrom(AUTHOR).fetch();

    Here is an example to illustrate what that means:

    - + 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) @@ -3463,7 +3463,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); @@ -3490,7 +3490,7 @@ query.addJoin(BOOK, BOOK.AUTHOR_ID.equal(AUTHOR.ID));]]>

    Note, that for historic reasons, the DSL API mixes mutable and immutable behaviour with respect to the internal representation of the being constructed. While creating , (such as functions) assumes immutable behaviour, creating does not. In other words, the following can be said:

    - + select2 = create.selectOne().fetch();]]>

    jOOQ does not explicitly support the asterisk operator in projections. However, you can omit the projection as in these examples:

    - +

    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:

    - + select(Collection> fields); public static SelectSelectStep select(Field... fields); @@ -3772,14 +3772,14 @@ public static SelectSelectStep> select(Field SelectSelectStep> select(Field field1, Field field2); public static SelectSelectStep> select(Field field1, Field field2, Field field3); // [...]]]> - +

    Since the generic R type is bound to some , the associated T type information can be used in various other contexts, e.g. the . Such a SELECT statement can be assigned typesafely:

    > s1 = create.select(BOOK.ID, BOOK.TITLE); Select> s2 = create.select(BOOK.ID, trim(BOOK.TITLE));]]> - +

    For more information about typesafe record types with degree up to {max-row-degree}, see the manual's section about .

    @@ -3805,7 +3805,7 @@ create.selectOne().from(BOOK.as("b"), AUTHOR.as("a")).fetch();]]>

    Read more about aliasing in the manual's section about .

    - +

    More advanced table expressions

    Apart from simple tables, you can pass any arbitrary to the jOOQ FROM clause. This may include in Oracle: @@ -3861,11 +3861,11 @@ DSL.using(SQLDialect.POSTGRES).selectOne().fetch();]]>

  • NATURAL LEFT [ OUTER ] JOIN
  • NATURAL RIGHT [ OUTER ] JOIN
  • - +

    Besides, jOOQ also supports

    - +
    • CROSS APPLY (T-SQL and Oracle 12c specific)
    • OUTER APPLY (T-SQL and Oracle 12c specific)
    • @@ -3998,7 +3998,7 @@ ON BOOK.AUTHOR_ID = AUTHOR.ID

      T-SQL has long known what the SQL standard calls lateral derived tables, lateral joins using the APPLY keyword. To every row resulting from the table expression on the left, we apply the table expression on the right. This is extremely useful for table-valued functions, which are also supported by jOOQ. Some examples:

      - + - +

      The above example shows standard usage of the LATERAL keyword to connect a derived table to the previous table in the . A similar statement can be written in T-SQL:

      - + - +

      LATERAL JOIN or CROSS APPLY are particularly useful together with , which are also supported by jOOQ.

      @@ -4150,12 +4150,12 @@ ORDER BY 1

      Note that this syntax is also supported in the CUBRID database and might be emulated in other dialects supporting common table expressions in the future.

      - +

      ORDER SIBLINGS

      The Oracle database allows for specifying a SIBLINGS keyword in the . Instead of ordering the overall result, this will only order siblings among each other, keeping the hierarchy intact. An example is given here:

      - + - +
    @@ -4199,7 +4199,7 @@ GROUP BY AUTHOR_ID

    Note, as defined in the SQL standard, when grouping, you may no longer project any columns that are not a formal part of the GROUP BY clause, or .

    - +

    MySQL's deviation from the SQL standard

    MySQL has a peculiar way of not adhering to this standard behaviour. This is documented in the MySQL manual. In short, with MySQL, you can also project any other field that is not part of the GROUP BY clause. The projected values will just be arbitrary values from within the group. You cannot rely on any ordering. For example: @@ -4234,7 +4234,7 @@ GROUP BY () .groupBy() .fetch();]]> - +

    ROLLUP(), CUBE() and GROUPING SETS()

    Some databases support the SQL standard grouping functions and some extensions thereof. See the manual's section about for more details. @@ -4255,7 +4255,7 @@ FROM BOOK GROUP BY AUTHOR_ID HAVING COUNT(*) >= 2 ]]>  -= 4

    - +
    The WINDOW clause

    The SQL:2003 standard as well as PostgreSQL and Sybase SQL Anywhere support a WINDOW clause that allows for specifying WINDOW frames for reuse in and .

    - +   - +

    Note that in order to create such a window definition, we need to first create a using .

    Even if only PostgreSQL and Sybase SQL Anywhere natively support this great feature, jOOQ can emulate it by expanding any and types that you pass to the window() method - if the database supports window functions at all.

    - +

    Some more information about and the WINDOW clause can be found on our blog: http://blog.jooq.org/2013/11/03/probably-the-coolest-sql-feature-window-functions/

    @@ -4453,8 +4453,8 @@ ORDER BY CASE TITLE

    The SQL standard defines that a "query expression" can be ordered, and that query expressions can contain , whose subqueries cannot be ordered. While this is defined as such in the SQL standard, many databases allowing for the in one way or another, do not adhere to this part of the SQL standard. Hence, jOOQ allows for ordering all SELECT statements, regardless whether they are constructed as a part of a UNION or not. Corner-cases are handled internally by jOOQ, by introducing synthetic subselects to adhere to the correct syntax, where this is needed.

    - - + +

    Oracle's ORDER SIBLINGS BY clause

    jOOQ also supports Oracle's SIBLINGS keyword to be used with ORDER BY clauses for @@ -4506,7 +4506,7 @@ SELECT TOP 1 * FROM BOOK

    Things get a little more tricky in those databases that have no native idiom for OFFSET pagination (actual queries may vary):

    - + 1]]>

    As you can see, jOOQ will take care of the incredibly painful ROW_NUMBER() OVER() (or ROWNUM for Oracle) filtering in subselects for you, you'll just have to write limit(1).offset(2) in any dialect.

    - +

    Side-note: If you're interested in understanding why we chose ROWNUM for Oracle, please refer to this very interesting benchmark, comparing the different approaches of doing pagination in Oracle: http://www.inf.unideb.hu/~gabora/pagination/results.html.

    @@ -4553,7 +4553,7 @@ WHERE RN > 1]]>

    - +
    The SEEK clause @@ -4563,7 +4563,7 @@ WHERE RN > 1]]>

    A much faster and more stable way to perform paging is the so-called keyset paging method also called seek method. jOOQ supports a synthetic seek() clause, that can be used to perform keyset paging. Imagine we have these data:

    - + 1]]>

    Now, if we want to display page 6 to the user, instead of going to page 6 by using a record OFFSET, we could just fetch the record strictly after the last record on page 5, which yields the values (533, 2). This is how you would do it with SQL or with jOOQ:

    - + As you can see, the jOOQ SEEK clause is a synthetic clause that does not really exist in SQL. However, the jOOQ syntax is far more intuitive for a variety of reasons:

    - +
    • It replaces OFFSET where you would expect
    • It doesn't force you to mix regular predicates with "seek" predicates
    • It is typesafe
    • It emulates for you, in those databases that do not support them
    - +

    This query now yields:

    - + Note that you cannot combine the SEEK clause with the OFFSET clause.

    - +

    More information about this great feature can be found in the jOOQ blog:

    @@ -4634,11 +4634,11 @@ LIMIT 5
  • http://blog.jooq.org/2013/10/26/faster-sql-paging-with-jooq-using-the-seek-method/
  • http://blog.jooq.org/2013/11/18/faster-sql-pagination-with-keysets-continued/
  • - +

    Further information about offset pagination vs. keyset pagination performance can be found on our partner page:

    - +
    No more offset @@ -4750,7 +4750,7 @@ SELECT * FROM author ORDER BY id DESC;]]>

    SQL allows to perform set operations as understood in standard set theory on result sets. These operations include unions, intersections, subtractions. For two subselects to be combinable by such a set operator, each subselect must return a of the same degree and type.

    - +

    UNION and UNION ALL

    These operators combine two results into one. While UNION removes all duplicate records resulting from this combination, UNION ALL leaves subselect results as they are. Typically, you should prefer UNION ALL over UNION, if you don't really need to remove duplicates. The following example shows how to use such a UNION operation in jOOQ. @@ -4765,12 +4765,12 @@ SELECT * FROM BOOK WHERE ID = 5 .unionAll( create.selectFrom(BOOK).where(BOOK.ID.equal(5))) .fetch();]]> - +

    INTERSECT [ ALL ] and EXCEPT [ ALL ]

    INTERSECT is the operation that produces only those values that are returned by both subselects. EXCEPT is the operation that returns only those values that are returned exclusively in the first subselect. Both operators will remove duplicates from their results. The SQL standard allows to specify the ALL keyword for both of these operators as well, but this is hardly supported in any database. jOOQ does not support INTERSECT ALL, EXEPT ALL operations either.

    - +

    jOOQ's set operators and how they're different from standard SQL

    As previously mentioned in the manual's section about the , jOOQ has slightly changed the semantics of these set operators. While in SQL, a subselect may not contain any or (unless you wrap the subselect into a ), jOOQ allows you to do so. In order to select both the youngest and the oldest author from the database, you can issue the following statement with jOOQ (rendered to the MySQL dialect): @@ -4791,7 +4791,7 @@ ORDER BY 1 .orderBy(AUTHOR.DATE_OF_BIRTH.desc()).limit(1)) .orderBy(1) .fetch();]]> - +

    In case your database doesn't support ordered UNION subselects, the subselects are nested in derived tables:

    @@ -4809,12 +4809,12 @@ SELECT * FROM ( ORDER BY 1]]> - +

    Projection typesafety for degrees between 1 and {max-row-degree}

    Two subselects that are combined by a set operator are required to be of the same degree and, in most databases, also of the same type. jOOQ 3.0's introduction of helps compile-checking these constraints:

    - + > s1 = select(BOOK.ID, BOOK.TITLE).from(BOOK); Select> s2 = selectOne(); @@ -4850,7 +4850,7 @@ s1.union(s4); // OK. The two Record[N] types match]]>

    Note that you can pass any string in the .hint() clause. If you use that clause, the passed string will always be put in between the SELECT [DISTINCT] keywords and the actual projection list. This can be useful in other databases too, such as MySQL, for instance:

    - +
    - +
    Lexical and logical SELECT clause order

    SQL has a lexical and a logical order of SELECT clauses. The lexical order of SELECT clauses is inspired by the English language. As SQL statements are commands for the database, it is natural to express a statement in an imperative tense, such as "SELECT this and that!".

    - +

    Logical SELECT clause order

    The logical order of SELECT clauses, however, does not correspond to the syntax. In fact, the logical order is this:

    - +
    • : First, all data sources are defined and joined
    • : Then, data is filtered as early as possible
    • @@ -4888,11 +4888,11 @@ FROM table1
    • : Then, a paging view is created for the ordered tuples
    • : Finally, pessimistic locking is applied
    - +

    The SQL Server documentation also explains this, with slightly different clauses:

    - +
    • FROM
    • ON
    • @@ -4906,16 +4906,16 @@ FROM table1
    • ORDER BY
    • TOP
    - +

    As can be seen, databases have to logically reorder a SQL statement in order to determine the best execution plan.

    - +

    Alternative syntaxes: LINQ, SLICK

    Some "higher-level" abstractions, such as C#'s LINQ or Scala's SLICK try to inverse the lexical order of SELECT clauses to what appears to be closer to the logical order. The obvious advantage of moving the SELECT clause to the end is the fact that the projection type, which is the record type returned by the SELECT statement can be re-used more easily in the target environment of the internal domain specific language.

    - +

    A LINQ example:

    @@ -4928,11 +4928,11 @@ Where p.UnitsInStock <= p.ReorderLevel AndAlso Not p.Discontinued // SELECT clause Select p]]> - +

    A SLICK example:

    - + - +

    As you can see, this syntax is a bit more verbose, but also more readable, as every field can be matched with its value. Internally, the two syntaxes are strictly equivalent.

    @@ -5038,7 +5038,7 @@ SELECT 101, 'Alfred', 'Döblin' FROM DUAL;

    The MySQL database supports a very convenient way to INSERT or UPDATE a record. This is a non-standard extension to the SQL syntax, which is supported by jOOQ and emulated in other RDBMS, where this is possible (i.e. if they support the SQL standard ). Here is an example how to use the ON DUPLICATE KEY UPDATE clause:

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, update the author's name create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -5048,11 +5048,11 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .execute();

    The synthetic ON DUPLICATE KEY IGNORE clause

    - +

    The MySQL database also supports an INSERT IGNORE INTO clause. This is supported by jOOQ using the more convenient SQL syntax variant of ON DUPLICATE KEY IGNORE, which can be equally emulated in other databases using a :

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, ignore the INSERT statement create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -5089,15 +5089,15 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    The INSERT SELECT statement

    - +

    In some occasions, you may prefer the INSERT SELECT syntax, for instance, when you copy records from one table to another:

    - + create.insertInto(AUTHOR_ARCHIVE) .select(create.selectFrom(AUTHOR).where(AUTHOR.DECEASED.isTrue())) .execute(); - +
    @@ -5149,7 +5149,7 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    jOOQ supports formal in various contexts, among which the UPDATE statement. Only one row value expression can be updated at a time. Here's an example:

    - + The above row value expressions usages are completely typesafe.

    - +

    UPDATE .. RETURNING

    The Firebird and Postgres databases support a RETURNING clause on their UPDATE statements, similar as the RETURNING clause in . This is useful to fetch trigger-generated values in one go. An example is given here:

    - + The H2 database ships with a somewhat less powerful but a little more intuitive syntax for its own version of the MERGE statement. An example more or less equivalent to the previous one can be seen here:

    - + -- Check if there is already an author called 'Hitchcock' -- If there is, rename him to John. If there isn't add him. @@ -5286,7 +5286,7 @@ VALUES ('John', 'Hitchcock') This syntax can be fully emulated by jOOQ for all other databases that support the SQL standard MERGE statement. For more information about the H2 MERGE syntax, see the documentation here:
    http://www.h2database.com/html/grammar.html#merge

    - +

    Typesafety of VALUES() for degrees up to {max-row-degree}

    Much like the , the MERGE statement's VALUES() clause provides typesafety for degrees up to {max-row-degree}, in both the standard syntax variant as well as the H2 variant. @@ -5356,7 +5356,7 @@ create.alterSequence(S_AUTHOR_ID).restartWith(n).execute();]]>

    - +
    The CREATE statement @@ -5368,7 +5368,7 @@ create.alterSequence(S_AUTHOR_ID).restartWith(n).execute();]]>

    Indexes

    - @@ -5444,7 +5444,7 @@ WHERE 50 < (
    - +
    The DROP statement @@ -5530,7 +5530,7 @@ create.dropViewIfExists(V_AUTHOR).execute();]]>

    Most of the times, when thinking about a you're probably thinking about an actual table in your database schema. If you're using jOOQ's , you will have all tables from your database schema available to you as type safe Java objects. You can then use these tables in SQL , or in other , just like any other table expression. An example is given here:

    - + - +

    The above example shows how AUTHOR and BOOK tables are joined in a . It also shows how you can access by dereferencing the relevant Java attributes of their tables.

    @@ -5583,11 +5583,11 @@ create.select() .and(a.FIRST_NAME.equal("Paulo"))) .orderBy(b.TITLE) .fetch();]]> - +

    As you can see in the above example, calling as() on generated tables returns an object of the same type as the table. This means that the resulting object can be used to dereference fields from the aliased table. This is quite powerful in terms of having your Java compiler check the syntax of your SQL statements. If you remove a column from a table, dereferencing that column from that table alias will cause compilation errors.

    - +

    Dereferencing columns from other table expressions

    Only few table expressions provide the SQL syntax typesafety as shown above, where generated tables are used. Most tables, however, expose their fields through field() methods: @@ -5599,12 +5599,12 @@ Table a = AUTHOR.as("a"); // Get fields from a: Field id = a.field("ID"); Field firstName = a.field("FIRST_NAME");]]> - +

    Derived column lists

    The SQL standard specifies how a table can be renamed / aliased in one go along with its columns. It references the term "derived column list" for the following syntax (as supported by Postgres, for instance):

    - + In jOOQ, you would simply specify a varargs list of column aliases as such:

    - + The that can be used in are the most powerful and best supported means of creating new in SQL. Informally, the following can be said:

    - + A(colA1, ..., colAn) "join" B(colB1, ..., colBm) "produces" C(colA1, ..., colAn, colB1, ..., colBm)

    @@ -5679,7 +5679,7 @@ create.select().from(values(

    jOOQ supports all of these JOIN types (except semi-join and anti-join) directly on any :

    - + table) @@ -5717,7 +5717,7 @@ Table naturalRightOuterJoin(TableLike)]]>

    Some databases allow for expressing in-memory temporary tables using a VALUES() constructor. This constructor usually works the same way as the VALUES() clause known from the or from the . With jOOQ, you can also use the VALUES() table constructor, to create tables that can be used in a :

    - + Note, that it is usually quite useful to provide column aliases ("derived column lists") along with the table alias for the VALUES() constructor.

    - +

    The above statement is emulated by jOOQ for those databases that do not support the VALUES() constructor, natively (actual emulations may vary):

    - + A can appear almost anywhere a can. Such a "nested SELECT" is often called a "derived table". Apart from many convenience methods accepting objects directly, a SELECT statement can always be transformed into a object using the asTable() method.

    - +

    Example: Scalar subquery

    - + If you are closely coupling your application to an Oracle database, you can take advantage of some Oracle-specific features, such as the PIVOT clause, used for statistical analyses. The formal syntax definition is as follows:

    - + -- SELECT .. FROM table PIVOT (aggregateFunction [, aggregateFunction] FOR column IN (expression [, expression])) -- WHERE .. - +

    The PIVOT clause is available from the type, as pivoting is done directly on a table. Currently, only Oracle's PIVOT clause is supported. Support for SQL Server's slightly different PIVOT clause will be added later. Also, jOOQ may emulate PIVOT for other dialects in the future.

    @@ -5909,7 +5909,7 @@ WHERE NOT EXISTS (

    The SQL standard specifies how SQL databases should implement ARRAY and TABLE types, as well as CURSOR types. Put simply, a CURSOR is a pointer to any materialised . Depending on the cursor's features, this table expression can be scrolled through in both directions, records can be locked, updated, removed, inserted, etc. Often, CURSOR types contain s, whereas ARRAY and TABLE types contain simple scalar values, although that is not a requirement

    - +

    ARRAY types in SQL are similar to Java's array types. They contain a "component type" or "element type" and a "dimension". This sort of ARRAY type is implemented in H2, HSQLDB and Postgres and supported by jOOQ as such. Oracle uses strongly-typed arrays, which means that an ARRAY type (VARRAY or TABLE type) has a name and possibly a maximum capacity associated with it.

    @@ -5932,7 +5932,7 @@ FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(null, null, 'ALLSTATS'));

    - +
    Table-valued functions @@ -5955,11 +5955,11 @@ BEGIN ORDER BY id RETURN END]]> - +

    The jOOQ code generator will now produce a from the above, which can be used as a SQL function:

    - + r1 = create.selectFrom(fBooks(null)).fetch(); @@ -5967,7 +5967,7 @@ Result r1 = create.selectFrom(fBooks(null)).fetch(); create.select(BOOK.ID, F_BOOKS.TITLE) .from(BOOK.crossApply(fBooks(BOOK.ID))) .fetch();]]> - +
    ¨ @@ -6039,12 +6039,12 @@ DSL.using(SQLDialect.SYBASE ).selectOne().getSQL();]]>

    Column expressions can be used in various SQL clauses in order to refer to one or several columns. This chapter explains how to form various types of column expressions with jOOQ. A particular type of column expression is given in the section about , where an expression may have a degree of more than one.

    - +

    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:

    - + field1 = BOOK.TITLE; @@ -6100,7 +6100,7 @@ ORDER BY BOOK.TITLE

    Just like , columns can be renamed using aliases. Here is an example:

    - + SELECT FIRST_NAME || ' ' || LAST_NAME author, COUNT(*) books FROM AUTHOR JOIN BOOK ON AUTHOR.ID = AUTHOR_ID @@ -6109,7 +6109,7 @@ GROUP BY FIRST_NAME, LAST_NAME;

    Here is how it's done with jOOQ:

    - + Record record = create.select( concat(AUTHOR.FIRST_NAME, val(" "), AUTHOR.LAST_NAME).as("author"), count().as("books")) @@ -6117,14 +6117,14 @@ GROUP BY FIRST_NAME, LAST_NAME; .join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID)) .groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .fetchAny(); - +

    When you alias Fields like above, you can access those Fields' values using the alias name:

    - + System.out.println("Author : " + record.getValue("author")); System.out.println("Books : " + record.getValue("books")); - + @@ -6137,7 +6137,7 @@ System.out.println("Books : " + record.getValue("books"));

    Sometimes, this automatic mapping might not be what you needed, or jOOQ cannot know the type of a field. In those cases you would write SQL type CAST like this:

    - + -- Let's say, your Postgres column LAST_NAME was VARCHAR(30) -- Then you could do this: SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL @@ -6145,27 +6145,27 @@ SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL

    in jOOQ, you can write something like that:

    - + create.select(TAuthor.LAST_NAME.cast(PostgresDataType.TEXT)).fetch();

    The same thing can be achieved by casting a Field directly to String.class, as TEXT is the default data type in Postgres to map to Java's String

    - + create.select(TAuthor.LAST_NAME.cast(String.class)).fetch(); - +

    The complete CAST API in consists of these three methods:

    - + { // Cast this field to the type of another field Field cast(Field field); - + // Cast this field to a given DataType Field cast(DataType type); - + // Cast this field to the default DataType for a given Class Field cast(Class type); } @@ -6188,14 +6188,14 @@ public class DSL {

    A slightly different use case than are data type coercions, which are not rendered through to generated SQL. Sometimes, you may want to pretend that a numeric value is really treated as a string value, for instance when binding a numeric :

    - + field1 = val(1).coerce(String.class); Field field2 = val("1").coerce(Integer.class);]]>

    In the above example, field1 will be treated by jOOQ as a Field<String>, binding the numeric literal 1 as a VARCHAR value. The same applies to field2, whose string literal "1" will be bound as an INTEGER value.

    - +

    This technique is better than performing unsafe or rawtype casting in Java, if you cannot access the "right" field type from any given expression.

    @@ -6215,15 +6215,15 @@ Field field2 = val("1").coerce(Integer.class);]]>

    In order to express a SQL query like this one:

    - + SELECT ((1 + 2) * (5 - 3) / 2) % 10 FROM DUAL - +

    You can write something like this in jOOQ:

    - + create.select(val(1).add(2).mul(val(5).sub(3)).div(2).mod(10)).fetch(); - +

    Operator precedence

    jOOQ does not know any operator precedence (see also ). All operations are evaluated from left to right, as with any object-oriented API. The two following expressions are the same: @@ -6251,14 +6251,14 @@ Field field2 = val("1").coerce(Integer.class);]]> - +

    String concatenation

    The SQL standard defines the concatenation operator to be an infix operator, similar to the ones we've seen in the chapter about . This operator looks like this: ||. Some other dialects do not support this operator, but expect a concat() function, instead. jOOQ renders the right operator / function, depending on your :

    - + SELECT 'A' || 'B' || 'C' FROM DUAL -- Or in MySQL: @@ -6286,13 +6286,13 @@ create.select(concat("A", "B", "C")).fetch();
  • NVL: Get the first non-null value among two arguments.
  • NVL2: Get the second argument if the first is null, or the third argument, otherwise.
  • - +

    Please refer to the for more details.

    - +
    Numeric functions @@ -6302,7 +6302,7 @@ create.select(concat("A", "B", "C")).fetch();

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ABS: Get the absolute value of a value.
    • ACOS: Get the arc cosine of a value.
    • @@ -6333,7 +6333,7 @@ create.select(concat("A", "B", "C")).fetch();
    • TANH: Get the hyperbolic tangent of a value.
    • TRUNC: Truncate the decimals off a given value.
    - +

    Please refer to the for more details.

    @@ -6358,13 +6358,13 @@ create.select(concat("A", "B", "C")).fetch();
  • SHL: Shift bits to the left
  • SHR: Shift bits to the right
  • - +

    Some background about bitwise operation emulation

    As stated before, not all databases support all of these bitwise operations. jOOQ emulates them wherever this is possible. More details can be seen in this blog post:
    http://blog.jooq.org/2011/10/30/the-comprehensive-sql-bitwise-operations-compatibility-list/

    - +
    @@ -6377,7 +6377,7 @@ create.select(concat("A", "B", "C")).fetch();

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ASCII: Get the ASCII code of a character.
    • BIT_LENGTH: Get the length of a string in bits.
    • @@ -6398,16 +6398,16 @@ create.select(concat("A", "B", "C")).fetch();
    • TRIM: Trim a string on both sides.
    • UPPER: Get a string in upper case letters.
    - +

    Please refer to the for more details.

    - +

    Regular expressions, REGEXP, REGEXP_LIKE, etc.

    Various databases have some means of searching through columns using regular expressions if the does not provide sufficient pattern matching power. While there are many different functions and operators in the various databases, jOOQ settled for the SQL:2008 standard REGEX_LIKE operator. Being an operator (and not a function), you should use the corresponding method on :

    - +

    @@ -6416,7 +6416,7 @@ create.select(concat("A", "B", "C")).fetch(); - +

    Case sensitivity with strings @@ -6429,20 +6429,20 @@ create.select(concat("A", "B", "C")).fetch();

    For these ad-hoc ordering use-cases, most people resort to using LOWER() or UPPER() as follows:

    - + -- Case-insensitive filtering: -SELECT * FROM BOOK +SELECT * FROM BOOK WHERE upper(TITLE) = 'ANIMAL FARM' -- Case-insensitive ordering: -SELECT * +SELECT * FROM AUTHOR ORDER BY upper(FIRST_NAME), upper(LAST_NAME) // Case-insensitive filtering: create.selectFrom(BOOK) .where(upper(BOOK.TITLE).eq("ANIMAL FARM")).fetch(); - + // Case-insensitive ordering: create.selectFrom(AUTHOR) .orderBy(upper(AUTHOR.FIRST_NAME), upper(AUTHOR.LAST_NAME)) @@ -6459,7 +6459,7 @@ create.selectFrom(AUTHOR)

    This is a list of date and time functions supported by jOOQ's :

    - +
    • CURRENT_DATE: Get current date as a DATE object.
    • CURRENT_TIME: Get current time as a TIME object.
    • @@ -6469,7 +6469,7 @@ create.selectFrom(AUTHOR)
    • TIMESTAMP_ADD: Add a number of days or an interval to a timestamp.
    • TIMESTAMP_DIFF: Get the difference as an INTERVAL DAY TO SECOND between two dates.
    - +

    Intervals in jOOQ

    jOOQ fills a gap opened by JDBC, which neglects an important SQL data type as defined by the SQL standards: INTERVAL types. See the manual's section about for more details. @@ -6621,7 +6621,7 @@ GROUP BY AUTHOR_ID WindowOverStep rank(); WindowOverStep denseRank(); WindowOverStep percentRank(); - + // Windowing functions WindowIgnoreNullsStep firstValue(Field field); WindowIgnoreNullsStep lastValue(Field field) @@ -6637,7 +6637,7 @@ GROUP BY AUTHOR_ID // Statistical functions WindowOverStep cumeDist(); WindowOverStep ntile(int number);]]> - +

    SQL distinguishes between various window function types (e.g. "ranking functions"). Depending on the function, SQL expects mandatory PARTITION BY or ORDER BY clauses within the OVER() clause. jOOQ does not enforce those rules for two reasons:

    @@ -6652,14 +6652,14 @@ GROUP BY AUTHOR_ID

    Here are some simple examples of window functions with jOOQ:

    - + -- Sample uses of ROW_NUMBER() ROW_NUMBER() OVER() ROW_NUMBER() OVER(PARTITION BY 1) ROW_NUMBER() OVER(ORDER BY BOOK.ID) ROW_NUMBER() OVER(PARTITION BY BOOK.AUTHOR_ID ORDER BY BOOK.ID) - + -- Sample uses of FIRST_VALUE FIRST_VALUE(BOOK.ID) OVER() FIRST_VALUE(BOOK.ID IGNORE NULLS) OVER() @@ -6670,14 +6670,14 @@ rowNumber().over() rowNumber().over().partitionByOne() rowNumber().over().partitionBy(BOOK.AUTHOR_ID) rowNumber().over().partitionBy(BOOK.AUTHOR_ID).orderBy(BOOK.ID) - + // Sample uses of firstValue() firstValue(BOOK.ID).over() firstValue(BOOK.ID).ignoreNulls().over() firstValue(BOOK.ID).respectNulls().over()
    - +

    An advanced window function example

    Window functions can be used for things like calculating a "running total". The following example fetches transactions and the running total for every transaction going back to the beginning of the transaction table (ordered by booked_at). Window functions are accessible from the previously seen type using the over() method: @@ -6705,7 +6705,7 @@ firstValue(BOOK.ID).respectNulls().over()

    In the previous chapter about , we have seen the concept of "ordered-set aggregate functions", such as Oracle's LISTAGG(). These functions have a window function / analytical function variant, as well. For example:

    - + SELECT LISTAGG(TITLE, ', ') WITHIN GROUP (ORDER BY TITLE) @@ -6790,7 +6790,7 @@ ORDER BY 1 NULLS LAST, 2 NULLS LAST

    In English, the ROLLUP() grouping function provides N+1 groupings, when N is the number of arguments to the ROLLUP() function. Each grouping has an additional group field from the ROLLUP() argument field list. The results of the second query might look something like this:

    - + GROUPING SETS() and other grouping functions:
    http://msdn.microsoft.com/en-us/library/bb510427(v=sql.105)

    - +

    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:

    - + ... fields); GroupField cube(Field... fields); @@ -6893,7 +6893,7 @@ Field groupingId(Field...);]]>

    MySQL and CUBRID don't know any grouping functions, but they support a WITH ROLLUP clause, that is equivalent to simple ROLLUP() grouping functions. jOOQ emulates ROLLUP() in MySQL and CUBRID, by rendering this WITH ROLLUP clause. The following two statements mean the same:

    - + Some databases support user-defined functions, which can be embedded in any SQL statement, if you're using jOOQ's . Let's say you have the following simple function in Oracle SQL:

    - + The above function will be made available from a generated class. You can use it like any other :

    - + - +

    Note that user-defined functions returning or data types can also be used wherever can be used, if they are

    @@ -6945,7 +6945,7 @@ END echo;

    Some databases support user-defined aggregate functions, which can then be used along with or as . An example for such a database is Oracle. With Oracle, you can define the following OBJECT type (the example was taken from the Oracle 11g documentation):

    - +

    jOOQ's will detect such aggregate functions and generate them differently from regular . They implement the type, as mentioned in the manual's section about . Here's how you can use the SECOND_MAX() aggregate function with jOOQ:

    - +
    - +
    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:

    - + Row1 row(T1 t1) { ... } public static Row2 row(T1 t1, T2 t2) { ... } @@ -7175,12 +7175,12 @@ public static RowN row(Object... values) { ... }]]>

    See the relevant sections for more details about how to use row value expressions in predicates.

    - +

    Using row value expressions in UPDATE statements

    The also supports a variant where row value expressions are updated, rather than single columns. See the relevant section for more details

    - +

    Higher-degree row value expressions

    jOOQ chose to explicitly support degrees up to {max-row-degree} to match Scala's typesafe tuple, function and product support. Unlike Scala, however, jOOQ also supports higher degrees without the additional typesafety. @@ -7204,7 +7204,7 @@ public static RowN row(Object... values) { ... }]]>

  • The of a
  • The 's ON clause
  • - +

    Boolean types in SQL

    Before SQL:1999, boolean types did not really exist in SQL. They were modelled by 0 and 1 numeric/char values. With SQL:1999, true booleans were introduced and are now supported by most databases. In short, these are possible boolean values: @@ -7300,7 +7300,7 @@ Condition combined2 = combined1.andNot(c); // The left-hand side of the AND NOT

    Here are all boolean operators on the interface:

    - + < to test for being strictly less
  • <= to test for being less or equal
  • - +

    Unfortunately, Java does not support operator overloading, hence these operators are also implemented as methods in jOOQ, like any other SQL syntax elements. The relevant parts of the interface are these:

    - + ); // = (some column expression) eq or equal(Select>); // = (some scalar SELECT statement) @@ -7362,12 +7362,12 @@ ge or greaterOrEqual(Select>); // >= (some scalar SELECT st

    Note that every operator is represented by two methods. A verbose one (such as equal()) and a two-character one (such as eq()). Both methods are the same. You may choose either one, depending on your taste. The manual will always use the more verbose one.

    - +

    jOOQ's convenience methods using comparison operators

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using comparison predicates:

    - +
    - +
    Boolean operator precedence @@ -7394,7 +7394,7 @@ BOOK.TITLE.notEqualIgnoreCase("animal farm")]]>

    In SQL, the two expressions wouldn't be the same, as SQL natively knows operator precedence.

    - + A AND B OR C AND D OR E -- Precedence is applied (((A AND B) OR C) AND D) OR E -- Precedence is overridden @@ -7408,7 +7408,7 @@ BOOK.TITLE.notEqualIgnoreCase("animal farm")]]>

    All variants of the that we've seen in the previous chapter also work for . If your database does not support row value expression comparison predicates, jOOQ emulates them the way they are defined in the SQL standard:

    - + (X, Y))]]>

    jOOQ supports all of the above row value expression comparison predicates, both with and at the right-hand side:

    - +
    - +
    Quantified comparison predicate @@ -7505,7 +7505,7 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    It is interesting to note that the SQL standard defines the in terms of the ANY-quantified predicate. The following two expressions are equivalent:

    - + @@ -7516,14 +7516,14 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    - +
    NULL predicate

    In SQL, you cannot compare NULL with any value using , as the result would yield NULL again, which is neither TRUE nor FALSE (see also the manual's section about ). In order to test a for NULL, use the NULL predicate as such:

    - + @@ -7561,7 +7561,7 @@ NOT((A, B) IS NOT NULL)]]>

    The SQL standard contains a nice truth table for the above rules:

    - + +-----------------------+-----------+---------------+---------------+-------------------+ | Expression | R IS NULL | R IS NOT NULL | NOT R IS NULL | NOT R IS NOT NULL | +-----------------------+-----------+---------------+---------------+-------------------+ @@ -7575,13 +7575,13 @@ NOT((A, B) IS NOT NULL)]]>

    In jOOQ, you would simply use the isNull() and isNotNull() methods on row value expressions. Again, as with the , the row value expression NULL predicate is emulated by jOOQ, if your database does not natively support it:

    - +
    - +
    DISTINCT predicate @@ -7608,7 +7608,7 @@ BOOK.TITLE.isNotDistinctFrom(BOOK.SUB_TITLE)]]>

    If your database does not natively support the DISTINCT predicate, jOOQ emulates it with an equivalent , modelling the above truth table:

    - + ... or better, if the INTERSECT set operation is supported:

    - + - +
    @@ -7649,7 +7649,7 @@ EXISTS(SELECT a INTERSECT SELECT b)

    The BETWEEN predicate can be seen as syntactic sugar for a pair of . According to the SQL standard, the following two predicates are equivalent:

    - + = [B] AND [A] <= [C]]]> @@ -7670,7 +7670,7 @@ BOOK.PUBLISHED_IN.notBetween(1920).and(1940)]]>

    The SQL standard defines the SYMMETRIC keyword to be used along with BETWEEN to indicate that you do not care which bound of the range is larger than the other. A database system should simply swap range bounds, in case the first bound is greater than the second one. jOOQ supports this keyword as well, emulating it if necessary.

    - + @@ -7681,7 +7681,7 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The emulation is done trivially:

    - + @@ -7696,27 +7696,27 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The SQL BETWEEN predicate also works well for . Much like the , it is defined in terms of a pair of regular :

    - + = [B] AND [A] <= [C] ([A] >= [B] AND [A] <= [C]) OR ([A] >= [C] AND [A] <= [B])]]> - +

    The above can be factored out according to the rules listed in the manual's section about .

    - +

    jOOQ supports the BETWEEN [SYMMETRIC] predicate and emulates it in all SQL dialects where necessary. An example is given here:

    - + - + - +
    LIKE predicate @@ -7737,7 +7737,7 @@ TITLE NOT LIKE '%abc%']]> - +

    Escaping operands with the LIKE predicate

    Often, your pattern may contain any of the wildcard characters "_" and "%", in case of which you may want to escape them. jOOQ does not automatically escape patterns in like() and notLike() methods. Instead, you can explicitly define an escape character as such: @@ -7756,12 +7756,12 @@ BOOK.TITLE.notLike("%The !%-Sign Book%", '!')]]>

    Please refer to your database manual for more details about escaping patterns with the LIKE predicate.

    - +

    jOOQ's convenience methods using the LIKE predicate

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using the LIKE predicate. Typical operations are "contains predicates", "starts with predicates", "ends with predicates", etc. Here is the full convenience API wrapping LIKE predicates:

    - + >) // Construct a NOT IN predicate from a subse

    A sample IN predicate might look like this:

    - + @@ -7814,12 +7814,12 @@ TITLE NOT IN ('Animal Farm', '1984')]]>
    BOOK.TITLE.notIn("Animal Farm", "1984")]]>
    - +

    NOT IN and NULL values

    Beware that you should probably not have any NULL values in the right hand side of a NOT IN predicate, as the whole expression would evaluate to NULL, which is rarely desired. This can be shown informally using the following reasoning:

    - + -- The following conditional expressions are formally or informally equivalent A NOT IN (B, C) A != ANY(B, C) @@ -7860,7 +7860,7 @@ NULL -- [ANY] AND NULL yields NULL -- Using a subselect (BOOK.ID, BOOK.TITLE) IN ( SELECT T.ID, T.TITLE - FROM T + FROM T )]]> - +

    In both cases, i.e. when using an IN list or when using a subselect, the type of the predicate is checked. Both sides of the predicate must be of equal degree and row type.

    - +

    - Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value. + Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value.

    - +
    EXISTS predicate @@ -7894,7 +7894,7 @@ row(BOOK.ID, BOOK.TITLE).in(
  • From a using
  • From a using , and from other clauses
  • - +

    An example of an EXISTS predicate can be seen here:

    @@ -7913,7 +7913,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

    - +

    Performance of IN vs. EXISTS

    In theory, the two types of predicates can perform equally well. If your database system ships with a sophisticated cost-based optimiser, it will be able to transform one predicate into the other, if you have all necessary constraints set (e.g. referential constraints, not null constraints). However, in reality, performance between the two might differ substantially. An interesting blog post investigating this topic on the MySQL database can be seen here:
    @@ -7921,7 +7921,7 @@ notExists(create.selectOne().from(BOOK)

    - +
    OVERLAPS predicate @@ -7959,7 +7959,7 @@ row(Date.valueOf('2010-01-01'), new DayToSecond(2)).overlaps(Date.valueOf('2010-

    Unlike the standard (or any database implementing the standard), jOOQ also supports the OVERLAPS predicate for comparing arbitrary . For instance, (1, 3) OVERLAPS (2, 4) will yield true in jOOQ. This is emulated as such

    - + In most cases, , , and as introduced in the previous chapters will be embedded into different SQL statement clauses as if the statement were a static SQL statement (e.g. in a view or stored procedure):

    - + - +

    It is, however, interesting to think of all of the above expressions as what they are: expressions. And as such, nothing keeps users from extracting expressions and referencing them from outside the statement. The following statement is exactly equivalent:

    @@ -8003,26 +8003,26 @@ create.select(select) .groupBy(groupBy) .orderBy() .fetch();]]> - +

    Each individual expression, and collection of expressions can be seen as an independent entity that can be

    - +
    1. Constructed dynamically
    2. Reused across queries
    - +

    Dynamic construction is particularly useful in the case of the , for dynamic predicate building. For instance:

    - +

    The dynamic SQL building power may be one of the biggest advantages of using a runtime query model like the one offered by jOOQ. Queries can be created dynamically, of arbitrary complexity. In the above example, we've just constructed a dynamic . The same can be done for any other clauses, including dynamic , or adding additional as needed.

    @@ -8058,7 +8058,7 @@ create.select()
  • - +

    You'll probably find other examples. If verbosity scares you off, don't worry. The verbose use-cases for jOOQ are rather rare, and when they come up, you do have an option. Just write SQL the way you're used to!

    @@ -8088,7 +8088,7 @@ Condition condition(String sql, Object... bindings); // Construct a condition taking other jOOQ object arguments // Example: condition("a = {0}", val(1)); 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 DSL:

    @@ -8146,7 +8146,7 @@ Result fetch(String sql, QueryPart... parts);]]>

    Apart from the general factory methods, plain SQL is also available in various other contexts. For instance, when adding a .where("a = b") clause to a query. Hence, there exist several convenience methods where plain SQL can be inserted usefully. This is an example displaying all various use-cases in one single query:

    - + LAST_NAME = create.field("a.LAST_NAME"); @@ -8267,7 +8267,7 @@ Name name = name("AUTHOR", "TITLE");]]> On a JDBC level, you can also reuse the SQL string and prepared statement object instead of constructing it again, as you can bind new values to the prepared statement. jOOQ currently does not cache prepared statements, internally. - +

    The following sections explain how you can introduce bind values in jOOQ, and how you can control the way they are rendered and bound to SQL.

    @@ -8280,7 +8280,7 @@ Name name = name("AUTHOR", "TITLE");]]>

    JDBC only knows indexed bind values. A typical example for using bind values with JDBC is this:

    - + With dynamic SQL, keeping track of the number of question marks and their corresponding index may turn out to be hard. jOOQ abstracts this and lets you provide the bind value right where it is needed. A trivial example is this:

    - + 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

    Should you decide to run the above query outside of jOOQ, using your own , you can do so as follows:

    - + select = create.select().from(BOOK).where(BOOK.ID.equal(5)).and(BOOK.TITLE.equal("Animal Farm")); // Render the SQL statement: @@ -8435,7 +8435,7 @@ create.select()

    Special care needs to be taken when using . While jOOQ's API allows you to specify bind values for use with plain SQL, you're not forced to do that. For instance, both of the following queries will lead to the same, valid result:

    - +

    A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] FROM AUTHOR JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID @@ -8578,15 +8578,15 @@ public final void accept(Context context) {

    As mentioned in the previous chapter about , there are some elements in the that are used for formatting / pretty-printing rendered SQL. In order to obtain pretty-printed SQL, just use the following :

    - - + +

    And then, use the above DSLContext to render pretty-printed SQL:

    - + A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] WHERE AUTHOR.ID = ? -- [...] @@ -8675,7 +8675,7 @@ public final void bind(BindContext context) throws DataAccessException {

    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:

    - + extends AbstractField {} public abstract class CustomCondition extends AbstractCondition {} public abstract class CustomTable> extends TableImpl {} @@ -8684,7 +8684,7 @@ public abstract class CustomRecord> extends TableRecord

    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 method, as discussed before:

    - + 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 showing how to create a field multiplying another field by 2

    - + IDx2 = new CustomField(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(" * ?"); @@ -8724,10 +8724,10 @@ final Field IDx2 = new CustomField(BOOK.ID.getName(), BOOK.ID. @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(DSL.val(2)); } @@ -8746,7 +8746,7 @@ create.select(IDx2).from(BOOK).fetch();]]>

    Many vendor-specific functions are not officially supported by jOOQ, but you can implement such support yourself using CustomField, for instance. Here's an example showing how to implement Oracle's TO_CHAR() function, emulating it in SQL Server using CONVERT():

    - + { @@ -8783,7 +8783,7 @@ class ToChar extends CustomField {

    The above CustomField implementation can be exposed from your own custom DSL class:

    - + toChar(Field field, String format) { return new ToChar(field, DSL.inline(format)); @@ -8791,7 +8791,7 @@ class ToChar extends CustomField { }]]>
    - +
    Plain SQL QueryParts @@ -8805,7 +8805,7 @@ class ToChar extends CustomField {

    The above distinction is best explained using an example:

    - +

    - +
    Custom SQL transformation @@ -8853,7 +8853,7 @@ create.attach(select);]]> With jOOQ 3.2's SPI, it is possible to perform custom SQL transformation to implement things like shared-schema multi-tenancy, or a security layer centrally preventing access to certain data. This SPI is extremely powerful, as you can make ad-hoc decisions at runtime regarding local or global transformation of your SQL statement. The following sections show a couple of simple, yet real-world use-cases.

    - +
    Logging abbreviated bind values @@ -8861,7 +8861,7 @@ create.attach(select);]]>

    When implementing a logger, one needs to carefully assess how much information should really be disclosed on what logger level. In log4j and similar frameworks, we distinguish between FATAL, ERROR, WARN, INFO, DEBUG, and TRACE. In DEBUG level, jOOQ's logs all executed statements including inlined bind values as such:

    - + with bind values : select * from "BOOK" where "BOOK"."TITLE" like 'How I stopped worrying%']]> @@ -8877,7 +8877,7 @@ public class BindValueAbbreviator extends DefaultVisitListener { @Override public void visitStart(VisitContext context) { - + // Transform only when rendering values if (context.renderContext() != null) { QueryPart part = context.queryPart(); @@ -8891,16 +8891,16 @@ public class BindValueAbbreviator extends DefaultVisitListener { // e.g. using commons-lang's StringUtils.abbreviate() if (value instanceof String && ((String) value).length() > maxLength) { anyAbbreviations = true; - + // ... and replace it in the current rendering context (not in the Query) context.queryPart(val(abbreviate((String) value, maxLength))); } - + // If the bind value is a byte[] (or Blob) of a given length, abbreviate it // e.g. by removing bytes from the array else if (value instanceof byte[] && ((byte[]) value).length > maxLength) { anyAbbreviations = true; - + // ... and replace it in the current rendering context (not in the Query) context.queryPart(val(Arrays.copyOf((byte[]) value, maxLength))); } @@ -8910,10 +8910,10 @@ public class BindValueAbbreviator extends DefaultVisitListener { @Override public void visitEnd(VisitContext context) { - + // If any abbreviations were performed before... if (anyAbbreviations) { - + // ... and if this is the top-level QueryPart, then append a SQL comment to indicate the abbreviation if (context.queryPartsLength() == 1) { context.renderContext().sql(" -- Bind values may have been abbreviated"); @@ -8938,14 +8938,14 @@ public class BindValueAbbreviator extends DefaultVisitListener {
    - +
    SQL building in Scala

    jOOQ-Scala is a maven module used for leveraging some advanced Scala features for those users that wish to use jOOQ with Scala.

    - +

    Using Scala's implicit defs to allow for operator overloading

    The most obvious Scala feature to use in jOOQ are implicit defs for implicit conversions in order to enhance the type with SQL-esque operators. @@ -8953,7 +8953,7 @@ public class BindValueAbbreviator extends DefaultVisitListener {

    The following depicts a trait which wraps all fields:

    - + The following depicts a trait which wraps numeric fields:

    - + An example query using such overloaded operators would then look like this:

    - +

    In a previous section of the manual, we've seen how jOOQ can be used to that can be executed with any API including JDBC or ... jOOQ. This section of the manual deals with various means of actually executing SQL with jOOQ.

    - +

    SQL execution with JDBC

    JDBC calls executable objects "". It distinguishes between three types of statements: @@ -9093,7 +9093,7 @@ fetch]]>

    Today, the JDBC API may look weird to users being used to object-oriented design. While statements hide a lot of SQL dialect-specific implementation details quite well, they assume a lot of knowledge about the internal state of a statement. For instance, you can use the method, to add a the prepared statement being created to an "internal list" of batch statements. Instead of returning a new type, this method forces user to reflect on the prepared statement's internal state or "mode".

    - +

    jOOQ is wrapping JDBC

    These things are abstracted away by jOOQ, which exposes such concepts in a more object-oriented way. For more details about jOOQ's batch query execution, see the manual's section about . @@ -9115,7 +9115,7 @@ fetch]]>

  • Both APIs return the number of affected records in non-result queries. JDBC: , jOOQ:
  • Both APIs return a scrollable result set type from result queries. JDBC: , jOOQ:
  • - +

    Differences to JDBC

    Some of the most important differences between JDBC and jOOQ are listed here: @@ -9131,14 +9131,14 @@ fetch]]>

    - +
    Query vs. ResultQuery

    Unlike JDBC, jOOQ has a lot of knowledge about a SQL query's structure and internals (see the manual's section about ). Hence, jOOQ distinguishes between these two fundamental types of queries. While every can be executed, only can return results (see the manual's section about to learn more about fetching results). With plain SQL, the distinction can be made clear most easily:

    - + result = resultQuery.fetch();]]>
  • : Some databases allow for returning many result sets from a single query. JDBC can handle this but it's very verbose. A list of results should be returned instead.
  • : Some queries take too long to execute to wait for their results. You should be able to spawn query execution in a separate process.
  • - +

    Convenience and how ResultQuery, Result, and Record share API

    The term "fetch" is always reused in jOOQ when you can fetch data from the database. An provides many overloaded means of fetching data:

    - +

    Various modes of fetching

    These modes of fetching are also documented in subsequent sections of the manual

    - + fetch(); @@ -9200,7 +9200,7 @@ List> fetchMany(); // Execute a ResultQuery with jOOQ, but return a JDBC ResultSet, not a jOOQ object ResultSet fetchResultSet();]]> - +

    Fetch convenience

    These means of fetching are also available from and APIs @@ -9246,11 +9246,11 @@ ResultSet fetchResultSet();]]>

    These means of fetching are also available from and APIs

    - + Map fetchMap(Field key); Map fetchMap(Field key, Field value); @@ -9290,7 +9290,7 @@ ResultSet fetchResultSet();]]>

    Yet, still, sometimes you wish to use strongly typed records, when you know that you're selecting only from a single table:

    - +

    Fetching strongly or weakly typed records

    When fetching data only from a single table, the type is known to jOOQ if you use jOOQ's to generate for your database tables. In order to fetch such strongly typed records, you will have to use the : @@ -9302,7 +9302,7 @@ BookRecord book = create.selectFrom(BOOK).where(BOOK.ID.equal(1)).fetchOne(); // Typesafe field access is now possible: 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:

    @@ -9310,11 +9310,11 @@ System.out.println("Published in: " + book.getPublishedIn());]]>
  • - +

    Mapping custom row types to strongly typed records

    - +

    Sometimes, you may want to explicitly select only a subset of your columns, but still use strongly typed records. Alternatively, you may want to join a one-to-one relationship and receive the two individual strongly typed records after the join.

    @@ -9375,7 +9375,7 @@ System.out.println("Author : " + author.getFirstName() + " " + author.getLa

    By default, jOOQ returns an object, which is essentially a of . Often, you will find yourself wanting to transform this result object into a type that corresponds more to your specific needs. Or you just want to list all values of one specific column. Here are some examples to illustrate those use cases:

    - + titles1 = create.select().from(BOOK).fetch().getValues(BOOK.TITLE); List titles2 = create.select().from(BOOK).fetch(BOOK.TITLE); @@ -9410,7 +9410,7 @@ Map> group4 = create.selectFrom(BOOK).fetchGroups(BO

    In a more functional operating mode, you might want to write callbacks that receive records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + () {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -9445,7 +9445,7 @@ create.selectFrom(BOOK)

    In a more functional operating mode, you might want to write callbacks that map records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + ids = create.selectFrom(BOOK) @@ -9457,12 +9457,12 @@ create.selectFrom(BOOK) return book.getId(); } }); - + // Or more concisely create.selectFrom(BOOK) .orderBy(BOOK.ID) .fetch(new RecordMapper() {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -9488,7 +9488,7 @@ create.selectFrom(BOOK)

    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. See the manual's section about to see how to modify jOOQ's standard POJO mapping behaviour.

    - +

    Using JPA-annotated POJOs

    jOOQ tries to find JPA annotations on your POJO types. If it finds any, they are used as the primary source for mapping meta-information. Only the annotation is used and understood by jOOQ. An example: @@ -9498,7 +9498,7 @@ create.selectFrom(BOOK) public class MyBook { @Column(name = "ID") public int myId; - + @Column(name = "TITLE") public String myTitle; } @@ -9507,16 +9507,16 @@ public class MyBook { MyBook myBook = create.select().from(BOOK).fetchAny().into(MyBook.class); List myBooks = create.select().from(BOOK).fetch().into(MyBook.class); List myBooks = create.select().from(BOOK).fetchInto(MyBook.class);]]> - +

    Just as with any other JPA implementation, you can put the annotation on any class member, including attributes, setters and getters. Please refer to the Javadoc for more details.

    - +

    Using simple POJOs

    If jOOQ does not find any JPA-annotations, columns are mapped to the "best-matching" constructor, attribute or setter. An example illustrates this:

    - + myBooks = create.select().from(BOOK).fetchInto(MyBook1.class);]]><

    Please refer to the Javadoc for more details.

    - +

    Using "immutable" POJOs

    If jOOQ does not find any default constructor, columns are mapped to the "best-matching" constructor. This allows for using "immutable" POJOs with jOOQ. An example illustrates this:

    - + myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchInto( public class MyBook3 { public final String title; public final int id; - + @ConstructorProperties({ "title", "id"}) public MyBook2(String title, int id) { this.title = title; @@ -9571,7 +9571,7 @@ MyBook3 myBook = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchA List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetch().into(MyBook3.class); List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchInto(MyBook3.class); ]]> - +

    Please refer to the Javadoc for more details.

    @@ -9580,12 +9580,12 @@ List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchI

    jOOQ also allows for fetching data into abstract classes or interfaces, or in other words, "proxyable" types. This means that jOOQ will return a wrapped in a implementing your custom type. An example of this is given here:

    - + - +

    Note: Because of your manual setting of ID = 10, jOOQ's store() method will asume that you want to insert a new record. See the manual's section about for more details on this.

    - +

    Interaction with DAOs

    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: @@ -9652,21 +9652,21 @@ bookDao.update(book); // Delete it again bookDao.delete(book);]]> - +

    More complex data structures

    jOOQ currently doesn't support more complex data structures, the way Hibernate/JPA attempt to map relational data onto POJOs. While future developments in this direction are not excluded, jOOQ claims that generic mapping strategies lead to an enormous additional complexity that only serves very few use cases. You are likely to find a solution using any of jOOQ's various , with only little boiler-plate code on the client side.

    - +
    POJOs with RecordMappers

    In the previous sections we have seen how to create types to map jOOQ records onto arbitrary objects. We have also seen how jOOQ provides default algorithms to map jOOQ records onto . Your own custom domain model might be much more complex, but you want to avoid looking up the most appropriate RecordMapper every time you need one. For this, you can provide jOOQ's with your own implementation of the interface. An example is given here:

    - + } } } - + // Books might be joined with their authors, create a 1:1 mapping if (type == Book.class) { return new BookMapper(); @@ -9703,12 +9703,12 @@ bookDao.delete(book);]]>

    The above is a very simple example showing that you will have complete flexibility in how to override jOOQ's record to POJO mapping mechanisms.

    - +

    Using third party libraries

    A couple of useful libraries exist out there, which implement custom, more generic mapping algorithms. Some of them have been specifically made to work with jOOQ. Among them are:

    - +
    • ModelMapper (with an explicit jOOQ integration)
    • SimpleFlatMapper (with an explicit jOOQ integration)
    • @@ -9723,7 +9723,7 @@ bookDao.delete(book);]]>

      Unlike JDBC's , jOOQ's does not represent an open database cursor with various fetch modes and scroll modes, that needs to be closed after usage. jOOQ's results are simple in-memory Java objects, containing all of the result values. If your result sets are large, or if you have a lot of network latency, you may wish to fetch records one-by-one, or in small chunks. jOOQ supports a type for that purpose. In order to obtain such a reference, use the method. An example is given here:

      - + cursor = null; @@ -9733,7 +9733,7 @@ try { // Cursor has similar methods as Iterator while (cursor.hasNext()) { BookRecord book = cursor.fetchOne(); - + Util.doThingsWithBook(book); } } @@ -9748,7 +9748,7 @@ finally {

      As a holds an internal reference to an open , it may need to be closed at the end of iteration. If a cursor is completely scrolled through, it will conveniently close the underlying ResultSet. However, you should not rely on that.

      - +

      Cursors ship with all the other fetch features

      Like or , gives access to all of the other fetch features that we've seen so far, i.e. @@ -9790,7 +9790,7 @@ finally {

      The correct (and verbose) way to do this with JDBC is as follows:

      - +

      As previously discussed in the chapter about , jOOQ does not rely on an internal state of any JDBC object, which is "externalised" by Javadoc. Instead, it has a straight-forward API allowing you to do the above in a one-liner:

      - + > results = create.fetchMany("sp_help 'author'");]]> @@ -9831,22 +9831,22 @@ List> results = create.fetchMany("sp_help 'author'");]]>
      Later fetching

      Using Java 8 CompletableFutures

      - +

      Java 8 has introduced the new type, which allows for functional composition of asynchronous execution units. When applying this to SQL and jOOQ, you might be writing code as follows:

      - + + .supplyAsync(() -> DSL.using(configuration) .insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .values(3, "Hitchcock") .execute() ) - + // This will supply an AuthorRecord value for the newly inserted author .handleAsync((rows, throwable) -> DSL.using(configuration) @@ -9859,30 +9859,30 @@ CompletableFuture record.changed(true); return record.insert(); }) - + // This will supply an int value indicating the number of deleted rows - .handleAsync((rows, throwable) -> + .handleAsync((rows, throwable) -> DSL.using(configuration) .delete(AUTHOR) .where(AUTHOR.ID.eq(3)) .execute() ) .join();]]> - +

      The above example will execute four actions one after the other, but asynchronously in the JDK's default or common . -

      - +

      +

      For more information, please refer to the Javadoc and official documentation. -

      - +

      +

      Using deprecated API

      - +

      Some queries take very long to execute, yet they are not crucial for the continuation of the main program. For instance, you could be generating a complicated report in a Swing application, and while this report is being calculated in your database, you want to display a background progress bar, allowing the user to pursue some other work. This can be achived simply with jOOQ, by creating a , a type that extends . An example is given here:

      - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(); @@ -9898,7 +9898,7 @@ Result result = future.get();]]>

      Note, that instead of letting jOOQ spawn a new thread, you can also provide jOOQ with your own :

      - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(service);]]> @@ -9912,7 +9912,7 @@ FutureResult future = create.selectFrom(BOOK).where(... complex pred

      When interacting with legacy applications, you may prefer to have jOOQ return a , rather than jOOQ's own types. This can be done simply, in two ways:

      - + cursor = create.fetchLazy(rs);]]>

      You can also tighten the interaction with jOOQ's data type system and features, by passing the record type to the above fetch methods:

      - + result = create.fetch (rs, Integer.class, String.class); Cursor result = create.fetchLazy(rs, Integer.class, String.class); @@ -9974,7 +9974,7 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Apart from a few extra features (), jOOQ only supports basic types as supported by the JDBC API. In your application, you may choose to transform these data types into your own ones, without writing too much boiler-plate code. This can be done using jOOQ's types. A converter essentially allows for two-way conversion between two Java data types <T> and <U>. By convention, the <T> type corresponds to the type in your database whereas the <U> type corresponds to your own user type. The Converter API is given here:

      - + extends Serializable { /** @@ -10001,12 +10001,12 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Such a converter can be used in many parts of the jOOQ API. Some examples have been illustrated in the manual's section about .

      - +

      A Converter for GregorianCalendar

      Here is a some more elaborate example involving a Converter for :

      - + { @@ -10037,12 +10037,12 @@ public class CalendarConverter implements Converter dates1 = create.selectFrom(BOOK).fetch().getValues(BOOK.PUBLISHING_DATE, new CalendarConverter()); List dates2 = create.selectFrom(BOOK).fetch(BOOK.PUBLISHING_DATE, new CalendarConverter()); ]]> - +

      Enum Converters

      jOOQ ships with a built-in default , that you can use to map VARCHAR values to enum literals or NUMBER values to enum ordinals (both modes are supported). Let's say, you want to map a YES / NO / MAYBE column to a custom Enum:

      - + - +

      Using Converters in generated source code

      jOOQ also allows for generated source code to reference your own custom converters, in order to permanently replace a <T> type by your own, custom <U> type. See the manual's section about for details. @@ -10104,20 +10104,20 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE) .join(AUTHOR).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) .intern(BOOK.AUTHOR_ID) .fetch();]]> - +

      You can specify as many fields as you want for interning. The above has the following effect:

      - +
      • If the interned Field is of type , then is called upon each string
      • If the interned Field is of any other type, then the call is ignored
      - +

      Future versions of jOOQ will implement interning of data for non-String data types by collecting values in , removing duplicate instances.

      - +

      Note, that jOOQ will not use interned data for identity comparisons: string1 == string2. Interning is used only to reduce the memory footprint of objects.

      @@ -10125,7 +10125,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)
    - +
    Static statements vs. Prepared Statements @@ -10135,7 +10135,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)

    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:

    - + @@ -10165,7 +10165,7 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    Whichever aproach is more optimal for you cannot be decided by jOOQ. In most cases, prepared statements are probably better. But you always have the option of forcing jOOQ to render inlined bind values.

    - +

    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 @@ -10179,15 +10179,15 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    As previously discussed in the chapter about , reusing PreparedStatements is handled a bit differently in jOOQ from how it is handled in JDBC

    - +

    Keeping open PreparedStatements with JDBC

    With JDBC, you can easily reuse a by not closing it between subsequent executions. An example is given here:

    - + The above technique can be quite useful when you want to reuse expensive database resources. This can be the case when your statement is executed very frequently and your database would take non-negligible time to soft-parse the prepared statement and generate a new statement / cursor resource.

    - +

    Keeping open PreparedStatements with jOOQ

    This is also modeled in jOOQ. However, the difference to JDBC is that closing a statement is the default action, whereas keeping it open has to be configured explicitly. This is better than JDBC, because the default action should be the one that is used most often. Keeping open statements is rarely done in average applications. Here's an example of how to keep open PreparedStatements with jOOQ:

    - + query = create.selectOne().keepStatement(true); @@ -10221,7 +10221,7 @@ finally {

    The above example shows how a query can be executed twice against the same underlying PreparedStatement. Unlike in other execution scenarios, you must not forget to close this query now

    - +

    Beware of resource leaks

    While jOOQ allows for explicitly keeping open PreparedStatement references in Query instances, the JDBC Connection may still be closed independently without jOOQ or the PreparedStatement noticing. It is the user's responsibility to close all resources according to the specification and behaviour of the concrete JDBC driver and the underlying database. @@ -10235,7 +10235,7 @@ finally {

    JDBC knows a couple of execution flags and modes, which can be set through the jOOQ API as well. jOOQ essentially supports these flags and execution modes:

    - + - + extends Query { // [...] @@ -10268,25 +10268,25 @@ finally { // The maximum number of rows to be fetched by JDBC // ----------------------------------------------------------- ResultQuery maxRows(int rows); - + }]]>

    Using ResultSet concurrency with ExecuteListeners

    An example of why you might want to manually set a ResultSet's concurrency flag to something non-default is given here:

    - + - +

    In the above example, your custom is triggered before jOOQ loads a new Record from the JDBC ResultSet. With the concurrency being set to ResultSet.CONCUR_UPDATABLE, you can now modify the database cursor through the standard JDBC ResultSet API.

    @@ -10344,22 +10344,22 @@ try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO author(id stmt.setString(2, "Erich"); stmt.setString(3, "Gamma"); stmt.addBatch(); - + stmt.setInt(1, 2); stmt.setString(2, "Richard"); stmt.setString(3, "Helm"); stmt.addBatch(); - + stmt.setInt(1, 3); stmt.setString(2, "Ralph"); stmt.setString(3, "Johnson"); stmt.addBatch(); - + stmt.setInt(1, 4); stmt.setString(2, "John"); stmt.setString(3, "Vlissides"); stmt.addBatch(); - + int[] result = stmt.executeBatch(); }]]>
    @@ -10368,7 +10368,7 @@ try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO author(id

    jOOQ supports executing queries in batch mode as follows:

    - + - +

    When creating a batch execution with a single query and multiple bind values, you will still have to provide jOOQ with dummy bind values for the original query. In the above example, these are set to null. For subsequent calls to bind(), there will be no type safety provided by jOOQ.

    @@ -10404,18 +10404,18 @@ create.batch(create.insertInto(AUTHOR, ID, FIRST_NAME, LAST_NAME ).values((Inte

    Instead of actually phrasing a select statement, you can also use the convenience methods:

    - + - +

    Inlining sequence references in SQL

    You can inline sequence references in jOOQ SQL statements. The following are examples of how to do that:

    - + The general distinction between (stored) procedures and (stored) functions can be summarised like this:

    - +

    Procedures

    • Are called using JDBC CallableStatement
    • Have no return value
    • Usually support OUT parameters
    - +

    Functions

    • Can be used in SQL statements
    • Have a return value
    • Usually don't support OUT parameters
    - +

    Exceptions to these rules

    • DB2, H2, and HSQLDB don't allow for JDBC escape syntax when calling functions. Functions must be used in a SELECT statement
    • @@ -10476,19 +10476,19 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

      To simplify things a little bit, jOOQ handles both procedures and functions the same way, using a more general type.

      - +

      Using jOOQ for standalone calls to stored procedures and functions

      If you're using jOOQ's , it will generate objects for you. Let's consider the following example:

      - +

      The generated artefacts can then be used as follows:

      - + - +

      But you can also call the procedure using a generated convenience method in a global Routines class:

      @@ -10515,7 +10515,7 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]>

      For more details about for procedures, see the manual's section about .

      - +

      Inlining stored function references in SQL

      Unlike procedures, functions can be inlined in SQL statements to generate or , if you're using . Assume you have a function like this: @@ -10523,11 +10523,11 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]> - +

      The generated artefacts can then be used as follows:

      - + boolean exists = create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]> - +

      For more info about inlining stored function references in SQL statements, please refer to the manual's section about .

      @@ -10568,7 +10568,7 @@ create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]>

      Oracle UDTs can have object-oriented structures including member functions and procedures. With Oracle, you can do things like this:

      - + {"name":"field-n","type":"type-n"}], "records":[[value-1-1,value-1-2,...,value-1-n], [value-2-1,value-2-2,...,value-2-n]]} - +

      Note: This format has changed in jOOQ 2.6.0

      @@ -10883,7 +10883,7 @@ Query query = error.query();]]>
    - +
    Importing JSON @@ -10942,12 +10942,12 @@ create.loadInto(BOOK)

    CRUD always uses the same patterns, regardless of the nature of underlying tables. This again, leads to a lot of boilerplate code, if you have to issue your statements yourself. Like Hibernate / JPA and other ORMs, jOOQ facilitates CRUD using a specific API involving types.

    - +

    Primary keys and updatability

    In normalised databases, every table has a primary key by which a tuple/record within that table can be uniquely identified. In simple cases, this is a (possibly auto-generated) number called ID. But in many cases, primary keys include several non-numeric columns. An important feature of such keys is the fact that in most databases, they are enforced using an index that allows for very fast random access to the table. A typical way to access / modify / delete a book is this:

    - + - +

    Normalised databases assume that a primary key is unique "forever", i.e. that a key, once inserted into a table, will never be changed or re-inserted after deletion. In order to use jOOQ's operations correctly, you should design your database accordingly.

    @@ -10968,7 +10968,7 @@ DELETE FROM BOOK WHERE ID = 5;]]>

    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:

    - + - +

    See the manual's section about for some more insight on "attached" objects.

    - +

    Storing

    Storing a record will perform an or an . In general, new records are always inserted, whereas records loaded from the database are always updated. This is best visualised in code: @@ -11007,7 +11007,7 @@ BookRecord book2 = create.fetchOne(BOOK, BOOK.ID.equal(id)); // Update the record: UPDATE BOOK SET TITLE = 'Animal Farm' WHERE ID = [id] book2.setTitle("Animal Farm"); book2.store();]]> - +

    Some remarks about storing:

    @@ -11017,18 +11017,18 @@ book2.store();]]>
  • When loading records from , jOOQ will assume the record is a new record. It will hence attempt to INSERT it.
  • When you activate , storing a record may fail, if the underlying database record has been changed in the mean time.
  • - +

    Deleting

    Deleting a record will remove it from the database. Here's how you delete records:

    - + - +

    Refreshing

    Refreshing a record from the database means that jOOQ will issue a to refresh all record values that are not the primary key. This is particularly useful when you use jOOQ's feature, in case a modified record is "stale" and cannot be stored to the database, because the underlying database record has changed in the mean time. @@ -11047,7 +11047,7 @@ book.refresh();]]>

    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 :

    - + The "original" value, i.e. the value as it was originally fetched from the database or null, if the record was never in the database
  • The "changed" flag, indicating if the value was ever changed through the Record API.
  • - +

    The purpose of the above information is for jOOQ's to know, which values need to be stored to the database, and which values have been left untouched.

    @@ -11083,19 +11083,19 @@ for (BookRecord book : create.fetch(BOOK, BOOK.PUBLISHED_IN.equal(1948))) {

    Many databases support the concept of IDENTITY values, or key values. This is reflected by JDBC's method. jOOQ abstracts using this method as many databases and JDBC drivers behave differently with respect to generated keys. Let's assume the following SQL Server BOOK table:

    - +

    If you're using jOOQ's , the above table will generate a with an IDENTITY column. This information is used by jOOQ internally, to update IDs after calling :

    - +

    and contain foreign key navigation methods. These navigation methods allow for "navigating" inbound or outbound foreign key references by executing an appropriate query. An example is given here:

    - + books = author.fetchChildren(FK_BOOK_AUTHOR);]]>

    Tables without a PRIMARY KEY are considered non-updatable by jOOQ, as jOOQ has no way of uniquely identifying such a record within the database. If you're using jOOQ's , such tables will generate classes, instead of classes. When you fetch from such a table, the returned records will not allow for calling any of the methods.

    - +

    Note, that some databases use internal rowid or object-id values to identify such records. jOOQ does not support these vendor-specific record meta-data.

    @@ -11226,7 +11226,7 @@ Result books = author.fetchChildren(FK_BOOK_AUTHOR);]]>
    - +

    Optimised optimistic locking using TIMESTAMP fields

    If you're using jOOQ's , you can take indicate TIMESTAMP or UPDATE COUNTER fields for every generated table in the . Let's say we have this table:

    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:

    - +

    As before, without the added TIMESTAMP column, optimistic locking is transparent to the API.

    - +

    Optimised optimistic locking using VERSION fields

    Instead of using TIMESTAMPs, you may also use numeric VERSION fields, containing version numbers that are incremented by jOOQ upon store() calls. @@ -11295,7 +11295,7 @@ book2.store();]]>

    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:

    - + books = create.fetch(BOOK); @@ -11311,7 +11311,7 @@ create.batchStore(books);]]>

    - +
    CRUD SPI: RecordListener @@ -11322,11 +11322,11 @@ create.batchStore(books);]]>
  • Adding a central ID generation algorithm, generating UUIDs for all of your records.
  • Adding a central record initialisation mechanism, preparing the database prior to inserting a new record.
  • - +

    An example of such a RecordListener is given here:

    - + - +

    Now, configure jOOQ's runtime to load your listener

    @@ -11366,7 +11366,7 @@ DSLContext create = DSL.using(configuration);]]>

    If you're using jOOQ's , you can configure it to generate and DAOs for you. jOOQ then generates one DAO per , i.e. per table with a single-column primary key. Generated DAOs implement a common jOOQ type called . This type contains the following methods:

    - + corresponds to the DAO's related table //

    corresponds to the DAO's related generated POJO type // corresponds to the DAO's related table's primary key type. @@ -11377,23 +11377,23 @@ public interface DAO, P, T> { void insert(P object) throws DataAccessException; void insert(P... objects) throws DataAccessException; void insert(Collection

    objects) throws DataAccessException; - + // These methods allow for updating POJOs based on their primary key void update(P object) throws DataAccessException; void update(P... objects) throws DataAccessException; void update(Collection

    objects) throws DataAccessException; - + // These methods allow for deleting POJOs based on their primary key void delete(P... objects) throws DataAccessException; void delete(Collection

    objects) throws DataAccessException; void deleteById(T... ids) throws DataAccessException; void deleteById(Collection ids) throws DataAccessException; - + // These methods allow for checking record existence boolean exists(P object) throws DataAccessException; boolean existsById(T id) throws DataAccessException; long count() throws DataAccessException; - + // These methods allow for retrieving POJOs by primary key or by some other field List

    findAll() throws DataAccessException; P findById(T id) throws DataAccessException; @@ -11422,7 +11422,7 @@ public class BookDao extends DAOImpl {

    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:

    - +

    Note how the lambda expression receives a new, derived configuration that should be used within the local scope:

    - + { // Wrap configuration in a new DSLContext: DSL.using(configuration).insertInto(...); DSL.using(configuration).insertInto(...); - + // Or, reuse the new DSLContext within the transaction scope: DSLContext ctx = DSL.using(configuration); ctx.insertInto(...); ctx.insertInto(...); - + // ... but avoid using the scope from outside the transaction: create.insertInto(...); create.insertInto(...); }); ]]> - +

    - While some implementations (e.g. ones based on ThreadLocals, e.g. Spring or JTA) may allow you to reuse the globally scoped reference, the jOOQ transaction API design allows for TransactionProvider implementations that require your transactional code to use the new, locally scoped Configuration, instead. + While some implementations (e.g. ones based on ThreadLocals, e.g. Spring or JTA) may allow you to reuse the globally scoped reference, the jOOQ transaction API design allows for TransactionProvider implementations that require your transactional code to use the new, locally scoped Configuration, instead.

    @@ -11643,7 +11643,7 @@ class SpringTransaction implements Transaction {

    With jOOQ, it's simple. All of jOOQ's exceptions are "system exceptions", hence they are all unchecked.

    - +

    jOOQ's DataAccessException

    jOOQ uses its own to wrap any underlying that might have occurred. Note that all methods in jOOQ that may cause such a DataAccessException document this both in the Javadoc as well as in their method signature. @@ -11659,7 +11659,7 @@ class SpringTransaction implements Transaction {

  • InvalidResultException: An operation was performed expecting only one result, but several results were returned.
  • MappingException: Something went wrong when loading a record from a or when mapping a record into a POJO
  • - +

    Override jOOQ's exception handling

    The following section about documents means of overriding jOOQ's exception handling, if you wish to deal separately with some types of constraint violations, or if you raise business errors from your database, etc. @@ -11676,7 +11676,7 @@ class SpringTransaction implements Transaction {

    For convenience and better backwards-compatibility, consider extending instead of implementing this interface.

    - +

    Example: Query statistics ExecuteListener

    Here is a sample implementation of an ExecuteListener, that is simply counting the number of queries per type that are being executed using jOOQ: @@ -11693,11 +11693,11 @@ public class StatisticsListener extends DefaultExecuteListener { public void start(ExecuteContext ctx) { synchronized (STATISTICS) { Integer count = STATISTICS.get(ctx.type()); - + if (count == null) { count = 0; } - + STATISTICS.put(ctx.type(), count + 1); } } @@ -11740,7 +11740,7 @@ for (ExecuteType type : ExecuteType.values()) {

    Please read the for more details

    - +

    Example: Custom Logging ExecuteListener

    The following depicts an example of a custom ExecuteListener, which pretty-prints all queries being executed by jOOQ to stdout: @@ -11763,7 +11763,7 @@ public class PrettyPrinter extends DefaultExecuteListener { // Create a new DSLContext for logging rendering purposes // This DSLContext doesn't need a connection, only the SQLDialect... DSLContext create = DSL.using(ctx.dialect(), - + // ... and the flag for pretty-printing new Settings().withRenderFormatted(true)); @@ -11771,12 +11771,12 @@ public class PrettyPrinter extends DefaultExecuteListener { if (ctx.query() != null) { System.out.println(create.renderInlined(ctx.query())); } - + // If we're executing a routine else if (ctx.routine() != null) { System.out.println(create.renderInlined(ctx.routine())); } - + // If we're executing anything else (e.g. plain SQL) else if (!StringUtils.isBlank(ctx.sql())) { System.out.println(ctx.sql()); @@ -11786,12 +11786,12 @@ public class PrettyPrinter extends DefaultExecuteListener {

    See also the manual's sections about for more sample implementations of actual ExecuteListeners.

    - +

    Example: Bad query execution ExecuteListener

    You can also use ExecuteListeners to interact with your SQL statements, for instance when you want to check if executed or statements contain a WHERE clause. This can be achieved trivially with the following sample ExecuteListener:

    - + 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:

    - + @@ -11843,7 +11843,7 @@ public class DeleteOrUpdateWithoutWhereException extends RuntimeException {}

    With the above configuration, let's fetch some data with jOOQ

    - +

    @@ -11891,7 +11891,7 @@ Finishing : Total: 4.814ms, +3.375ms

  • 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
  • - +

    Optimise wisely

    Don't be put off by the above paragraphs. You should optimise wisely, i.e. only in places where you really need very high throughput to your database. jOOQ's overhead compared to plain JDBC is typically less than 1ms per query. @@ -11948,7 +11948,7 @@ Finishing : Total: 4.814ms, +3.375ms

    You need to tell jOOQ some things about your database connection. Here's an example of how to do it for an Oracle database

    - + @@ -11957,7 +11957,7 @@ Finishing : Total: 4.814ms, +3.375ms jdbc:oracle:thin:@[your jdbc connection parameters] [your database user] [your database password] - + user[db-user] @@ -11969,9 +11969,9 @@ Finishing : Total: 4.814ms, +3.375ms org.jooq.util.oracle.OracleDatabase @@ -12005,9 +12005,9 @@ Finishing : Total: 4.814ms, +3.375ms Use the pipe to separate several expressions) Watch out for case-sensitivity. Depending on your database, this might be important! - + You can create case-insensitive regular expressions using this syntax: (?i:expr) - + Whitespace is ignored and comments are possible. --> .* @@ -12038,7 +12038,7 @@ Finishing : Total: 4.814ms, +3.375ms @@ -12059,13 +12059,13 @@ Finishing : Total: 4.814ms, +3.375ms

    Code generation works by calling this class with the above property file as argument.

    - + org.jooq.util.GenerationTool /jooq-config.xml

    Be sure that these elements are located on the classpath:

    - +
    • The XML configuration file
    • jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar
    • @@ -12090,7 +12090,7 @@ Finishing : Total: 4.814ms, +3.375ms
    • this example uses jOOQ's log4j support by adding log4j.xml and log4j.jar to the project classpath.
    • the actual jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar artefacts may contain version numbers in the file names.
    - +
    Eclipse configuration
    @@ -12192,7 +12192,7 @@ Finishing : Total: 4.814ms, +3.375ms

    - +
    Running the code generator with Ant @@ -12203,14 +12203,14 @@ Finishing : Total: 4.814ms, +3.375ms - - + ]]> @@ -12229,7 +12229,7 @@ Finishing : Total: 4.814ms, +3.375ms generate-sources - @@ -12241,7 +12241,7 @@ Finishing : Total: 4.814ms, +3.375ms - + @@ -12255,7 +12255,7 @@ Finishing : Total: 4.814ms, +3.375ms ]]>
    - +
    Running the code generator with Gradle @@ -12263,7 +12263,7 @@ Finishing : Total: 4.814ms, +3.375ms

    We recommend using the Gradle plugin by Etienne Studer (from Gradle Inc.). It provides a concise DSL that allows you to tune all configuration properties supported by each jOOQ version. Please direct any support questions or issues you may find directly to the third party plugin vendor.

    - +

    Alternatively, the XML MarkupBuilder can be used

    If you don't want to use the above third party plugin, there's also the possibility to use jOOQ's standalone code generator for simplicity. The following working example build.gradle script should work out of the box: @@ -12395,9 +12395,9 @@ org.jooq.util.GenerationTool.generate( false @@ -12410,7 +12410,7 @@ org.jooq.util.GenerationTool.generate( production schema. Use this to override your local development schema name for source code generation. If not specified, this will be the same as the input-schema. - + This will be ignored if outputSchemaToDefault is set to true --> [your database schema / owner / name] @@ -12519,30 +12519,30 @@ org.jooq.util.GenerationTool.generate( false - + true - + false ]]> @@ -12551,7 +12551,7 @@ org.jooq.util.GenerationTool.generate(

    Some of the above properties depend on other properties to work correctly. For instance, when generating immutable pojos, pojos must be generated. jOOQ will enforce such properties even if you tell it otherwise. Here is a list of property interdependencies:

    - +
    • When daos = true, then jOOQ will set relations = true
    • When daos = true, then jOOQ will set records = true
    • @@ -12560,7 +12560,7 @@ org.jooq.util.GenerationTool.generate(
    - +
    Programmatic generator configuration @@ -12568,7 +12568,7 @@ org.jooq.util.GenerationTool.generate(

    In the previous sections, we have covered how to set up jOOQ's code generator using XML, either by running a standalone Java application, or by using Maven. However, it is also possible to use jOOQ's GenerationTool programmatically. The XSD file used for the configuration (http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd) is processed using XJC to produce Java artefacts. The below example uses those artefacts to produce the equivalent configuration of the previous :

    - +

    For the above example, you will need all of jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, and jooq-codegen-{jooq-version}.jar, on your classpath.

    - +

    Manually loading the XML file

    - +

    Alternatively, you can also load parts of the configuration from an XML file using JAXB and programmatically modify other parts using the code generation API:

    - + org.h2.Driver ]]> - +

    Load the above using standard JAXB API:

    - +

    - +
    Custom generator strategies @@ -12641,7 +12641,7 @@ GeberationTool.generate(configuration);]]>

    jOOQ allows you to override default implementations of the code generator or the generator strategy. Specifically, the latter can be very useful if you want to inject custom behaviour into jOOQ's code generator with respect to naming classes, members, methods, and other Java objects.

    - + @@ -12866,58 +12866,58 @@ public class Book implements java.io.Serializable { - + MY_SCHEMA - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - +
    - + MY_TABLE - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomBaseClasscom.example.MyOptionalCustomInterface
    - + - + MY_FIELD - + --> MatcherRule --> MatcherRule @@ -12925,30 +12925,30 @@ public class Book implements java.io.Serializable { --> MatcherRule - + - + MY_ROUTINE - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + - + MY_SEQUENCE - + --> MatcherRule @@ -12964,19 +12964,19 @@ public class Book implements java.io.Serializable { CAMEL - + PREFIX_$0_SUFFIX ]]> - +

    Some examples

    The following example shows a matcher strategy that adds a "T_" prefix to all table classes and to table identifiers: @@ -12987,7 +12987,7 @@ public class Book implements java.io.Serializable { - + UPPER @@ -13022,13 +13022,13 @@ public class Book implements java.io.Serializable { ]]> - +

    For more information about each XML tag, please refer to the http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd XSD file.

    - +
    Custom code sections @@ -13075,7 +13075,7 @@ public class Book implements java.io.Serializable {

    Any of the below methods can be overridden:

    - + Tables.java: This file contains all table objects in the form of static member references to the actual singleton object
  • UDTs.java: This file contains all UDT objects in the form of static member references to the actual singleton object
  • - +

    Referencing global artefacts

    When referencing global artefacts from your client application, you would typically static import them as such:

    - + @@ -13171,7 +13171,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate a implementation that looks like this:

    - + { // The singleton instance @@ -13187,7 +13187,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE) public Book as(java.lang.String alias) { return new Book(alias); } - + // [...] }]]> @@ -13206,7 +13206,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)
  • instanceFields: This flag controls the "static" keyword on table columns, as well as aliasing convenience
  • records: The generated record type is referenced from tables allowing for type-safe single-table record fetching
  • - +

    Flags controlling table generation

    Table generation cannot be deactivated @@ -13220,7 +13220,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate an implementation that looks like this:

    - + - +

    Flags influencing generated records

    These flags from the influence generated records: @@ -13278,7 +13278,7 @@ implements IBook {

  • interfaces: If interfaces are generated, records will implement them
  • jpaAnnotations: JPA annotations are used on generated records
  • - +

    Flags controlling record generation

    Record generation can be deactivated using the records flag @@ -13292,7 +13292,7 @@ implements IBook {

    Every table in your database will generate a POJO implementation that looks like this:

    - + - +

    Flags influencing generated POJOs

    These flags from the influence generated POJOs: @@ -13341,7 +13341,7 @@ public class Book implements java.io.Serializable

  • jpaAnnotations: JPA annotations are used on generated records
  • validationAnnotations: JSR-303 validation annotations are used on generated records
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the pojos flag @@ -13355,16 +13355,16 @@ public class Book implements java.io.Serializable

    Every table in your database will generate an interface that looks like this:

    - + - +

    Flags influencing generated interfaces

    These flags from the influence generated interfaces: @@ -13373,7 +13373,7 @@ public class Book implements java.io.Serializable

  • dateAsTimestamp: This influences all relevant getters and setters
  • unsignedTypes: This influences all relevant getters and setters
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the interfaces flag @@ -13388,7 +13388,7 @@ public class Book implements java.io.Serializable

    Every table in your database will generate a implementation that looks like this:

    - + { // Generated constructors @@ -13412,10 +13412,10 @@ public class Book implements java.io.Serializable public List fetchByAuthorId(Integer... values) { return fetch(BOOK.AUTHOR_ID, values); } - + // [...] }]]> - +

    Flags controlling DAO generation

    DAO generation can be activated using the daos flag @@ -13429,13 +13429,13 @@ public class Book implements java.io.Serializable

    Every sequence in your database will generate a implementation that looks like this:

    - + S_AUTHOR_ID = new SequenceImpl("S_AUTHOR_ID", TEST, SQLDataType.INTEGER); }]]> - +

    Flags controlling sequence generation

    Sequence generation cannot be deactivated @@ -13473,7 +13473,7 @@ public class Book implements java.io.Serializable public BigDecimal getResult() { return getValue(RESULT); } - + // [...] }]]> @@ -13495,7 +13495,7 @@ public class Book implements java.io.Serializable

    Every UDT in your database will generate a implementation that looks like this:

    - + { // The singleton UDT instance @@ -13508,10 +13508,10 @@ public class Book implements java.io.Serializable createField("CITY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); public static final UDTField COUNTRY = createField("COUNTRY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); - + // [...] }]]> - +

    Besides the implementation, a implementation is also generated

    @@ -13526,7 +13526,7 @@ public class Book implements java.io.Serializable public String getCity() {...} public void setCountry(String value) {...} public String getCountry() {...} - + // [...] }]]>
    @@ -13555,20 +13555,20 @@ public class Book implements java.io.Serializable BOOLEAN .*\.IS_VALID - + .* @@ -13599,7 +13599,7 @@ public class Book implements java.io.Serializable GregorianCalendar - + java.util.GregorianCalendar @@ -13615,21 +13615,21 @@ public class Book implements java.io.Serializable GregorianCalendar .*\.DATE_OF_.* - + .* @@ -13663,15 +13663,15 @@ create.selectFrom(AUTHOR)
    - - + +
    Custom data type binding

    The previous section discussed the case where your custom data type is mapped onto a standard JDBC type as contained in . In some cases, however, you want to map your own type onto a type that is not explicitly supported by JDBC, such as for instance, PostgreSQL's various advanced data types like JSON or HSTORE, or PostGIS types. For this, you can register an for relevant columns in your code generator. Consider the following trivial implementation of a binding for PostgreSQL's JSON data type, which binds the JSON string in PostgreSQL to a Google GSON object:

    - + {

    The above implementation intercepts all the interaction on a JDBC level, such that jOOQ will never need to know how to crrectly serialise / deserialise your custom data type. Similar to what we've seen in the previous section about , we can now register such a binding to the code generator. Note that you will reuse the same types of XML elements (<customType/> and <forcedType/>):

    - + JsonElement - + com.google.gson.JsonElement @@ -13781,26 +13781,26 @@ public class PostgresJSONGsonBinding implements Binding { JsonElement .*JSON.* - + .* -]]> +]]>

    See also the section about to learn about an alternative use of <forcedTypes/>. @@ -13820,7 +13820,7 @@ public class PostgresJSONGsonBinding implements Binding {

    - +
    Mapping generated schemata and tables @@ -13841,23 +13841,23 @@ public class PostgresJSONGsonBinding implements Binding {
    - +
    Code generation for large schemas

    Databases can become very large in real-world applications. This is not a problem for jOOQ's code generator, but it can be for the Java compiler. jOOQ generates some classes for . These classes can hit two sorts of limits of the compiler / JVM:

    - +
    • Methods (including static / instance initialisers) are allowed to contain only 64kb of bytecode.
    • Classes are allowed to contain at most 64k of constant literals
    - +

    While there exist workarounds for the above two limitations (delegating initialisations to nested classes, inheriting constant literals from implemented interfaces), the preferred approach is either one of these:

    - +
    • Distribute your database objects in several schemas. That is probably a good idea anyway for such large databases
    • to exclude excess database objects
    • @@ -13940,11 +13940,11 @@ public class PostgresJSONGsonBinding implements Binding {

      When writing unit tests for your data access layer, you have probably used some generic mocking tool offered by popular providers like Mockito, jmock, mockrunner, or even DBUnit. With jOOQ, you can take advantage of the built-in JDBC mock API that allows you to emulate a simple database on the JDBC level for precisely those SQL/JDBC use cases supported by jOOQ.

      - +

      - Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider. + Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider.

      - +

      Mocking the JDBC API

      JDBC is a very complex API. It takes a lot of time to write a useful and correct mock implementation, implementing at least these interfaces: @@ -13957,16 +13957,16 @@ public class PostgresJSONGsonBinding implements Binding {

    - +

    Optionally, you may even want to implement interfaces, such as , , , and many others. In addition to the above, you might need to find a way to simultaneously support incompatible JDBC minor versions, such as 4.0, 4.1

    - +

    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 :

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    As you can see, the configuration setup is simple. Now, the MockDataProvider acts as your single point of contact with JDBC / jOOQ. It unifies any of these execution modes, transparently:

    - +
    • Statements without results
    • Statements without results but with generated keys
    • @@ -13989,16 +13989,16 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
    • Batch statements with single queries and multiple bind value sets
    • Batch statements with multiple queries and no bind values
    - +

    The above are the execution modes supported by jOOQ. Whether you're using any of jOOQ's various fetching modes (e.g. , , , ) is irrelevant, as those modes are all built on top of the standard JDBC API.

    - +

    Implementing MockDataProvider

    Now, here's how to implement MockDataProvider:

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc // 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 String sql = ctx.sql(); - + // Exceptions are propagated through the JDBC and jOOQ APIs if (sql.toUpperCase().startsWith("DROP")) { throw new SQLException("Statement not supported: " + sql); } - + // You decide, whether any given statement returns results, and how many else if (sql.toUpperCase().startsWith("SELECT")) { - + // Always return one author record Result result = create.newResult(AUTHOR); result.add(create.newRecord(AUTHOR)); @@ -14026,12 +14026,12 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc result.get(0).setValue(AUTHOR.LAST_NAME, "Orwell"); mock[0] = new MockResult(1, result); } - + // You can detect batch statements easily else if (ctx.batch()) { // [...] } - + return mock; } }]]> @@ -14043,17 +14043,17 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • : The number of affected rows
  • : The result set
  • - +

    You should return as many MockResult objects as there were query executions (in ) or results (in ). Instead of an awkward JDBC ResultSet, however, you can construct a "friendlier" with your own record types. The jOOQ mock API will use meta data provided with this Result in order to create the necessary JDBC

    - +

    See the for a list of rules that you should follow.

    - +
    SQL 2 jOOQ Parser @@ -14063,20 +14063,20 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    Gudu Software Ltd has been selling enterprise quality SQL software to hundreds of customers to help them migrate from one database to another using the General SQL Parser. Now you can take advantage of their knowledge to parse your SQL statements and transform them directly into jOOQ statements using a free trial version of SQL 2 jOOQ!

    - +

    It's as simple as this!

    - +
    • Create a JDBC connection
    • Create a new SQL2jOOQ converter object
    • Convert your SQL code
    • Get the result
    - +

    See it in action:

    - + If all goes well, the above program yields:

    - + > result = create.select( Actor.ACTOR.FIRST_NAME, Actor.ACTOR.LAST_NAME ) @@ -14140,21 +14140,21 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    Please take note of the fact that the sql2jooq library is Open Source, but it depends on the commercial gsp.jar parser, whose trial licensing terms can be seen here:

    - +

    https://github.com/sqlparser/sql2jooq/blob/master/sql2jooq/LICENSE-GSQLPARSER.txt

    - +

    For more information about the General SQL Parser, please refer to the product blog.

    - +

    Please report any issues, ideas, wishes to the jOOQ user group or the sql2jooq GitHub project.

    - +
    jOOQ Console @@ -14202,7 +14202,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • Sybase Adaptive Server Enterprise 15.5
  • Sybase SQL Anywhere 12
  • - +

    For an up-to-date list of currently supported RDBMS, please refer to http://www.jooq.org/legal/licensing/#databases.

    @@ -14223,7 +14223,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME, This chapter should document the most important notes about SQL, JDBC and jOOQ data types.

    - +
    BLOBs and CLOBs @@ -14233,7 +14233,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    Unsigned integer types @@ -14257,7 +14257,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
    - +
    INTERVAL data types @@ -14268,11 +14268,11 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • YEAR TO MONTH: This interval type models a number of months and years
  • DAY TO SECOND: This interval type models a number of days, hours, minutes, seconds and milliseconds
  • - +

    Both interval types ship with a variant of subtypes, such as DAY TO HOUR, HOUR TO SECOND, etc. jOOQ models these types as Java objects extending : (where Number.intValue() corresponds to the absolute number of months) and (where Number.intValue() corresponds to the absolute number of milliseconds)

    - +

    Interval arithmetic

    In addition to the documented previously, interval arithmetic is also supported by jOOQ. Essentially, the following operations are supported: @@ -14287,7 +14287,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    XML data types @@ -14296,7 +14296,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    Geospacial data types @@ -14306,7 +14306,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    CURSOR data types @@ -14315,22 +14315,22 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    > cursor;]]> - +

    In fact, such a cursor will be fetched immediately by jOOQ and wrapped in an object.

    - +
    ARRAY and TABLE data types

    The SQL standard specifies ARRAY data types, that can be mapped to Java arrays as such:

    - + intArray;]]> - +

    The above array type is supported by these SQL dialects:

    @@ -14339,33 +14339,33 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • HSQLDB
  • Postgres
  • - +

    Oracle typed arrays

    Oracle has strongly-typed arrays and table types (as opposed to the previously seen anonymously typed arrays). These arrays are wrapped by types.

    - +
    Oracle DATE data type

    - Oracle's DATE data type does not conform to the SQL standard. It is really a TIMESTAMP(0), i.e. a TIMESTAMP with a fractional second precision of zero. The most appropriate JDBC type for Oracle DATE types is . + Oracle's DATE data type does not conform to the SQL standard. It is really a TIMESTAMP(0), i.e. a TIMESTAMP with a fractional second precision of zero. The most appropriate JDBC type for Oracle DATE types is .

    - +

    Performance implications

    - +

    When binding TIMESTAMP variables to SQL statements, instead of truncating such variables to DATE, the cost based optimiser may choose to widen the database column from DATE to TIMESTAMP using an Oracle INTERNAL_FUNCTION(), which prevents index usage. Details about this behaviour can be seen in this Stack Overflow question.

    - +

    Use a data type binding to work around this issue

    - +

    The best way to work around this issue is to implement a , which generates the CAST expression for every bind variable:

    - + ctx) throws SQLException { render.keyword("cast").sql('(') @@ -14374,15 +14374,15 @@ public final void sql(BindingSQLContext ctx) throws SQLException { }]]>

    Deprecated functionality

    - +

    Historic versions of jOOQ used to support a <dateAsTimestamp/> flag, which can be used with the out-of-the-box as a :

    - + true - + @@ -14401,7 +14401,7 @@ public final void sql(BindingSQLContext ctx) throws SQLException {

    For more information, please refer to . -

    +

    @@ -14413,12 +14413,12 @@ public final void sql(BindingSQLContext ctx) throws SQLException {

    jOOQ takes SQL as an external domain-specific language and maps it onto Java, creating an internal domain-specific language. Internal DSLs cannot 100% implement their external language counter parts, as they have to adhere to the syntax rules of their host or target language (i.e. Java). This section explains the various problems and workarounds encountered and implemented in jOOQ.

    - +

    SQL allows for "keywordless" syntax

    SQL syntax does not always need keywords to form expressions. The clause takes various argument assignments:

    - + UPDATE t SET a = 1, b = 2 update(t).set(a, 1).set(b, 2) @@ -14436,12 +14436,12 @@ public final void sql(BindingSQLContext ctx) throws SQLException {

    In this case, ROW is an actual (optional) SQL keyword, implemented by at least PostgreSQL.

    - +

    SQL contains "composed" keywords

    As most languages, SQL does not attribute any meaning to whitespace. However, whitespace is important when forming "composed" keywords, i.e. SQL clauses composed of several keywords. jOOQ follows standard Java method naming conventions to map SQL keywords (case-insensitive) to Java methods (case-sensitive, camel-cased). Some examples:

    - + GROUP BY ORDER BY @@ -14454,7 +14454,7 @@ whenMatchedThenUpdate()

    Future versions of jOOQ may use all-uppercased method names in addition to the camel-cased ones (to prevent collisions with Java keywords):

    - + GROUP BY ORDER BY @@ -14485,7 +14485,7 @@ WHEN_MATCHED_THEN_UPDATE()

    The above example omits THEN and END keywords in Java. Future versions of jOOQ may comprise a more complete DSL, including such keywords again though, to provide a more 1:1 match for the SQL language.

    - +

    SQL contains "superfluous" syntactic elements

    Some SQL constructs are hard to map to Java, but they are also not really necessary. SQL often expects syntactic parentheses where they wouldn't really be needed, or where they feel slightly inconsistent with the rest of the SQL language. @@ -14522,7 +14522,7 @@ WHEN_MATCHED_THEN_UPDATE()

    jOOQ replaces those keywords by "synonyms":

    - + CASE .. ELSE PIVOT .. FOR .. IN .. @@ -14550,7 +14550,7 @@ pivot(..).on(..).in(..)

    Most SQL operators have to be mapped to descriptive method names in Java, as Java does not allow operator overloading:

    - + , != @@ -14579,7 +14579,7 @@ set(a, b)

    This is less of a syntactic SQL feature than a semantic one. In SQL, objects can be referenced before (i.e. "lexicographically before") they are declared. This is particularly true for

    - + @@ -14590,7 +14590,7 @@ select(t.a).from(t)]]>

    A more sophisticated example are common table expressions (CTE), which are currently not supported by jOOQ:

    - + WITH t(a, b) AS ( SELECT 1, 2 FROM DUAL ) @@ -14602,7 +14602,7 @@ FROM t

    - +
    jOOQ's BNF pseudo-notation @@ -14611,7 +14611,7 @@ FROM t

    - +
    Quality Assurance @@ -14623,16 +14623,16 @@ FROM t
  • To add lots of type-safety to your inline SQL
  • To increase productivity when writing inline SQL using your favourite IDE's autocompletion capabilities
  • - +

    With jOOQ being in the core of your application, you want to be sure that you can trust jOOQ. That is why jOOQ is heavily unit and integration tested with a strong focus on integration tests:

    - +

    Unit tests

    Unit tests are performed against dummy JDBC interfaces using http://jmock.org/. These tests verify that various implementations render correct SQL and bind variables correctly.

    - +

    Integration tests

    This is the most important part of the jOOQ test suites. Some 1500 queries are currently run against a standard integration test database. Both the test database and the queries are translated into every one of the 14 supported SQL dialects to ensure that regressions are unlikely to be introduced into the code base. @@ -14643,17 +14643,17 @@ FROM t

    jOOQ integration tests run the weirdest and most unrealistic queries. As a side-effect of these extensive integration test suites, many corner-case bugs for JDBC drivers and/or open source databases have been discovered, feature requests submitted through jOOQ and reported mainly to CUBRID, Derby, H2, HSQLDB.

    - +

    Code generation tests

    For every one of the 14 supported integration test databases, source code is generated and the tiniest differences in generated source code can be discovered. In case of compilation errors in generated source code, new test tables/views/columns are added to avoid regressions in this field.

    - +

    API Usability tests and proofs of concept

    jOOQ is used in jOOQ-meta as a proof of concept. This includes complex queries such as the following Postgres query

    - + These rather complex queries show that the jOOQ API is fit for advanced SQL use-cases, compared to the rather simple, often unrealistic queries in the integration test suite.

    - +

    Clean API and implementation. Code is kept DRY

    As a general rule of thumb throughout the jOOQ code, everything is kept DRY. Some examples: @@ -14719,19 +14719,19 @@ for (Record record : create.select(

    - +
    Migrating to jOOQ 3.0

    This section is for all users of jOOQ 2.x who wish to upgrade to the next major release. In the next sub-sections, the most important changes are explained. Some code hints are also added to help you fix compilation errors.

    - +

    Type-safe row value expressions

    Support for has been added in jOOQ 2.6. In jOOQ 3.0, many API parts were thoroughly (but often incompatibly) changed, in order to provide you with even more type-safety.

    - +

    Here are some affected API parts:

    @@ -14741,11 +14741,11 @@ for (Record record : create.select(
  • IN predicates and comparison predicates taking subselects changed incompatibly
  • INSERT and MERGE statements now take typesafe VALUES() clauses
  • - +

    Some hints related to row value expressions:

    - + record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result> result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch(); @@ -14753,31 +14753,31 @@ Result> result = create.select(BOOK.TITLE, BOOK.ID).fro // But Record2 extends Record. You don't have to use the additional typesafety: Record record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch();]]> - +

    SelectQuery and SelectXXXStep are now generic

    In order to support type-safe row value expressions and type-safe Record[N] types, SelectQuery is now generic: SelectQuery<R>

    - +

    SimpleSelectQuery and SimpleSelectXXXStep API were removed

    The duplication of the SELECT API is no longer useful, now that SelectQuery and SelectXXXStep are generic.

    - +

    Factory was split into DSL (query building) and DSLContext (query execution)

    The pre-existing Factory class has been split into two parts:

    - +
    1. 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
    2. 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 renamed to DSLContext. An example:

    - + - +

    Quantified comparison predicates

    Field.equalAny(...) and similar methods have been removed in favour of Field.equal(any(...)). This greatly simplified the Field API. An example:

    - + > subselect = any(select(BOOK.ID).from(BOOK)); Condition condition = BOOK.ID.equal(subselect);]]> - +

    FieldProvider

    The FieldProvider marker interface was removed. Its methods still exist on FieldProvider subtypes. Note, they have changed names from getField() to field() and from getIndex() to indexOf()

    - +

    GroupField

    GroupField has been introduced as a DSL marker interface to denote fields that can be passed to GROUP BY clauses. This includes all org.jooq.Field types. However, fields obtained from ROLLUP(), CUBE(), and GROUPING SETS() functions no longer implement Field. Instead, they only implement GroupField. An example:

    - + field1a = Factory.rollup(...); // OK Field field2a = Factory.one(); // OK @@ -14823,19 +14823,19 @@ GroupField field1b = DSL.rollup(...); // OK Field field1c = DSL.rollup(...); // Compilation error GroupField field2b = DSL.one(); // OK Field field2c = DSL.one(); // OK]]> - +

    NULL predicate

    Beware! Previously, Field.equal(null) was translated internally to an IS NULL predicate. This is no longer the case. Binding Java "null" to a comparison predicate will result in a regular comparison predicate (which never returns true). This was changed for several reasons:

    - +
    • To most users, this was a surprising "feature".
    • Other predicates didn't behave in such a way, e.g. the IN predicate, the BETWEEN predicate, or the LIKE predicate.
    • Variable binding behaved unpredictably, as IS NULL predicates don't bind any variables.
    • The generated SQL depended on the possible combinations of bind values, which creates unnecessary hard-parses every time a new unique SQL statement is rendered.
    - +

    Here is an example how to check if a field has a given value, without applying SQL's ternary NULL logic:

    @@ -14848,7 +14848,7 @@ Condition condition1 = BOOK.TITLE.equal(possiblyNull); // jOOQ 3.0 Condition condition2 = BOOK.TITLE.equal(possiblyNull).or(BOOK.TITLE.isNull().and(val(possiblyNull).isNull())); Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    Configuration

    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 @@ -14862,7 +14862,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> In order to resolve confusion that used to arise because of different lifecycle durations, these types are now no longer formally connected through inheritance.

    - +

    ConnectionProvider

    In order to allow for simpler connection / data source management, jOOQ externalised connection handling in a new ConnectionProvider type. The previous two connection modes are maintained backwards-compatibly (JDBC standalone connection mode, pooled DataSource mode). Other connection modes can be injected using: @@ -14872,24 +14872,24 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    These are some side-effects of the above change

    - +
    • 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. This resolves many class loader issues that were encountered before. It also helps listener implementations control their lifecycles themselves.

    - +

    Data type API

    The data type API has been changed drastically in order to enable some new DataType-related features. These changes include: @@ -14899,16 +14899,16 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]>[SQLDialect]DataType and SQLDataType no longer implement DataType. They're mere constant containers

  • Various minor API changes have been done.
  • - +

    Object renames

    These objects have been moved / renamed:

    - +
    • jOOU: a library used to represent unsigned integer types was moved from org.jooq.util.unsigned to org.jooq.util.types (which already contained INTERVAL data types)
    - +

    Feature removals

    Here are some minor features that have been removed in jOOQ 3.0 @@ -15002,7 +15002,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> --> diff --git a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.6.xml b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.6.xml index 60dfb26862..54c9d06745 100644 --- a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.6.xml +++ b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.6.xml @@ -126,7 +126,7 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ's reason for being - compared to SQL / JDBC

    So why not just use SQL? @@ -149,14 +149,14 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ is different

    SQL was never meant to be abstracted. To be confined in the narrow boundaries of heavy mappers, hiding the beauty and simplicity of relational data. SQL was never meant to be object-oriented. SQL was never meant to be anything other than... SQL!

    - + - +
    Getting started with jOOQ @@ -345,12 +345,12 @@ limitations under the License.

    This section helps you correctly interpret this manual in the context of jOOQ.

    - +

    Code blocks

    The following are code blocks:

    - + @@ -366,7 +366,7 @@ org.jooq.property=value]]>

    These are useful to provide examples in code. Often, with jOOQ, it is even more useful to compare SQL code with its corresponding Java/jOOQ code. When this is done, the blocks are aligned side-by-side, with SQL usually being on the left, and an equivalent jOOQ DSL query in Java usually being on the right:

    - + @@ -378,17 +378,17 @@ create.selectOne().fetch()]]>

    The contents of code blocks follow conventions, too. If nothing else is mentioned next to any given code block, then the following can be assumed:

    - - + + - +

    Your naming may differ, of course. For instance, you could name the "create" instance "db", instead.

    - +

    Execution

    - +

    When you're coding PL/SQL, T-SQL or some other procedural SQL language, SQL statements are always executed immediately at the semi-colon. This is not the case in jOOQ, because as an internal DSL, jOOQ can never be sure that your statement is complete until you call fetch() or execute(). The manual tries to apply fetch() and execute() as thoroughly as possible. If not, it is implied:

    @@ -428,7 +428,7 @@ create.update(T).set(T.V, 1).execute();]]>

    jOOQ allows to override runtime behaviour using . If nothing is specified, the default runtime settings are assumed.

    - +

    Sample database

    jOOQ query examples run against the sample database. See the manual's section about to learn more about the sample database. @@ -463,7 +463,7 @@ CREATE TABLE book ( title VARCHAR2(400) NOT NULL, published_in NUMBER(7) NOT NULL, language_id NUMBER(7) NOT NULL, - + CONSTRAINT fk_book_author FOREIGN KEY (author_id) REFERENCES author(id), CONSTRAINT fk_book_language FOREIGN KEY (language_id) REFERENCES language(id) ); @@ -476,7 +476,7 @@ CREATE TABLE book_to_book_store ( name VARCHAR2(400) NOT NULL, book_id INTEGER NOT NULL, stock INTEGER, - + PRIMARY KEY(name, book_id), CONSTRAINT fk_b2bs_book_store FOREIGN KEY (name) REFERENCES book_store (name) ON DELETE CASCADE, CONSTRAINT fk_b2bs_book FOREIGN KEY (book_id) REFERENCES book (id) ON DELETE CASCADE @@ -487,7 +487,7 @@ CREATE TABLE book_to_book_store (

    In addition to the above, you may assume the following sample data:

    - + Effectively, jOOQ was originally designed to replace any other database abstraction framework short of the ones handling connection pooling (and more sophisticated )

    - +

    Use jOOQ the way you prefer

    ... but open source is community-driven. And the community has shown various ways of using jOOQ that diverge from its original intent. Some use cases encountered are: @@ -546,7 +546,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]>Using jOOQ for SQL building and Spring Data for SQL execution

  • Using jOOQ without the to build the basis of a framework for dynamic SQL execution.
  • - +

    The following sections explain about various use cases for using jOOQ in your application.

    @@ -559,7 +559,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]> This is the most simple of all use cases, allowing for construction of valid SQL for any database. In this use case, you will not use and probably not even . Instead, you'll use to wrap strings, literals and other user-defined objects into an object-oriented, type-safe AST modelling your SQL statements. An example is given here:

    - + - +

    The SQL string built with the jOOQ query DSL can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools (note that since jOOQ uses PreparedStatement by default, this will generate a bind variable for "1948". ).

    @@ -596,7 +596,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID)) .where(BOOK.PUBLISHED_IN.equal(1948)) .getSQL();]]> - +

    The SQL string that you can generate as such can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools.

    @@ -616,7 +616,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    Instead of any tool mentioned in the previous chapters, you can also use jOOQ directly to execute your jOOQ-generated SQL statements. This will add a lot of convenience on top of the previously discussed API for typesafe SQL construction, when you can re-use the information from generated classes to fetch records and custom data types. An example is given here:

    - + > result = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) @@ -670,10 +670,10 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { // Skip previously distinguished authors if ((int) author.getDistinguished() == 1) continue; - + // Check if the author has written more than 5 books if (author.fetchChildren(Keys.FK_BOOK_AUTHOR).size() > 5) { - + // Mark the author as a "distinguished" author author.setDistinguished(1); author.store(); @@ -690,7 +690,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {
    - +
    jOOQ for PROs @@ -728,7 +728,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { This manual section is intended for new users, to help them get a running application with jOOQ, quickly.

    - +
    Step 1: Preparation @@ -737,7 +737,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { If you haven't already downloaded it, download jOOQ:
    http://www.jooq.org/download

    - +

    Alternatively, you can create a Maven dependency to download jOOQ artefacts:

    @@ -760,7 +760,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    Note that only the jOOQ Open Source Edition is available from Maven Central. If you're using the jOOQ Professional Edition or the jOOQ Enterprise Edition, you will have to manually install jOOQ in your local Nexus, or in your local Maven cache. For more information, please refer to the licensing pages.

    - +

    Please refer to the manual's section about to learn how to use jOOQ's code generator with Maven.

    @@ -775,14 +775,14 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    - +
    Step 2: Your database

    We're going to create a database called "library" and a corresponding "author" table. Connect to MySQL via your command line client and type the following:

    - + CREATE DATABASE `library`; USE `library`; @@ -796,7 +796,7 @@ CREATE TABLE `author` (
    - +
    Step 3: Code generation @@ -808,7 +808,7 @@ CREATE TABLE `author` (

    The easiest way to generate a schema is to copy the jOOQ jar files (there should be 3) and the MySQL Connector jar file to a temporary directory. Then, create a library.xml that looks like this:

    - + @@ -865,7 +865,7 @@ CREATE TABLE `author` (

    generator.target.directory - the directory to output to.

    - +

    Once you have the JAR files and library.xml in your temp directory, type this on a Windows machine:

    @@ -885,7 +885,7 @@ CREATE TABLE `author` (

    Note: jOOQ will try loading the library.xml from your classpath. This is also why there is a trailing period (.) on the classpath. If the file cannot be found on the classpath, jOOQ will look on the file system from the current working directory.

    - +

    Replace the filenames with your actual filenames. In this example, jOOQ {jooq-version} is being used. If everything has worked, you should see this in your console output:

    @@ -947,17 +947,17 @@ INFO: Packages fetched : 0 (0 included, 0 excluded) Nov 1, 2011 7:25:08 PM org.jooq.impl.JooqLogger info INFO: GENERATION FINISHED! : Total: 791.688ms, +9.143ms - +
    - +
    Step 4: Connect to your database

    Let's just write a vanilla main class in the project containing the generated classes:

    - +
    - +
    Step 5: Querying

    Let's add a simple query constructed with jOOQ's query DSL:

    - + result = create.select().from(AUTHOR).fetch();]]> @@ -1007,7 +1007,7 @@ Result result = create.select().from(AUTHOR).fetch();]]>

    - +
    Step 6: Iterating @@ -1026,7 +1026,7 @@ Result result = create.select().from(AUTHOR).fetch();]]>

    The full program should now look like this:

    - +
    - +
    Step 7: Explore! @@ -1122,7 +1122,7 @@ public class Main {
  • Another example using Spring and Guice for transaction management can be downloaded from GitHub.
  • Another, excellent tutorial by Petri Kainulainen can be found here.
  • - +

    Add the required Maven dependencies

    For this example, we'll create the following Maven dependencies @@ -1201,7 +1201,7 @@ public class Main {

    The above dependencies are configured together using a Spring Beans configuration:

    - + - + - + @@ -1259,7 +1259,7 @@ public class Main { - + ]]> @@ -1310,7 +1310,7 @@ public class QueryTest {

    The following example shows how you can use Spring's TransactionManager to explicitly handle transactions:

    - +
    - +
    Using jOOQ with Flyway

    Flyway - Database Migrations Made EasyWhen performing database migrations, we at Data Geekery recommend using jOOQ with Flyway - Database Migrations Made Easy. In this chapter, we're going to look into a simple way to get started with the two frameworks.

    - +

    Philosophy

    - +

    There are a variety of ways how jOOQ and Flyway could interact with each other in various development setups. In this tutorial we're going to show just one variant of such framework team play - a variant that we find particularly compelling for most use cases.

    - +

    The general philosophy behind the following approach can be summarised as this:

    - +
    • 1. Database increment
    • 2. Database migration
    • 3. Code re-generation
    • 4. Development
    - +

    The four steps above can be repeated time and again, every time you need to modify something in your database. More concretely, let's consider:

    - +
    • 1. Database increment - You need a new column in your database, so you write the necessary DDL in a Flyway script
    • 2. Database migration - This Flyway script is now part of your deliverable, which you can share with all developers who can migrate their databases with it, the next time they check out your change
    • @@ -1456,15 +1456,15 @@ public class TransactionTest { ]]>

      0. Maven Project Configuration - Dependencies

      - +

      While jOOQ and Flyway could be used in standalone migration scripts, in this tutorial, we'll be using Maven for the standard project setup. You will also find the source code of this tutorial on GitHub at https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-flyway-example, and the full pom.xml file here.

      - +

      These are the dependencies that we're using in our Maven configuration:

      - + org.jooq @@ -1797,14 +1797,14 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre;

    - +
    Using jOOQ with JAX-RS

    In some use-cases, having a lean, single-tier server-side architecture is desirable. Typically, such architectures expose a RESTful API implementing client code and the UI using something like AngularJS.

    - +

    In Java, the standard API for RESTful applications is JAX-RS, which is part of JEE 7, along with a standard JSON implementation. But you can use JAX-RS also outside of a JEE container. The following example shows how to set up a simple license server using these technologies:

    @@ -1817,9 +1817,9 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre;

    For the example, we'll use a PostgreSQL database.

    - +

    Creating the license server database

    - +

    We'll keep the example simple and use a LICENSE table to store all license keys and associated information, whereas a LOG_VERIFY table is used to log access to the license server. Here's the DDL:

    @@ -1831,7 +1831,7 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre; LICENSEE TEXT NOT NULL, -- The e-mail address of the licensee LICENSE TEXT NOT NULL, -- The license key VERSION VARCHAR(50) NOT NULL DEFAULT '.*', -- The licensed version(s), a regular expression - + CONSTRAINT PK_LICENSE PRIMARY KEY (ID), CONSTRAINT UK_LICENSE UNIQUE (LICENSE) ); @@ -1844,7 +1844,7 @@ CREATE TABLE LICENSE_SERVER.LOG_VERIFY ( REQUEST_IP VARCHAR(50) NOT NULL, -- The request IP verifying the license VERSION VARCHAR(50) NOT NULL, -- The version that is being verified MATCH BOOLEAN NOT NULL, -- Whether the verification was successful - + CONSTRAINT PK_LOG_VERIFY PRIMARY KEY (ID) );]]> @@ -1866,13 +1866,13 @@ $$ LANGUAGE PLPGSQL;

    The actual algorithm might be using a secret salt to hash the function arguments. For the sake of a tutorial, a constant string will suffice.

    - +

    Setting up the project

    - +

    We're going to be setting up the

    - + 9966 - + org.jooq jooq-codegen-maven @@ -1938,7 +1938,7 @@ $$ LANGUAGE PLPGSQL; servlet-api 2.5 - + org.jooq jooq @@ -1960,13 +1960,13 @@ $$ LANGUAGE PLPGSQL;

    With the above setup, we're now pretty ready to start developing our license service as a JAX-RS service.

    - +

    The license service class

    - +

    Once we've run the , we can write the following service class:

    - + /license/verify checks if a given licensee has access to version using a license. * @@ -2026,7 +2026,7 @@ public class LicenseService { @Override public String run(DSLContext ctx) { String v = (version == null || version.equals("")) ? "" : version; - + // Use the jOOQ query DSL API to generate a log entry return ctx.insertInto(LOG_VERIFY) @@ -2047,10 +2047,10 @@ public class LicenseService { } }); } - + // [...] }]]> - +

    The INSERT INTO LOG_VERIFY query is actually rather interesting. In plain SQL, it would look like this:

    @@ -2075,7 +2075,7 @@ RETURNING MATCH;]]> */ private String run(CtxRunnable runnable) { Connection c = null; - + try { Class.forName("org.postgresql.Driver"); c = getConnection("jdbc:postgresql:postgres", "postgres", System.getProperty("pw", "test")); @@ -2083,7 +2083,7 @@ RETURNING MATCH;]]> .set(new DefaultConnectionProvider(c)) .set(SQLDialect.POSTGRES) .set(new Settings().withExecuteLogging(false))); - + return runnable.run(ctx); } catch (Exception e) { @@ -2095,13 +2095,13 @@ RETURNING MATCH;]]> JDBCUtils.safeClose(c); } } - + private interface CtxRunnable { String run(DSLContext ctx); }]]>

    Configuring Spring and Jetty

    - +

    All we need now is to configure Spring...

    @@ -2159,7 +2159,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/sch

    Using the license server

    - +

    You can now use the license server at the following URLs

    @@ -2176,7 +2176,7 @@ http://localhost:8088/jooq-jax-rs-example/license/verify?mail=test@example.com&l

    Let's verify what happened, in the database:

    - + - +

    Downloading the complete example

    - +

    The complete example can be downloaded for free and under the terms of the Apache Software License 2.0 from here:
    https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-jax-rs-example @@ -2206,21 +2206,21 @@ select * from license_server.log_verify

    - +
    jOOQ and Java 8

    Java 8 has introduced a great set of enhancements, among which lambda expressions and the new Streams API. These new constructs align very well with jOOQ's fluent API as can be seen in the following examples:

    - +

    jOOQ and lambda expressions

    jOOQ's API is fully Java-8-ready, which basically means that it is a SAM (Single Abstract Method) type, which can be instanciated using a lambda expression. Consider this example:

    - + - +

    The above example shows how jOOQ's method can receive a lambda expression that implements to map from jOOQ to your custom types.

    - +

    jOOQ and the Streams API

    @@ -2281,7 +2281,7 @@ select * from license_server.log_verify // Just emit a CREATE TABLE statement System.out.println( "CREATE TABLE " + table + " ("); - + // Map each "Column" type into a String // containing the column specification, // and join them using comma and @@ -2292,15 +2292,15 @@ select * from license_server.log_verify " " + col.type) .collect(Collectors.joining(",\n")) ); - + System.out.println(");"); } );]]> - +

    The above example is explained more in depth in this blog post: http://blog.jooq.org/2014/04/11/java-8-friday-no-more-need-for-orms/. For more information about Java 8, consider these resources:

    - +
    - +
    jOOQ and Nashorn

    With Java 8 and the new built-in JavaScript engine Nashorn, a whole new ecosystem of software can finally make easy use of jOOQ in server-side JavaScript. A very simple example can be seen here:

    - +

    - More details about how to use jOOQ, JDBC, and SQL with Nashorn can be seen here. + More details about how to use jOOQ, JDBC, and SQL with Nashorn can be seen here.

    - +
    jOOQ and Scala @@ -2533,7 +2533,7 @@ print(
  • Type inference using "var" and "val" keywords
  • Lambda expressions and for-comprehension syntax for record iteration and data type conversion
  • - +

    But jOOQ also leverages other useful Scala features, such as

    @@ -2541,15 +2541,15 @@ print(
  • implicit defs for operator overloading
  • Scala Macros (soon to come)
  • - +

    All of the above heavily improve jOOQ's querying DSL API experience for Scala developers.

    - +

    A short example jOOQ application in Scala might look like this:

    - +
    - - + +
    jOOQ and Groovy @@ -2615,7 +2615,7 @@ object Test { //

    A short example jOOQ application in Groovy might look like this:

    - +
    - +
    jOOQ and NoSQL @@ -2668,7 +2668,7 @@ DSL.using(sql.connection)

    - +
    Dependencies @@ -2686,7 +2686,7 @@ DSL.using(sql.connection)
    - +
    Build your own @@ -2715,7 +2715,7 @@ DSL.using(sql.connection)
    - +
    jOOQ and backwards-compatibility @@ -2727,7 +2727,7 @@ DSL.using(sql.connection)
  • If a minor release includes backwards-compatible, API-relevant new features, [Y] is incremented by one and [Z] is reset to zero.
  • If a major release includes backwards-incompatible, API-relevant new features, [X] is incremented by one and [Y], [Z] are reset to zero.
  • - +

    jOOQ's understanding of backwards-compatibility

    Backwards-compatibility is important to jOOQ. You've chosen jOOQ as a strategic SQL engine and you don't want your SQL to break. That is why there is at most one major release per year, which changes only those parts of jOOQ's API and functionality, which were agreed upon on the user group. During the year, only minor releases are shipped, adding new features in a backwards-compatible way @@ -2740,15 +2740,15 @@ DSL.using(sql.connection)

  • Overloading methods for convenience
  • Changing the type hierarchy of interfaces
  • - +

    It becomes obvious that it would be impossible to add new language elements (e.g. new , new ) to the API without breaking any client code that actually implements those interfaces. Hence, the following rule should be observed:

    - +

    jOOQ's DSL interfaces should not be implemented by client code! Extend only those extension points that are explicitly documented as "extendable" (e.g. )

    - +

    jOOQ-codegen and jOOQ-meta

    While a reasonable amount of care is spent to maintain these two modules under the rules of semantic versioning, it may well be that minor releases introduce backwards-incompatible changes. This will be announced in the respective release notes and should be the exception. @@ -2776,7 +2776,7 @@ DSL.using(sql.connection) - +

    The query DSL type @@ -2807,7 +2807,7 @@ DSL.using(sql.connection) // ... which is in fact the same as: DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    DSL subclasses @@ -2826,7 +2826,7 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME));
    - + @@ -2835,14 +2835,14 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    The DSLContext class

    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.

    - +

    Fluent creation of a DSLContext object

    The DSLContext object can be created fluently from the : @@ -2857,7 +2857,7 @@ DSLContext create = DSL.using(connection, dialect);]]>

    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

    A Configuration can be supplied with these objects: @@ -2876,7 +2876,7 @@ DSLContext create = DSL.using(connection, dialect);]]> - +

    Wrapping a Configuration object, a DSLContext can construct , for later . An example is given here:

    @@ -2918,7 +2918,7 @@ DSL.using(connection, dialect) CONNECT BY clause to the query */ -@Support({ SQLDialect.CUBRID, SQLDialect.}) +@Support({ SQLDialect.CUBRID, SQLDialect.ORACLE }) SelectConnectByConditionStep connectBy(Condition condition);]]>

    @@ -2940,7 +2940,7 @@ SelectSelectStep select(Field... fields);]]>

    Nevertheless, the IS DISTINCT FROM predicate is supported by jOOQ in all dialects, as its semantics can be expressed with an equivalent . For more details, see the manual's section about the .

    - +

    jOOQ and the Oracle SQL dialect

    Oracle SQL is much more expressive than many other SQL dialects. It features many unique keywords, clauses and functions that are out of scope for the SQL standard. Some examples for this are @@ -2964,13 +2964,13 @@ SelectSelectStep select(Field... fields);]]>

    In jOOQ 3.1, the notion of a SQLDialect.family() was introduced, in order to group several similar into a common family. An example for this is SQL Server, which is supported by jOOQ in various versions:

    - +
    • : The "version-less" SQL Server version. This always maps to the latest supported version of SQL Server
    • : The SQL Server version 2012
    • : The SQL Server version 2008
    - +

    In the above list, SQLSERVER is both a dialect and a family of three dialects. This distinction is used internally by jOOQ to distinguish whether to use the clause (SQL Server 2012), or whether to emulate it using ROW_NUMBER() OVER() (SQL Server 2008).

    @@ -2987,7 +2987,7 @@ SelectSelectStep select(Field... fields);]]>

    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.

    - +

    Interact with JDBC DataSources

    If you're in a J2EE or Spring context, however, you may wish to use a instead. Connections obtained from such a DataSource will be closed after query execution by jOOQ. The semantics of such a close operation should be the returning of the connection into a connection pool, not the actual closing of the underlying connection. Typically, this makes sense in an environment using distributed JTA transactions. An example of using DataSources with jOOQ can be seen in the tutorial section about . @@ -2995,17 +2995,17 @@ SelectSelectStep select(Field... fields);]]>

    Note, in this case, jOOQ will internally use a , which you can reference directly if you prefer that.

    - +

    Inject custom behaviour

    If your specific environment works differently from any of the above approaches, you can inject your own custom implementation of a ConnectionProvider into jOOQ. This is the API contract you have to fulfil:

    - + @@ -3015,19 +3015,19 @@ 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...

    - +
    - +

    Here is an example of how to use the custom data API. Let's assume that you have written an , that prevents INSERT statements, when a given flag is set to true:

    @@ -3037,10 +3037,10 @@ public class NoInsertListener extends DefaultExecuteListener { @Override public void start(ExecuteContext ctx) { - + // This listener is active only, when your custom flag is set to true 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) { throw new DataAccessException("No INSERT statements allowed"); @@ -3051,11 +3051,11 @@ public class NoInsertListener extends DefaultExecuteListener {

    See the manual's section about to learn more about how to implement an ExecuteListener.

    - +

    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:

    - + ExecuteListeners are a useful tool to...

    - +
    • implement custom logging
    • apply triggers written in Java
    • collect query execution statistics
    - +

    ExecuteListeners are hooked into your by returning them from an :

    @@ -3113,7 +3113,7 @@ configuration.set( new DefaultExecuteListenerProvider(new PerformanceLoggingListener()), new DefaultExecuteListenerProvider(new NoInsertListener()) );]]>
    - +

    See the manual's section about to see examples of such listener implementations.

    @@ -3157,22 +3157,22 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - +

    All Settings

    - +

    This section of the manual explains all the available Settings flags as available from the XSD specification.

    - + false - + ... @@ -3183,17 +3183,17 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - UPPER_CASED : UPPER - lower_cased : LOWER - CasedAsReportedByTheDatabase : AS_IS - + Defaults to "QUOTED" --> LOWER UPPER - + false @@ -3201,54 +3201,54 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - question marks : INDEXED - named parameters : NAMED - inlined values : INLINED - + Defaults to "INDEXED". - + This value is overridden by statementType == STATIC_STATEMENT, in case of which, this defaults to INLINED --> INDEXED - + PREPARED_STATEMENT - + true false true false ]]> - +

    More details

    - +

    Please refer to the jOOQ runtime configuration XSD for more details:
    http://www.jooq.org/xsd/jooq-runtime-{runtime-xsd-version}.xsd

    - +
    Runtime schema and table mapping @@ -3256,7 +3256,7 @@ DSLContext create = DSL.using(connection, dialect, settings);]]>

    You may wish to design your database in a way that you have several instances of your schema. This is useful when you want to cleanly separate data belonging to several customers / organisation units / branches / users and put each of those entities' data in a separate database or schema.

    - +

    In our AUTHOR example this would mean that you provide a book reference database to several companies, such as My Book World and Books R Us. In that case, you'll probably have a schema setup like this:

    @@ -3286,7 +3286,7 @@ create.selectFrom(AUTHOR).fetch();

    The query executed with a Configuration equipped with the above mapping will in fact produce this SQL statement:

    - + SELECT * FROM MY_BOOK_WORLD.AUTHOR

    Even if AUTHOR was generated from DEV. @@ -3361,7 +3361,7 @@ create.selectFrom(AUTHOR).fetch();

    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

    @@ -3395,7 +3395,7 @@ create.selectFrom(AUTHOR).fetch();

    Here is an example to illustrate what that means:

    - + 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) @@ -3467,7 +3467,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); @@ -3494,7 +3494,7 @@ query.addJoin(BOOK, BOOK.AUTHOR_ID.equal(AUTHOR.ID));]]>

    Note, that for historic reasons, the DSL API mixes mutable and immutable behaviour with respect to the internal representation of the being constructed. While creating , (such as functions) assumes immutable behaviour, creating does not. In other words, the following can be said:

    - + select2 = create.selectOne().fetch();]]>

    jOOQ does not explicitly support the asterisk operator in projections. However, you can omit the projection as in these examples:

    - +

    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:

    - + select(Collection> fields); public static SelectSelectStep select(Field... fields); @@ -3776,14 +3776,14 @@ public static SelectSelectStep> select(Field SelectSelectStep> select(Field field1, Field field2); public static SelectSelectStep> select(Field field1, Field field2, Field field3); // [...]]]> - +

    Since the generic R type is bound to some , the associated T type information can be used in various other contexts, e.g. the . Such a SELECT statement can be assigned typesafely:

    > s1 = create.select(BOOK.ID, BOOK.TITLE); Select> s2 = create.select(BOOK.ID, trim(BOOK.TITLE));]]> - +

    For more information about typesafe record types with degree up to {max-row-degree}, see the manual's section about .

    @@ -3809,7 +3809,7 @@ create.selectOne().from(BOOK.as("b"), AUTHOR.as("a")).fetch();]]>

    Read more about aliasing in the manual's section about .

    - +

    More advanced table expressions

    Apart from simple tables, you can pass any arbitrary to the jOOQ FROM clause. This may include in Oracle: @@ -3865,11 +3865,11 @@ DSL.using(SQLDialect.POSTGRES).selectOne().fetch();]]>

  • NATURAL LEFT [ OUTER ] JOIN
  • NATURAL RIGHT [ OUTER ] JOIN
  • - +

    Besides, jOOQ also supports

    - +
    • CROSS APPLY (T-SQL and Oracle 12c specific)
    • OUTER APPLY (T-SQL and Oracle 12c specific)
    • @@ -4002,7 +4002,7 @@ ON BOOK.AUTHOR_ID = AUTHOR.ID

      T-SQL has long known what the SQL standard calls lateral derived tables, lateral joins using the APPLY keyword. To every row resulting from the table expression on the left, we apply the table expression on the right. This is extremely useful for table-valued functions, which are also supported by jOOQ. Some examples:

      - + - +

      The above example shows standard usage of the LATERAL keyword to connect a derived table to the previous table in the . A similar statement can be written in T-SQL:

      - + - +

      LATERAL JOIN or CROSS APPLY are particularly useful together with , which are also supported by jOOQ.

      @@ -4154,12 +4154,12 @@ ORDER BY 1

      Note that this syntax is also supported in the CUBRID database and might be emulated in other dialects supporting common table expressions in the future.

      - +

      ORDER SIBLINGS

      The Oracle database allows for specifying a SIBLINGS keyword in the . Instead of ordering the overall result, this will only order siblings among each other, keeping the hierarchy intact. An example is given here:

      - + - +
    @@ -4203,7 +4203,7 @@ GROUP BY AUTHOR_ID

    Note, as defined in the SQL standard, when grouping, you may no longer project any columns that are not a formal part of the GROUP BY clause, or .

    - +

    MySQL's deviation from the SQL standard

    MySQL has a peculiar way of not adhering to this standard behaviour. This is documented in the MySQL manual. In short, with MySQL, you can also project any other field that is not part of the GROUP BY clause. The projected values will just be arbitrary values from within the group. You cannot rely on any ordering. For example: @@ -4238,7 +4238,7 @@ GROUP BY () .groupBy() .fetch();]]> - +

    ROLLUP(), CUBE() and GROUPING SETS()

    Some databases support the SQL standard grouping functions and some extensions thereof. See the manual's section about for more details. @@ -4259,7 +4259,7 @@ FROM BOOK GROUP BY AUTHOR_ID HAVING COUNT(*) >= 2 ]]>  -= 4

    - +
    The WINDOW clause

    The SQL:2003 standard as well as PostgreSQL and Sybase SQL Anywhere support a WINDOW clause that allows for specifying WINDOW frames for reuse in and .

    - +   - +

    Note that in order to create such a window definition, we need to first create a using .

    Even if only PostgreSQL and Sybase SQL Anywhere natively support this great feature, jOOQ can emulate it by expanding any and types that you pass to the window() method - if the database supports window functions at all.

    - +

    Some more information about and the WINDOW clause can be found on our blog: http://blog.jooq.org/2013/11/03/probably-the-coolest-sql-feature-window-functions/

    @@ -4457,8 +4457,8 @@ ORDER BY CASE TITLE

    The SQL standard defines that a "query expression" can be ordered, and that query expressions can contain , whose subqueries cannot be ordered. While this is defined as such in the SQL standard, many databases allowing for the in one way or another, do not adhere to this part of the SQL standard. Hence, jOOQ allows for ordering all SELECT statements, regardless whether they are constructed as a part of a UNION or not. Corner-cases are handled internally by jOOQ, by introducing synthetic subselects to adhere to the correct syntax, where this is needed.

    - - + +

    Oracle's ORDER SIBLINGS BY clause

    jOOQ also supports Oracle's SIBLINGS keyword to be used with ORDER BY clauses for @@ -4510,7 +4510,7 @@ SELECT TOP 1 * FROM BOOK

    Things get a little more tricky in those databases that have no native idiom for OFFSET pagination (actual queries may vary):

    - + 1]]>

    As you can see, jOOQ will take care of the incredibly painful ROW_NUMBER() OVER() (or ROWNUM for Oracle) filtering in subselects for you, you'll just have to write limit(1).offset(2) in any dialect.

    - +

    Side-note: If you're interested in understanding why we chose ROWNUM for Oracle, please refer to this very interesting benchmark, comparing the different approaches of doing pagination in Oracle: http://www.inf.unideb.hu/~gabora/pagination/results.html.

    @@ -4557,7 +4557,7 @@ WHERE RN > 1]]>

    - +
    The SEEK clause @@ -4567,7 +4567,7 @@ WHERE RN > 1]]>

    A much faster and more stable way to perform paging is the so-called keyset paging method also called seek method. jOOQ supports a synthetic seek() clause, that can be used to perform keyset paging. Imagine we have these data:

    - + 1]]>

    Now, if we want to display page 6 to the user, instead of going to page 6 by using a record OFFSET, we could just fetch the record strictly after the last record on page 5, which yields the values (533, 2). This is how you would do it with SQL or with jOOQ:

    - + As you can see, the jOOQ SEEK clause is a synthetic clause that does not really exist in SQL. However, the jOOQ syntax is far more intuitive for a variety of reasons:

    - +
    • It replaces OFFSET where you would expect
    • It doesn't force you to mix regular predicates with "seek" predicates
    • It is typesafe
    • It emulates for you, in those databases that do not support them
    - +

    This query now yields:

    - + Note that you cannot combine the SEEK clause with the OFFSET clause.

    - +

    More information about this great feature can be found in the jOOQ blog:

    @@ -4638,11 +4638,11 @@ LIMIT 5
  • http://blog.jooq.org/2013/10/26/faster-sql-paging-with-jooq-using-the-seek-method/
  • http://blog.jooq.org/2013/11/18/faster-sql-pagination-with-keysets-continued/
  • - +

    Further information about offset pagination vs. keyset pagination performance can be found on our partner page:

    - +
    No more offset @@ -4754,7 +4754,7 @@ SELECT * FROM author ORDER BY id DESC;]]>

    SQL allows to perform set operations as understood in standard set theory on result sets. These operations include unions, intersections, subtractions. For two subselects to be combinable by such a set operator, each subselect must return a of the same degree and type.

    - +

    UNION and UNION ALL

    These operators combine two results into one. While UNION removes all duplicate records resulting from this combination, UNION ALL leaves subselect results as they are. Typically, you should prefer UNION ALL over UNION, if you don't really need to remove duplicates. The following example shows how to use such a UNION operation in jOOQ. @@ -4769,12 +4769,12 @@ SELECT * FROM BOOK WHERE ID = 5 .unionAll( create.selectFrom(BOOK).where(BOOK.ID.equal(5))) .fetch();]]> - +

    INTERSECT [ ALL ] and EXCEPT [ ALL ]

    INTERSECT is the operation that produces only those values that are returned by both subselects. EXCEPT is the operation that returns only those values that are returned exclusively in the first subselect. Both operators will remove duplicates from their results. The SQL standard allows to specify the ALL keyword for both of these operators as well, but this is hardly supported in any database. jOOQ does not support INTERSECT ALL, EXEPT ALL operations either.

    - +

    jOOQ's set operators and how they're different from standard SQL

    As previously mentioned in the manual's section about the , jOOQ has slightly changed the semantics of these set operators. While in SQL, a subselect may not contain any or (unless you wrap the subselect into a ), jOOQ allows you to do so. In order to select both the youngest and the oldest author from the database, you can issue the following statement with jOOQ (rendered to the MySQL dialect): @@ -4795,7 +4795,7 @@ ORDER BY 1 .orderBy(AUTHOR.DATE_OF_BIRTH.desc()).limit(1)) .orderBy(1) .fetch();]]> - +

    In case your database doesn't support ordered UNION subselects, the subselects are nested in derived tables:

    @@ -4813,12 +4813,12 @@ SELECT * FROM ( ORDER BY 1]]> - +

    Projection typesafety for degrees between 1 and {max-row-degree}

    Two subselects that are combined by a set operator are required to be of the same degree and, in most databases, also of the same type. jOOQ 3.0's introduction of helps compile-checking these constraints:

    - + > s1 = select(BOOK.ID, BOOK.TITLE).from(BOOK); Select> s2 = selectOne(); @@ -4854,7 +4854,7 @@ s1.union(s4); // OK. The two Record[N] types match]]>

    Note that you can pass any string in the .hint() clause. If you use that clause, the passed string will always be put in between the SELECT [DISTINCT] keywords and the actual projection list. This can be useful in other databases too, such as MySQL, for instance:

    - +
    - +
    Lexical and logical SELECT clause order

    SQL has a lexical and a logical order of SELECT clauses. The lexical order of SELECT clauses is inspired by the English language. As SQL statements are commands for the database, it is natural to express a statement in an imperative tense, such as "SELECT this and that!".

    - +

    Logical SELECT clause order

    The logical order of SELECT clauses, however, does not correspond to the syntax. In fact, the logical order is this:

    - +
    • : First, all data sources are defined and joined
    • : Then, data is filtered as early as possible
    • @@ -4892,11 +4892,11 @@ FROM table1
    • : Then, a paging view is created for the ordered tuples
    • : Finally, pessimistic locking is applied
    - +

    The SQL Server documentation also explains this, with slightly different clauses:

    - +
    • FROM
    • ON
    • @@ -4910,16 +4910,16 @@ FROM table1
    • ORDER BY
    • TOP
    - +

    As can be seen, databases have to logically reorder a SQL statement in order to determine the best execution plan.

    - +

    Alternative syntaxes: LINQ, SLICK

    Some "higher-level" abstractions, such as C#'s LINQ or Scala's SLICK try to inverse the lexical order of SELECT clauses to what appears to be closer to the logical order. The obvious advantage of moving the SELECT clause to the end is the fact that the projection type, which is the record type returned by the SELECT statement can be re-used more easily in the target environment of the internal domain specific language.

    - +

    A LINQ example:

    @@ -4932,11 +4932,11 @@ Where p.UnitsInStock <= p.ReorderLevel AndAlso Not p.Discontinued // SELECT clause Select p]]> - +

    A SLICK example:

    - + INSERT statement is used to insert new records into a database table. The following sections describe the various operation modes of the jOOQ INSERT statement.

    - +
    INSERT .. VALUES - +

    INSERT .. VALUES with a single row

    Records can either be supplied using a VALUES() constructor, or a SELECT statement. jOOQ supports both types of INSERT statements. An example of an INSERT statement using a VALUES() constructor is given here: @@ -4994,7 +4994,7 @@ VALUES (100, 'Hermann', 'Hesse'); create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME); step.values("A", "B", "C"); // ^^^ Doesn't compile, the expected type is Integer]]> - +

    INSERT .. VALUES with multiple rows

    The SQL standard specifies that multiple rows can be supplied to the VALUES() constructor in an INSERT statement. Here's an example of a multi-record INSERT @@ -5032,14 +5032,14 @@ SELECT 101, 'Alfred', 'Döblin' FROM DUAL;

    - +
    INSERT .. DEFAULT VALUES

    A lesser-known syntactic feature of SQL is the INSERT .. DEFAULT VALUES statement, where a single record is inserted, containing only DEFAULT values for every row. It is written as such:

    - + create.insertInto(AUTHOR) .defaultValues() .execute(); - +

    This can make a lot of sense in situations where you want to "reserve" a row in the database for an subsequent within the same transaction. Or if you just want to send an event containing trigger-generated default values, such as IDs or timestamps.

    @@ -5057,18 +5057,18 @@ DEFAULT VALUES;

    -  create.insertInto( AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, ...) .values( - defaultValue(AUTHOR.ID), - defaultValue(AUTHOR.FIRST_NAME), + defaultValue(AUTHOR.ID), + defaultValue(AUTHOR.FIRST_NAME), defaultValue(AUTHOR.LAST_NAME), ...) .execute(); @@ -5077,7 +5077,7 @@ VALUES (

    - +
    INSERT .. SET @@ -5094,13 +5094,13 @@ VALUES ( .set(AUTHOR.FIRST_NAME, "Alfred") .set(AUTHOR.LAST_NAME, "Döblin") .execute(); - +

    As you can see, this syntax is a bit more verbose, but also more readable, as every field can be matched with its value. Internally, the two syntaxes are strictly equivalent. -

    +

    - +
    INSERT .. SELECT @@ -5108,22 +5108,22 @@ VALUES (

    In some occasions, you may prefer the INSERT SELECT syntax, for instance, when you copy records from one table to another:

    - + create.insertInto(AUTHOR_ARCHIVE) .select(selectFrom(AUTHOR).where(AUTHOR.DECEASED.isTrue())) .execute();
    - +
    INSERT .. ON DUPLICATE KEY

    The synthetic ON DUPLICATE KEY UPDATE clause

    - +

    The MySQL database supports a very convenient way to INSERT or UPDATE a record. This is a non-standard extension to the SQL syntax, which is supported by jOOQ and emulated in other RDBMS, where this is possible (i.e. if they support the SQL standard ). Here is an example how to use the ON DUPLICATE KEY UPDATE clause:

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, update the author's name create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -5133,11 +5133,11 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .execute();

    The synthetic ON DUPLICATE KEY IGNORE clause

    - +

    The MySQL database also supports an INSERT IGNORE INTO clause. This is supported by jOOQ using the more convenient SQL syntax variant of ON DUPLICATE KEY IGNORE, which can be equally emulated in other databases using a :

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, ignore the INSERT statement create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -5146,11 +5146,11 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .execute();
    - +
    INSERT .. RETURNING - +

    The Postgres database has native support for an INSERT .. RETURNING clause. This is a very powerful concept that is emulated for all other dialects using JDBC's method. Take this example:

    @@ -5230,7 +5230,7 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    jOOQ supports formal in various contexts, among which the UPDATE statement. Only one row value expression can be updated at a time. Here's an example:

    - + The above row value expressions usages are completely typesafe.

    - +

    UPDATE .. RETURNING

    The Firebird and Postgres databases support a RETURNING clause on their UPDATE statements, similar as the RETURNING clause in . This is useful to fetch trigger-generated values in one go. An example is given here:

    - + The H2 database ships with a somewhat less powerful but a little more intuitive syntax for its own version of the MERGE statement. An example more or less equivalent to the previous one can be seen here:

    - + -- Check if there is already an author called 'Hitchcock' -- If there is, rename him to John. If there isn't add him. @@ -5367,7 +5367,7 @@ VALUES ('John', 'Hitchcock') This syntax can be fully emulated by jOOQ for all other databases that support the SQL standard MERGE statement. For more information about the H2 MERGE syntax, see the documentation here:
    http://www.h2database.com/html/grammar.html#merge

    - +

    Typesafety of VALUES() for degrees up to {max-row-degree}

    Much like the , the MERGE statement's VALUES() clause provides typesafety for degrees up to {max-row-degree}, in both the standard syntax variant as well as the H2 variant. @@ -5473,7 +5473,7 @@ create.alterSequence(S_AUTHOR_ID).restartWith(n).execute();]]>

    - +
    The CREATE statement @@ -5485,7 +5485,7 @@ create.alterSequence(S_AUTHOR_ID).restartWith(n).execute();]]>

    Indexes

    - @@ -5561,7 +5561,7 @@ WHERE 50 < (
    - +
    The DROP statement @@ -5647,7 +5647,7 @@ create.dropViewIfExists(V_AUTHOR).execute();]]>

    Most of the times, when thinking about a you're probably thinking about an actual table in your database schema. If you're using jOOQ's , you will have all tables from your database schema available to you as type safe Java objects. You can then use these tables in SQL , or in other , just like any other table expression. An example is given here:

    - + - +

    The above example shows how AUTHOR and BOOK tables are joined in a . It also shows how you can access by dereferencing the relevant Java attributes of their tables.

    @@ -5700,11 +5700,11 @@ create.select() .and(a.FIRST_NAME.equal("Paulo"))) .orderBy(b.TITLE) .fetch();]]> - +

    As you can see in the above example, calling as() on generated tables returns an object of the same type as the table. This means that the resulting object can be used to dereference fields from the aliased table. This is quite powerful in terms of having your Java compiler check the syntax of your SQL statements. If you remove a column from a table, dereferencing that column from that table alias will cause compilation errors.

    - +

    Dereferencing columns from other table expressions

    Only few table expressions provide the SQL syntax typesafety as shown above, where generated tables are used. Most tables, however, expose their fields through field() methods: @@ -5716,12 +5716,12 @@ Table a = AUTHOR.as("a"); // Get fields from a: Field id = a.field("ID"); Field firstName = a.field("FIRST_NAME");]]> - +

    Derived column lists

    The SQL standard specifies how a table can be renamed / aliased in one go along with its columns. It references the term "derived column list" for the following syntax (as supported by Postgres, for instance):

    - + In jOOQ, you would simply specify a varargs list of column aliases as such:

    - + The that can be used in are the most powerful and best supported means of creating new in SQL. Informally, the following can be said:

    - + A(colA1, ..., colAn) "join" B(colB1, ..., colBm) "produces" C(colA1, ..., colAn, colB1, ..., colBm)

    @@ -5796,7 +5796,7 @@ create.select().from(values(

    jOOQ supports all of these JOIN types (except semi-join and anti-join) directly on any :

    - + table) @@ -5834,7 +5834,7 @@ Table naturalRightOuterJoin(TableLike)]]>

    Some databases allow for expressing in-memory temporary tables using a VALUES() constructor. This constructor usually works the same way as the VALUES() clause known from the or from the . With jOOQ, you can also use the VALUES() table constructor, to create tables that can be used in a :

    - + Note, that it is usually quite useful to provide column aliases ("derived column lists") along with the table alias for the VALUES() constructor.

    - +

    The above statement is emulated by jOOQ for those databases that do not support the VALUES() constructor, natively (actual emulations may vary):

    - + A can appear almost anywhere a can. Such a "nested SELECT" is often called a "derived table". Apart from many convenience methods accepting objects directly, a SELECT statement can always be transformed into a object using the asTable() method.

    - +

    Example: Scalar subquery

    - + If you are closely coupling your application to an Oracle database, you can take advantage of some Oracle-specific features, such as the PIVOT clause, used for statistical analyses. The formal syntax definition is as follows:

    - + -- SELECT .. FROM table PIVOT (aggregateFunction [, aggregateFunction] FOR column IN (expression [, expression])) -- WHERE .. - +

    The PIVOT clause is available from the type, as pivoting is done directly on a table. Currently, only Oracle's PIVOT clause is supported. Support for SQL Server's slightly different PIVOT clause will be added later. Also, jOOQ may emulate PIVOT for other dialects in the future.

    @@ -6026,7 +6026,7 @@ WHERE NOT EXISTS (

    The SQL standard specifies how SQL databases should implement ARRAY and TABLE types, as well as CURSOR types. Put simply, a CURSOR is a pointer to any materialised . Depending on the cursor's features, this table expression can be scrolled through in both directions, records can be locked, updated, removed, inserted, etc. Often, CURSOR types contain s, whereas ARRAY and TABLE types contain simple scalar values, although that is not a requirement

    - +

    ARRAY types in SQL are similar to Java's array types. They contain a "component type" or "element type" and a "dimension". This sort of ARRAY type is implemented in H2, HSQLDB and Postgres and supported by jOOQ as such. Oracle uses strongly-typed arrays, which means that an ARRAY type (VARRAY or TABLE type) has a name and possibly a maximum capacity associated with it.

    @@ -6049,7 +6049,7 @@ FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(null, null, 'ALLSTATS'));

    - +
    Table-valued functions @@ -6072,11 +6072,11 @@ BEGIN ORDER BY id RETURN END]]> - +

    The jOOQ code generator will now produce a from the above, which can be used as a SQL function:

    - + r1 = create.selectFrom(fBooks(null)).fetch(); @@ -6084,7 +6084,7 @@ Result r1 = create.selectFrom(fBooks(null)).fetch(); create.select(BOOK.ID, F_BOOKS.TITLE) .from(BOOK.crossApply(fBooks(BOOK.ID))) .fetch();]]> - +
    ¨ @@ -6158,12 +6158,12 @@ DSL.using(SQLDialect.SYBASE ).selectOne().getSQL();]]>

    Column expressions can be used in various SQL clauses in order to refer to one or several columns. This chapter explains how to form various types of column expressions with jOOQ. A particular type of column expression is given in the section about , where an expression may have a degree of more than one.

    - +

    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:

    - + field1 = BOOK.TITLE; @@ -6219,7 +6219,7 @@ ORDER BY BOOK.TITLE

    Just like , columns can be renamed using aliases. Here is an example:

    - + SELECT FIRST_NAME || ' ' || LAST_NAME author, COUNT(*) books FROM AUTHOR JOIN BOOK ON AUTHOR.ID = AUTHOR_ID @@ -6228,7 +6228,7 @@ GROUP BY FIRST_NAME, LAST_NAME;

    Here is how it's done with jOOQ:

    - + Record record = create.select( concat(AUTHOR.FIRST_NAME, val(" "), AUTHOR.LAST_NAME).as("author"), count().as("books")) @@ -6236,14 +6236,14 @@ GROUP BY FIRST_NAME, LAST_NAME; .join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID)) .groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .fetchAny(); - +

    When you alias Fields like above, you can access those Fields' values using the alias name:

    - + System.out.println("Author : " + record.getValue("author")); System.out.println("Books : " + record.getValue("books")); - +
    @@ -6256,7 +6256,7 @@ System.out.println("Books : " + record.getValue("books"));

    Sometimes, this automatic mapping might not be what you needed, or jOOQ cannot know the type of a field. In those cases you would write SQL type CAST like this:

    - + -- Let's say, your Postgres column LAST_NAME was VARCHAR(30) -- Then you could do this: SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL @@ -6264,27 +6264,27 @@ SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL

    in jOOQ, you can write something like that:

    - + create.select(TAuthor.LAST_NAME.cast(PostgresDataType.TEXT)).fetch();

    The same thing can be achieved by casting a Field directly to String.class, as TEXT is the default data type in Postgres to map to Java's String

    - + create.select(TAuthor.LAST_NAME.cast(String.class)).fetch(); - +

    The complete CAST API in consists of these three methods:

    - + { // Cast this field to the type of another field Field cast(Field field); - + // Cast this field to a given DataType Field cast(DataType type); - + // Cast this field to the default DataType for a given Class Field cast(Class type); } @@ -6307,14 +6307,14 @@ public class DSL {

    A slightly different use case than are data type coercions, which are not rendered through to generated SQL. Sometimes, you may want to pretend that a numeric value is really treated as a string value, for instance when binding a numeric :

    - + field1 = val(1).coerce(String.class); Field field2 = val("1").coerce(Integer.class);]]>

    In the above example, field1 will be treated by jOOQ as a Field<String>, binding the numeric literal 1 as a VARCHAR value. The same applies to field2, whose string literal "1" will be bound as an INTEGER value.

    - +

    This technique is better than performing unsafe or rawtype casting in Java, if you cannot access the "right" field type from any given expression.

    @@ -6334,15 +6334,15 @@ Field field2 = val("1").coerce(Integer.class);]]>

    In order to express a SQL query like this one:

    - + SELECT ((1 + 2) * (5 - 3) / 2) % 10 FROM DUAL - +

    You can write something like this in jOOQ:

    - + create.select(val(1).add(2).mul(val(5).sub(3)).div(2).mod(10)).fetch(); - +

    Operator precedence

    jOOQ does not know any operator precedence (see also ). All operations are evaluated from left to right, as with any object-oriented API. The two following expressions are the same: @@ -6370,14 +6370,14 @@ Field field2 = val("1").coerce(Integer.class);]]> - +

    String concatenation

    The SQL standard defines the concatenation operator to be an infix operator, similar to the ones we've seen in the chapter about . This operator looks like this: ||. Some other dialects do not support this operator, but expect a concat() function, instead. jOOQ renders the right operator / function, depending on your :

    - + SELECT 'A' || 'B' || 'C' FROM DUAL -- Or in MySQL: @@ -6405,13 +6405,13 @@ create.select(concat("A", "B", "C")).fetch();
  • NVL: Get the first non-null value among two arguments.
  • NVL2: Get the second argument if the first is null, or the third argument, otherwise.
  • - +

    Please refer to the for more details.

    - +
    Numeric functions @@ -6421,7 +6421,7 @@ create.select(concat("A", "B", "C")).fetch();

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ABS: Get the absolute value of a value.
    • ACOS: Get the arc cosine of a value.
    • @@ -6452,7 +6452,7 @@ create.select(concat("A", "B", "C")).fetch();
    • TANH: Get the hyperbolic tangent of a value.
    • TRUNC: Truncate the decimals off a given value.
    - +

    Please refer to the for more details.

    @@ -6477,13 +6477,13 @@ create.select(concat("A", "B", "C")).fetch();
  • SHL: Shift bits to the left
  • SHR: Shift bits to the right
  • - +

    Some background about bitwise operation emulation

    As stated before, not all databases support all of these bitwise operations. jOOQ emulates them wherever this is possible. More details can be seen in this blog post:
    http://blog.jooq.org/2011/10/30/the-comprehensive-sql-bitwise-operations-compatibility-list/

    - +
    @@ -6496,7 +6496,7 @@ create.select(concat("A", "B", "C")).fetch();

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ASCII: Get the ASCII code of a character.
    • BIT_LENGTH: Get the length of a string in bits.
    • @@ -6517,16 +6517,16 @@ create.select(concat("A", "B", "C")).fetch();
    • TRIM: Trim a string on both sides.
    • UPPER: Get a string in upper case letters.
    - +

    Please refer to the for more details.

    - +

    Regular expressions, REGEXP, REGEXP_LIKE, etc.

    Various databases have some means of searching through columns using regular expressions if the does not provide sufficient pattern matching power. While there are many different functions and operators in the various databases, jOOQ settled for the SQL:2008 standard REGEX_LIKE operator. Being an operator (and not a function), you should use the corresponding method on :

    - +

    @@ -6535,7 +6535,7 @@ create.select(concat("A", "B", "C")).fetch(); - +

    Case sensitivity with strings @@ -6548,20 +6548,20 @@ create.select(concat("A", "B", "C")).fetch();

    For these ad-hoc ordering use-cases, most people resort to using LOWER() or UPPER() as follows:

    - + -- Case-insensitive filtering: -SELECT * FROM BOOK +SELECT * FROM BOOK WHERE upper(TITLE) = 'ANIMAL FARM' -- Case-insensitive ordering: -SELECT * +SELECT * FROM AUTHOR ORDER BY upper(FIRST_NAME), upper(LAST_NAME) // Case-insensitive filtering: create.selectFrom(BOOK) .where(upper(BOOK.TITLE).eq("ANIMAL FARM")).fetch(); - + // Case-insensitive ordering: create.selectFrom(AUTHOR) .orderBy(upper(AUTHOR.FIRST_NAME), upper(AUTHOR.LAST_NAME)) @@ -6578,7 +6578,7 @@ create.selectFrom(AUTHOR)

    This is a list of date and time functions supported by jOOQ's :

    - +
    • CURRENT_DATE: Get current date as a DATE object.
    • CURRENT_TIME: Get current time as a TIME object.
    • @@ -6588,7 +6588,7 @@ create.selectFrom(AUTHOR)
    • TIMESTAMP_ADD: Add a number of days or an interval to a timestamp.
    • TIMESTAMP_DIFF: Get the difference as an INTERVAL DAY TO SECOND between two dates.
    - +

    Intervals in jOOQ

    jOOQ fills a gap opened by JDBC, which neglects an important SQL data type as defined by the SQL standards: INTERVAL types. See the manual's section about for more details. @@ -6740,7 +6740,7 @@ GROUP BY AUTHOR_ID WindowOverStep rank(); WindowOverStep denseRank(); WindowOverStep percentRank(); - + // Windowing functions WindowIgnoreNullsStep firstValue(Field field); WindowIgnoreNullsStep lastValue(Field field) @@ -6756,7 +6756,7 @@ GROUP BY AUTHOR_ID // Statistical functions WindowOverStep cumeDist(); WindowOverStep ntile(int number);]]> - +

    SQL distinguishes between various window function types (e.g. "ranking functions"). Depending on the function, SQL expects mandatory PARTITION BY or ORDER BY clauses within the OVER() clause. jOOQ does not enforce those rules for two reasons:

    @@ -6771,14 +6771,14 @@ GROUP BY AUTHOR_ID

    Here are some simple examples of window functions with jOOQ:

    - + -- Sample uses of ROW_NUMBER() ROW_NUMBER() OVER() ROW_NUMBER() OVER(PARTITION BY 1) ROW_NUMBER() OVER(ORDER BY BOOK.ID) ROW_NUMBER() OVER(PARTITION BY BOOK.AUTHOR_ID ORDER BY BOOK.ID) - + -- Sample uses of FIRST_VALUE FIRST_VALUE(BOOK.ID) OVER() FIRST_VALUE(BOOK.ID IGNORE NULLS) OVER() @@ -6789,14 +6789,14 @@ rowNumber().over() rowNumber().over().partitionByOne() rowNumber().over().partitionBy(BOOK.AUTHOR_ID) rowNumber().over().partitionBy(BOOK.AUTHOR_ID).orderBy(BOOK.ID) - + // Sample uses of firstValue() firstValue(BOOK.ID).over() firstValue(BOOK.ID).ignoreNulls().over() firstValue(BOOK.ID).respectNulls().over()
    - +

    An advanced window function example

    Window functions can be used for things like calculating a "running total". The following example fetches transactions and the running total for every transaction going back to the beginning of the transaction table (ordered by booked_at). Window functions are accessible from the previously seen type using the over() method: @@ -6824,7 +6824,7 @@ firstValue(BOOK.ID).respectNulls().over()

    In the previous chapter about , we have seen the concept of "ordered-set aggregate functions", such as Oracle's LISTAGG(). These functions have a window function / analytical function variant, as well. For example:

    - + SELECT LISTAGG(TITLE, ', ') WITHIN GROUP (ORDER BY TITLE) @@ -6909,7 +6909,7 @@ ORDER BY 1 NULLS LAST, 2 NULLS LAST

    In English, the ROLLUP() grouping function provides N+1 groupings, when N is the number of arguments to the ROLLUP() function. Each grouping has an additional group field from the ROLLUP() argument field list. The results of the second query might look something like this:

    - + GROUPING SETS() and other grouping functions:
    http://msdn.microsoft.com/en-us/library/bb510427(v=sql.105)

    - +

    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:

    - + ... fields); GroupField cube(Field... fields); @@ -7012,7 +7012,7 @@ Field groupingId(Field...);]]>

    MySQL and CUBRID don't know any grouping functions, but they support a WITH ROLLUP clause, that is equivalent to simple ROLLUP() grouping functions. jOOQ emulates ROLLUP() in MySQL and CUBRID, by rendering this WITH ROLLUP clause. The following two statements mean the same:

    - + Some databases support user-defined functions, which can be embedded in any SQL statement, if you're using jOOQ's . Let's say you have the following simple function in Oracle SQL:

    - + The above function will be made available from a generated class. You can use it like any other :

    - + - +

    Note that user-defined functions returning or data types can also be used wherever can be used, if they are

    @@ -7064,7 +7064,7 @@ END echo;

    Some databases support user-defined aggregate functions, which can then be used along with or as . An example for such a database is Oracle. With Oracle, you can define the following OBJECT type (the example was taken from the Oracle 11g documentation):

    - +

    jOOQ's will detect such aggregate functions and generate them differently from regular . They implement the type, as mentioned in the manual's section about . Here's how you can use the SECOND_MAX() aggregate function with jOOQ:

    - +
    - +
    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:

    - + Row1 row(T1 t1) { ... } public static Row2 row(T1 t1, T2 t2) { ... } @@ -7294,12 +7294,12 @@ public static RowN row(Object... values) { ... }]]>

    See the relevant sections for more details about how to use row value expressions in predicates.

    - +

    Using row value expressions in UPDATE statements

    The also supports a variant where row value expressions are updated, rather than single columns. See the relevant section for more details

    - +

    Higher-degree row value expressions

    jOOQ chose to explicitly support degrees up to {max-row-degree} to match Scala's typesafe tuple, function and product support. Unlike Scala, however, jOOQ also supports higher degrees without the additional typesafety. @@ -7323,7 +7323,7 @@ public static RowN row(Object... values) { ... }]]>

  • The of a
  • The 's ON clause
  • - +

    Boolean types in SQL

    Before SQL:1999, boolean types did not really exist in SQL. They were modelled by 0 and 1 numeric/char values. With SQL:1999, true booleans were introduced and are now supported by most databases. In short, these are possible boolean values: @@ -7419,7 +7419,7 @@ Condition combined2 = combined1.andNot(c); // The left-hand side of the AND NOT

    Here are all boolean operators on the interface:

    - + < to test for being strictly less
  • <= to test for being less or equal
  • - +

    Unfortunately, Java does not support operator overloading, hence these operators are also implemented as methods in jOOQ, like any other SQL syntax elements. The relevant parts of the interface are these:

    - + ); // = (some column expression) eq or equal(Select>); // = (some scalar SELECT statement) @@ -7481,12 +7481,12 @@ ge or greaterOrEqual(Select>); // >= (some scalar SELECT st

    Note that every operator is represented by two methods. A verbose one (such as equal()) and a two-character one (such as eq()). Both methods are the same. You may choose either one, depending on your taste. The manual will always use the more verbose one.

    - +

    jOOQ's convenience methods using comparison operators

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using comparison predicates:

    - +
    - +
    Boolean operator precedence @@ -7513,7 +7513,7 @@ BOOK.TITLE.notEqualIgnoreCase("animal farm")]]>

    In SQL, the two expressions wouldn't be the same, as SQL natively knows operator precedence.

    - + A AND B OR C AND D OR E -- Precedence is applied (((A AND B) OR C) AND D) OR E -- Precedence is overridden @@ -7527,7 +7527,7 @@ BOOK.TITLE.notEqualIgnoreCase("animal farm")]]>

    All variants of the that we've seen in the previous chapter also work for . If your database does not support row value expression comparison predicates, jOOQ emulates them the way they are defined in the SQL standard:

    - + (X, Y))]]>

    jOOQ supports all of the above row value expression comparison predicates, both with and at the right-hand side:

    - +
    - +
    Quantified comparison predicate @@ -7624,7 +7624,7 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    It is interesting to note that the SQL standard defines the in terms of the ANY-quantified predicate. The following two expressions are equivalent:

    - + @@ -7635,14 +7635,14 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    - +
    NULL predicate

    In SQL, you cannot compare NULL with any value using , as the result would yield NULL again, which is neither TRUE nor FALSE (see also the manual's section about ). In order to test a for NULL, use the NULL predicate as such:

    - + @@ -7680,7 +7680,7 @@ NOT((A, B) IS NOT NULL)]]>

    The SQL standard contains a nice truth table for the above rules:

    - + +-----------------------+-----------+---------------+---------------+-------------------+ | Expression | R IS NULL | R IS NOT NULL | NOT R IS NULL | NOT R IS NOT NULL | +-----------------------+-----------+---------------+---------------+-------------------+ @@ -7694,13 +7694,13 @@ NOT((A, B) IS NOT NULL)]]>

    In jOOQ, you would simply use the isNull() and isNotNull() methods on row value expressions. Again, as with the , the row value expression NULL predicate is emulated by jOOQ, if your database does not natively support it:

    - +
    - +
    DISTINCT predicate @@ -7727,7 +7727,7 @@ BOOK.TITLE.isNotDistinctFrom(BOOK.SUB_TITLE)]]>

    If your database does not natively support the DISTINCT predicate, jOOQ emulates it with an equivalent , modelling the above truth table:

    - + ... or better, if the INTERSECT set operation is supported:

    - + - +
    @@ -7768,7 +7768,7 @@ EXISTS(SELECT a INTERSECT SELECT b)

    The BETWEEN predicate can be seen as syntactic sugar for a pair of . According to the SQL standard, the following two predicates are equivalent:

    - + = [B] AND [A] <= [C]]]> @@ -7789,7 +7789,7 @@ BOOK.PUBLISHED_IN.notBetween(1920).and(1940)]]>

    The SQL standard defines the SYMMETRIC keyword to be used along with BETWEEN to indicate that you do not care which bound of the range is larger than the other. A database system should simply swap range bounds, in case the first bound is greater than the second one. jOOQ supports this keyword as well, emulating it if necessary.

    - + @@ -7800,7 +7800,7 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The emulation is done trivially:

    - + @@ -7815,27 +7815,27 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The SQL BETWEEN predicate also works well for . Much like the , it is defined in terms of a pair of regular :

    - + = [B] AND [A] <= [C] ([A] >= [B] AND [A] <= [C]) OR ([A] >= [C] AND [A] <= [B])]]> - +

    The above can be factored out according to the rules listed in the manual's section about .

    - +

    jOOQ supports the BETWEEN [SYMMETRIC] predicate and emulates it in all SQL dialects where necessary. An example is given here:

    - + - + - +
    LIKE predicate @@ -7856,7 +7856,7 @@ TITLE NOT LIKE '%abc%']]> - +

    Escaping operands with the LIKE predicate

    Often, your pattern may contain any of the wildcard characters "_" and "%", in case of which you may want to escape them. jOOQ does not automatically escape patterns in like() and notLike() methods. Instead, you can explicitly define an escape character as such: @@ -7875,12 +7875,12 @@ BOOK.TITLE.notLike("%The !%-Sign Book%", '!')]]>

    Please refer to your database manual for more details about escaping patterns with the LIKE predicate.

    - +

    jOOQ's convenience methods using the LIKE predicate

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using the LIKE predicate. Typical operations are "contains predicates", "starts with predicates", "ends with predicates", etc. Here is the full convenience API wrapping LIKE predicates:

    - + >) // Construct a NOT IN predicate from a subse

    A sample IN predicate might look like this:

    - + @@ -7933,12 +7933,12 @@ TITLE NOT IN ('Animal Farm', '1984')]]>
    BOOK.TITLE.notIn("Animal Farm", "1984")]]>
    - +

    NOT IN and NULL values

    Beware that you should probably not have any NULL values in the right hand side of a NOT IN predicate, as the whole expression would evaluate to NULL, which is rarely desired. This can be shown informally using the following reasoning:

    - + -- The following conditional expressions are formally or informally equivalent A NOT IN (B, C) A != ANY(B, C) @@ -7979,7 +7979,7 @@ NULL -- [ANY] AND NULL yields NULL -- Using a subselect (BOOK.ID, BOOK.TITLE) IN ( SELECT T.ID, T.TITLE - FROM T + FROM T )]]> - +

    In both cases, i.e. when using an IN list or when using a subselect, the type of the predicate is checked. Both sides of the predicate must be of equal degree and row type.

    - +

    - Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value. + Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value.

    - +
    EXISTS predicate @@ -8013,7 +8013,7 @@ row(BOOK.ID, BOOK.TITLE).in(
  • From a using
  • From a using , and from other clauses
  • - +

    An example of an EXISTS predicate can be seen here:

    @@ -8032,7 +8032,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

    - +

    Performance of IN vs. EXISTS

    In theory, the two types of predicates can perform equally well. If your database system ships with a sophisticated cost-based optimiser, it will be able to transform one predicate into the other, if you have all necessary constraints set (e.g. referential constraints, not null constraints). However, in reality, performance between the two might differ substantially. An interesting blog post investigating this topic on the MySQL database can be seen here:
    @@ -8040,7 +8040,7 @@ notExists(create.selectOne().from(BOOK)

    - +
    OVERLAPS predicate @@ -8078,7 +8078,7 @@ row(Date.valueOf('2010-01-01'), new DayToSecond(2)).overlaps(Date.valueOf('2010-

    Unlike the standard (or any database implementing the standard), jOOQ also supports the OVERLAPS predicate for comparing arbitrary . For instance, (1, 3) OVERLAPS (2, 4) will yield true in jOOQ. This is emulated as such

    - +
    - +
    Dynamic SQL

    In most cases, , , and as introduced in the previous chapters will be embedded into different SQL statement clauses as if the statement were a static SQL statement (e.g. in a view or stored procedure):

    - + - +

    It is, however, interesting to think of all of the above expressions as what they are: expressions. And as such, nothing keeps users from extracting expressions and referencing them from outside the statement. The following statement is exactly equivalent:

    @@ -8122,26 +8122,26 @@ create.select(select) .groupBy(groupBy) .orderBy() .fetch();]]> - +

    Each individual expression, and collection of expressions can be seen as an independent entity that can be

    - +
    1. Constructed dynamically
    2. Reused across queries
    - +

    Dynamic construction is particularly useful in the case of the , for dynamic predicate building. For instance:

    - +

    The dynamic SQL building power may be one of the biggest advantages of using a runtime query model like the one offered by jOOQ. Queries can be created dynamically, of arbitrary complexity. In the above example, we've just constructed a dynamic . The same can be done for any other clauses, including dynamic , or adding additional as needed.

    @@ -8177,7 +8177,7 @@ create.select()
  • - +

    You'll probably find other examples. If verbosity scares you off, don't worry. The verbose use-cases for jOOQ are rather rare, and when they come up, you do have an option. Just write SQL the way you're used to!

    @@ -8207,7 +8207,7 @@ Condition condition(String sql, Object... bindings); // Construct a condition taking other jOOQ object arguments // Example: condition("a = {0}", val(1)); 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 DSL:

    @@ -8265,7 +8265,7 @@ Result fetch(String sql, QueryPart... parts);]]>

    Apart from the general factory methods, plain SQL is also available in various other contexts. For instance, when adding a .where("a = b") clause to a query. Hence, there exist several convenience methods where plain SQL can be inserted usefully. This is an example displaying all various use-cases in one single query:

    - + LAST_NAME = create.field("a.LAST_NAME"); @@ -8386,7 +8386,7 @@ Name name = name("AUTHOR", "TITLE");]]> On a JDBC level, you can also reuse the SQL string and prepared statement object instead of constructing it again, as you can bind new values to the prepared statement. jOOQ currently does not cache prepared statements, internally. - +

    The following sections explain how you can introduce bind values in jOOQ, and how you can control the way they are rendered and bound to SQL.

    @@ -8399,7 +8399,7 @@ Name name = name("AUTHOR", "TITLE");]]>

    JDBC only knows indexed bind values. A typical example for using bind values with JDBC is this:

    - + With dynamic SQL, keeping track of the number of question marks and their corresponding index may turn out to be hard. jOOQ abstracts this and lets you provide the bind value right where it is needed. A trivial example is this:

    - + 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

    Should you decide to run the above query outside of jOOQ, using your own , you can do so as follows:

    - + select = create.select().from(BOOK).where(BOOK.ID.equal(5)).and(BOOK.TITLE.equal("Animal Farm")); // Render the SQL statement: @@ -8552,25 +8552,25 @@ create.select()
    SQL injection - +

    SQL injection is serious

    SQL injection is a serious problem that needs to be taken care of thoroughly. A single vulnerability can be enough for an attacker to dump your whole database, and potentially seize your database server. We've blogged about the severity of this threat on the jOOQ blog.

    - +

    SQL injection happens because a programming language (SQL) is used to dynamically create arbitrary server-side statements based on user input. Programmers must take lots of care not to mix the language parts (SQL) with the user input ()

    - +

    SQL injection in jOOQ

    With jOOQ, SQL is usually created via a type safe, non-dynamic Java abstract syntax tree, where bind variables are a part of that abstract syntax tree. It is not possible to expose SQL injection vulnerabilities this way.

    - +

    However, jOOQ offers convenient ways of introducing in various places of the jOOQ API (which are annotated using since jOOQ 3.6). While jOOQ's API allows you to specify bind values for use with plain SQL, you're not forced to do that. For instance, both of the following queries will lead to the same, valid result:

    - +

    A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] FROM AUTHOR JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID @@ -8713,15 +8713,15 @@ public final void accept(Context context) {

    As mentioned in the previous chapter about , there are some elements in the that are used for formatting / pretty-printing rendered SQL. In order to obtain pretty-printed SQL, just use the following :

    - - + +

    And then, use the above DSLContext to render pretty-printed SQL:

    - + A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] WHERE AUTHOR.ID = ? -- [...] @@ -8814,11 +8814,11 @@ public final void bind(BindContext context) throws DataAccessException {

    Converters

    - +

    The simplest use-case of injecting custom data types is by using . A Converter can convert from a database type <T> to a user-defined type <U> and vice versa. You'll be implementing this SPI:

    - + { // Your conversion logic goes into these two methods, that can convert @@ -8829,8 +8829,8 @@ public final void bind(BindContext context) throws DataAccessException { // You need to provide Class instances for each type, too: Class fromType(); Class toType(); -}]]> - +}]]> +

    If, for instance, you want to use Java 8's for SQL DATE and for SQL TIMESTAMP, you write a converter like this:

    @@ -8861,14 +8861,14 @@ public class LocalDateConverter implements Converter { public Class toType() { return LocalDate.class; } -}]]> +}]]>

    This converter can now be used in a variety of jOOQ API, most importanly to create a new data type:

    - + type = SQLDataType.DATE.asConvertedDataType(new LocalDateConverter());]]> - +

    And data types, in turn, can be used with any , i.e. with any , including or based ones:

    @@ -8881,15 +8881,15 @@ Field date1 = DSL.field("my_table.my_column", type); // Name based Field date2 = DSL.field(name("my_table", "my_column"), type);]]> - +

    Bindings

    - +

    While converters are very useful for simple use-cases, is useful when you need to customise data type interactions at a JDBC level, e.g. when you want to bind a PostgreSQL JSON data type. Custom bindings implement the following SPI:

    - + extends Serializable { // A converter that does the conversion between the database type T @@ -8909,11 +8909,11 @@ Field date2 = DSL.field(name("my_table", "my_column"), type);]]> ctx) throws SQLException; void get(BindingGetSQLInputContext ctx) throws SQLException; }]]> - +

    Below is full fledged example implementation that uses Google Gson to model JSON documents in Java

    - + { public void get(BindingGetSQLInputContext ctx) throws SQLException { throw new SQLFeatureNotSupportedException(); } -}]]> - +}]]> +

    Code generation

    There is a special section in the manual explaining how to automatically tie your Converters and Bindings to your generated code. The relevant sections are:

    - +
    - +
    Custom syntax elements

    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:

    - + extends AbstractField {} public abstract class CustomCondition extends AbstractCondition {} public abstract class CustomTable> extends TableImpl {} @@ -9024,7 +9024,7 @@ public abstract class CustomRecord> extends TableRecord

    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 method, as discussed before:

    - + 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 showing how to create a field multiplying another field by 2

    - + IDx2 = new CustomField(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(" * ?"); @@ -9064,10 +9064,10 @@ final Field IDx2 = new CustomField(BOOK.ID.getName(), BOOK.ID. @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(DSL.val(2)); } @@ -9086,7 +9086,7 @@ create.select(IDx2).from(BOOK);]]>

    Many vendor-specific functions are not officially supported by jOOQ, but you can implement such support yourself using CustomField, for instance. Here's an example showing how to implement Oracle's TO_CHAR() function, emulating it in SQL Server using CONVERT():

    - + { @@ -9123,7 +9123,7 @@ class ToChar extends CustomField {

    The above CustomField implementation can be exposed from your own custom DSL class:

    - + toChar(Field field, String format) { return new ToChar(field, DSL.inline(format)); @@ -9131,7 +9131,7 @@ class ToChar extends CustomField { }]]>
    - +
    Plain SQL QueryParts @@ -9145,10 +9145,10 @@ class ToChar extends CustomField {

    The above distinction is best explained using an example:

    - + Note that for historic reasons the two API usages can also be mixed, although this is not recommended and the exact behaviour is unspecified.

    - +

    Plain SQL templating specification

    - +

    Templating with QueryPart placeholders (or bind value placeholders) requires a simple parsing logic to be applied to SQL strings. The jOOQ template parser behaves according to the following rules:

    @@ -9183,13 +9183,13 @@ create.selectFrom(BOOK).where(
  • QueryPart placeholders ({number}) are replaced by the matching QueryPart.
  • Keywords ({identifier}) are treated like keywords and rendered in the correct case according to .
  • - +

    Tools for templating

    - +

    A variety of API is provided to create template elements that are intended for use with the above templating mechanism. These tools can be found in

    - +

    - +
    Custom SQL transformation @@ -9235,7 +9235,7 @@ create.attach(select);]]> With jOOQ 3.2's SPI, it is possible to perform custom SQL transformation to implement things like shared-schema multi-tenancy, or a security layer centrally preventing access to certain data. This SPI is extremely powerful, as you can make ad-hoc decisions at runtime regarding local or global transformation of your SQL statement. The following sections show a couple of simple, yet real-world use-cases.

    - +
    Logging abbreviated bind values @@ -9243,7 +9243,7 @@ create.attach(select);]]>

    When implementing a logger, one needs to carefully assess how much information should really be disclosed on what logger level. In log4j and similar frameworks, we distinguish between FATAL, ERROR, WARN, INFO, DEBUG, and TRACE. In DEBUG level, jOOQ's logs all executed statements including inlined bind values as such:

    - + with bind values : select * from "BOOK" where "BOOK"."TITLE" like 'How I stopped worrying%']]> @@ -9259,7 +9259,7 @@ public class BindValueAbbreviator extends DefaultVisitListener { @Override public void visitStart(VisitContext context) { - + // Transform only when rendering values if (context.renderContext() != null) { QueryPart part = context.queryPart(); @@ -9273,16 +9273,16 @@ public class BindValueAbbreviator extends DefaultVisitListener { // e.g. using commons-lang's StringUtils.abbreviate() if (value instanceof String && ((String) value).length() > maxLength) { anyAbbreviations = true; - + // ... and replace it in the current rendering context (not in the Query) context.queryPart(val(abbreviate((String) value, maxLength))); } - + // If the bind value is a byte[] (or Blob) of a given length, abbreviate it // e.g. by removing bytes from the array else if (value instanceof byte[] && ((byte[]) value).length > maxLength) { anyAbbreviations = true; - + // ... and replace it in the current rendering context (not in the Query) context.queryPart(val(Arrays.copyOf((byte[]) value, maxLength))); } @@ -9292,10 +9292,10 @@ public class BindValueAbbreviator extends DefaultVisitListener { @Override public void visitEnd(VisitContext context) { - + // If any abbreviations were performed before... if (anyAbbreviations) { - + // ... and if this is the top-level QueryPart, then append a SQL comment to indicate the abbreviation if (context.queryPartsLength() == 1) { context.renderContext().sql(" -- Bind values may have been abbreviated"); @@ -9320,14 +9320,14 @@ public class BindValueAbbreviator extends DefaultVisitListener {
    - +
    SQL building in Scala

    jOOQ-Scala is a maven module used for leveraging some advanced Scala features for those users that wish to use jOOQ with Scala.

    - +

    Using Scala's implicit defs to allow for operator overloading

    The most obvious Scala feature to use in jOOQ are implicit defs for implicit conversions in order to enhance the type with SQL-esque operators. @@ -9335,7 +9335,7 @@ public class BindValueAbbreviator extends DefaultVisitListener {

    The following depicts a trait which wraps all fields:

    - + The following depicts a trait which wraps numeric fields:

    - + An example query using such overloaded operators would then look like this:

    - +

    In a previous section of the manual, we've seen how jOOQ can be used to that can be executed with any API including JDBC or ... jOOQ. This section of the manual deals with various means of actually executing SQL with jOOQ.

    - +

    SQL execution with JDBC

    JDBC calls executable objects "". It distinguishes between three types of statements: @@ -9475,7 +9475,7 @@ fetch]]>

    Today, the JDBC API may look weird to users being used to object-oriented design. While statements hide a lot of SQL dialect-specific implementation details quite well, they assume a lot of knowledge about the internal state of a statement. For instance, you can use the method, to add a the prepared statement being created to an "internal list" of batch statements. Instead of returning a new type, this method forces user to reflect on the prepared statement's internal state or "mode".

    - +

    jOOQ is wrapping JDBC

    These things are abstracted away by jOOQ, which exposes such concepts in a more object-oriented way. For more details about jOOQ's batch query execution, see the manual's section about . @@ -9483,7 +9483,7 @@ fetch]]>

    The following sections of this manual will show how jOOQ is wrapping JDBC for SQL execution

    - +

    Alternative execution modes

    Just because you can, doesn't mean you must. At the end of this chapter, we'll show how you can use jOOQ to generate SQL statements that are then executed with other APIs, such as Spring's JdbcTemplate, or Hibernate. For more information see the . @@ -9502,7 +9502,7 @@ fetch]]>

  • Both APIs return the number of affected records in non-result queries. JDBC: , jOOQ:
  • Both APIs return a scrollable result set type from result queries. JDBC: , jOOQ:
  • - +

    Differences to JDBC

    Some of the most important differences between JDBC and jOOQ are listed here: @@ -9518,14 +9518,14 @@ fetch]]>

    - +
    Query vs. ResultQuery

    Unlike JDBC, jOOQ has a lot of knowledge about a SQL query's structure and internals (see the manual's section about ). Hence, jOOQ distinguishes between these two fundamental types of queries. While every can be executed, only can return results (see the manual's section about to learn more about fetching results). With plain SQL, the distinction can be made clear most easily:

    - + result = resultQuery.fetch();]]>
  • : Some databases allow for returning many result sets from a single query. JDBC can handle this but it's very verbose. A list of results should be returned instead.
  • : Some queries take too long to execute to wait for their results. You should be able to spawn query execution in a separate process.
  • - +

    Convenience and how ResultQuery, Result, and Record share API

    The term "fetch" is always reused in jOOQ when you can fetch data from the database. An provides many overloaded means of fetching data:

    - +

    Various modes of fetching

    These modes of fetching are also documented in subsequent sections of the manual

    - + fetch(); @@ -9587,7 +9587,7 @@ List> fetchMany(); // Execute a ResultQuery with jOOQ, but return a JDBC ResultSet, not a jOOQ object ResultSet fetchResultSet();]]> - +

    Fetch convenience

    These means of fetching are also available from and APIs @@ -9633,11 +9633,11 @@ ResultSet fetchResultSet();]]>

    These means of fetching are also available from and APIs

    - + Map fetchMap(Field key); Map fetchMap(Field key, Field value); @@ -9677,7 +9677,7 @@ ResultSet fetchResultSet();]]>

    Yet, still, sometimes you wish to use strongly typed records, when you know that you're selecting only from a single table:

    - +

    Fetching strongly or weakly typed records

    When fetching data only from a single table, the type is known to jOOQ if you use jOOQ's to generate for your database tables. In order to fetch such strongly typed records, you will have to use the : @@ -9689,7 +9689,7 @@ BookRecord book = create.selectFrom(BOOK).where(BOOK.ID.equal(1)).fetchOne(); // Typesafe field access is now possible: 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:

    @@ -9697,11 +9697,11 @@ System.out.println("Published in: " + book.getPublishedIn());]]>
  • - +

    Mapping custom row types to strongly typed records

    - +

    Sometimes, you may want to explicitly select only a subset of your columns, but still use strongly typed records. Alternatively, you may want to join a one-to-one relationship and receive the two individual strongly typed records after the join.

    @@ -9762,7 +9762,7 @@ System.out.println("Author : " + author.getFirstName() + " " + author.getLa

    By default, jOOQ returns an object, which is essentially a of . Often, you will find yourself wanting to transform this result object into a type that corresponds more to your specific needs. Or you just want to list all values of one specific column. Here are some examples to illustrate those use cases:

    - + titles1 = create.select().from(BOOK).fetch().getValues(BOOK.TITLE); List titles2 = create.select().from(BOOK).fetch(BOOK.TITLE); @@ -9797,7 +9797,7 @@ Map> group4 = create.selectFrom(BOOK).fetchGroups(BO

    In a more functional operating mode, you might want to write callbacks that receive records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + () {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -9832,7 +9832,7 @@ create.selectFrom(BOOK)

    In a more functional operating mode, you might want to write callbacks that map records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + ids = create.selectFrom(BOOK) @@ -9844,12 +9844,12 @@ create.selectFrom(BOOK) return book.getId(); } }); - + // Or more concisely create.selectFrom(BOOK) .orderBy(BOOK.ID) .fetch(new RecordMapper() {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -9875,7 +9875,7 @@ create.selectFrom(BOOK)

    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. See the manual's section about to see how to modify jOOQ's standard POJO mapping behaviour.

    - +

    Using JPA-annotated POJOs

    jOOQ tries to find JPA annotations on your POJO types. If it finds any, they are used as the primary source for mapping meta-information. Only the annotation is used and understood by jOOQ. An example: @@ -9885,7 +9885,7 @@ create.selectFrom(BOOK) public class MyBook { @Column(name = "ID") public int myId; - + @Column(name = "TITLE") public String myTitle; } @@ -9894,16 +9894,16 @@ public class MyBook { MyBook myBook = create.select().from(BOOK).fetchAny().into(MyBook.class); List myBooks = create.select().from(BOOK).fetch().into(MyBook.class); List myBooks = create.select().from(BOOK).fetchInto(MyBook.class);]]> - +

    Just as with any other JPA implementation, you can put the annotation on any class member, including attributes, setters and getters. Please refer to the Javadoc for more details.

    - +

    Using simple POJOs

    If jOOQ does not find any JPA-annotations, columns are mapped to the "best-matching" constructor, attribute or setter. An example illustrates this:

    - + myBooks = create.select().from(BOOK).fetchInto(MyBook1.class);]]><

    Please refer to the Javadoc for more details.

    - +

    Using "immutable" POJOs

    If jOOQ does not find any default constructor, columns are mapped to the "best-matching" constructor. This allows for using "immutable" POJOs with jOOQ. An example illustrates this:

    - + myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchInto( public class MyBook3 { public final String title; public final int id; - + @ConstructorProperties({ "title", "id"}) public MyBook2(String title, int id) { this.title = title; @@ -9958,7 +9958,7 @@ MyBook3 myBook = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchA List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetch().into(MyBook3.class); List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchInto(MyBook3.class); ]]> - +

    Please refer to the Javadoc for more details.

    @@ -9967,12 +9967,12 @@ List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchI

    jOOQ also allows for fetching data into abstract classes or interfaces, or in other words, "proxyable" types. This means that jOOQ will return a wrapped in a implementing your custom type. An example of this is given here:

    - + - +

    Note: Because of your manual setting of ID = 10, jOOQ's store() method will asume that you want to insert a new record. See the manual's section about for more details on this.

    - +

    Interaction with DAOs

    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: @@ -10039,21 +10039,21 @@ bookDao.update(book); // Delete it again bookDao.delete(book);]]> - +

    More complex data structures

    jOOQ currently doesn't support more complex data structures, the way Hibernate/JPA attempt to map relational data onto POJOs. While future developments in this direction are not excluded, jOOQ claims that generic mapping strategies lead to an enormous additional complexity that only serves very few use cases. You are likely to find a solution using any of jOOQ's various , with only little boiler-plate code on the client side.

    - +
    POJOs with RecordMappers

    In the previous sections we have seen how to create types to map jOOQ records onto arbitrary objects. We have also seen how jOOQ provides default algorithms to map jOOQ records onto . Your own custom domain model might be much more complex, but you want to avoid looking up the most appropriate RecordMapper every time you need one. For this, you can provide jOOQ's with your own implementation of the interface. An example is given here:

    - + } } } - + // Books might be joined with their authors, create a 1:1 mapping if (type == Book.class) { return new BookMapper(); @@ -10090,12 +10090,12 @@ bookDao.delete(book);]]>

    The above is a very simple example showing that you will have complete flexibility in how to override jOOQ's record to POJO mapping mechanisms.

    - +

    Using third party libraries

    A couple of useful libraries exist out there, which implement custom, more generic mapping algorithms. Some of them have been specifically made to work with jOOQ. Among them are:

    - +
    • ModelMapper (with an explicit jOOQ integration)
    • SimpleFlatMapper (with an explicit jOOQ integration)
    • @@ -10110,7 +10110,7 @@ bookDao.delete(book);]]>

      Unlike JDBC's , jOOQ's does not represent an open database cursor with various fetch modes and scroll modes, that needs to be closed after usage. jOOQ's results are simple in-memory Java objects, containing all of the result values. If your result sets are large, or if you have a lot of network latency, you may wish to fetch records one-by-one, or in small chunks. jOOQ supports a type for that purpose. In order to obtain such a reference, use the method. An example is given here:

      - + cursor = null; @@ -10120,7 +10120,7 @@ try { // Cursor has similar methods as Iterator while (cursor.hasNext()) { BookRecord book = cursor.fetchOne(); - + Util.doThingsWithBook(book); } } @@ -10135,7 +10135,7 @@ finally {

      As a holds an internal reference to an open , it may need to be closed at the end of iteration. If a cursor is completely scrolled through, it will conveniently close the underlying ResultSet. However, you should not rely on that.

      - +

      Cursors ship with all the other fetch features

      Like or , gives access to all of the other fetch features that we've seen so far, i.e. @@ -10177,7 +10177,7 @@ finally {

      The correct (and verbose) way to do this with JDBC is as follows:

      - +

      As previously discussed in the chapter about , jOOQ does not rely on an internal state of any JDBC object, which is "externalised" by Javadoc. Instead, it has a straight-forward API allowing you to do the above in a one-liner:

      - + > results = create.fetchMany("sp_help 'author'");]]> @@ -10218,22 +10218,22 @@ List> results = create.fetchMany("sp_help 'author'");]]>
      Later fetching

      Using Java 8 CompletableFutures

      - +

      Java 8 has introduced the new type, which allows for functional composition of asynchronous execution units. When applying this to SQL and jOOQ, you might be writing code as follows:

      - + + .supplyAsync(() -> DSL.using(configuration) .insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .values(3, "Hitchcock") .execute() ) - + // This will supply an AuthorRecord value for the newly inserted author .handleAsync((rows, throwable) -> DSL.using(configuration) @@ -10246,30 +10246,30 @@ CompletableFuture record.changed(true); return record.insert(); }) - + // This will supply an int value indicating the number of deleted rows - .handleAsync((rows, throwable) -> + .handleAsync((rows, throwable) -> DSL.using(configuration) .delete(AUTHOR) .where(AUTHOR.ID.eq(3)) .execute() ) .join();]]> - +

      The above example will execute four actions one after the other, but asynchronously in the JDK's default or common . -

      - +

      +

      For more information, please refer to the Javadoc and official documentation. -

      - +

      +

      Using deprecated API

      - +

      Some queries take very long to execute, yet they are not crucial for the continuation of the main program. For instance, you could be generating a complicated report in a Swing application, and while this report is being calculated in your database, you want to display a background progress bar, allowing the user to pursue some other work. This can be achived simply with jOOQ, by creating a , a type that extends . An example is given here:

      - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(); @@ -10285,7 +10285,7 @@ Result result = future.get();]]>

      Note, that instead of letting jOOQ spawn a new thread, you can also provide jOOQ with your own :

      - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(service);]]> @@ -10299,7 +10299,7 @@ FutureResult future = create.selectFrom(BOOK).where(... complex pred

      When interacting with legacy applications, you may prefer to have jOOQ return a , rather than jOOQ's own types. This can be done simply, in two ways:

      - + cursor = create.fetchLazy(rs);]]>

      You can also tighten the interaction with jOOQ's data type system and features, by passing the record type to the above fetch methods:

      - + result = create.fetch (rs, Integer.class, String.class); Cursor result = create.fetchLazy(rs, Integer.class, String.class); @@ -10361,7 +10361,7 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Apart from a few extra features (), jOOQ only supports basic types as supported by the JDBC API. In your application, you may choose to transform these data types into your own ones, without writing too much boiler-plate code. This can be done using jOOQ's types. A converter essentially allows for two-way conversion between two Java data types <T> and <U>. By convention, the <T> type corresponds to the type in your database whereas the <U> type corresponds to your own user type. The Converter API is given here:

      - + extends Serializable { /** @@ -10388,12 +10388,12 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Such a converter can be used in many parts of the jOOQ API. Some examples have been illustrated in the manual's section about .

      - +

      A Converter for GregorianCalendar

      Here is a some more elaborate example involving a Converter for :

      - + { @@ -10424,12 +10424,12 @@ public class CalendarConverter implements Converter dates1 = create.selectFrom(BOOK).fetch().getValues(BOOK.PUBLISHING_DATE, new CalendarConverter()); List dates2 = create.selectFrom(BOOK).fetch(BOOK.PUBLISHING_DATE, new CalendarConverter()); ]]> - +

      Enum Converters

      jOOQ ships with a built-in default , that you can use to map VARCHAR values to enum literals or NUMBER values to enum ordinals (both modes are supported). Let's say, you want to map a YES / NO / MAYBE column to a custom Enum:

      - + - +

      Using Converters in generated source code

      jOOQ also allows for generated source code to reference your own custom converters, in order to permanently replace a <T> type by your own, custom <U> type. See the manual's section about for details. @@ -10491,20 +10491,20 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE) .join(AUTHOR).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) .intern(BOOK.AUTHOR_ID) .fetch();]]> - +

      You can specify as many fields as you want for interning. The above has the following effect:

      - +
      • If the interned Field is of type , then is called upon each string
      • If the interned Field is of any other type, then the call is ignored
      - +

      Future versions of jOOQ will implement interning of data for non-String data types by collecting values in , removing duplicate instances.

      - +

      Note, that jOOQ will not use interned data for identity comparisons: string1 == string2. Interning is used only to reduce the memory footprint of objects.

      @@ -10512,7 +10512,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)
    - +
    Static statements vs. Prepared Statements @@ -10522,7 +10522,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)

    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:

    - + @@ -10552,7 +10552,7 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    Whichever aproach is more optimal for you cannot be decided by jOOQ. In most cases, prepared statements are probably better. But you always have the option of forcing jOOQ to render inlined bind values.

    - +

    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 @@ -10566,15 +10566,15 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    As previously discussed in the chapter about , reusing PreparedStatements is handled a bit differently in jOOQ from how it is handled in JDBC

    - +

    Keeping open PreparedStatements with JDBC

    With JDBC, you can easily reuse a by not closing it between subsequent executions. An example is given here:

    - + The above technique can be quite useful when you want to reuse expensive database resources. This can be the case when your statement is executed very frequently and your database would take non-negligible time to soft-parse the prepared statement and generate a new statement / cursor resource.

    - +

    Keeping open PreparedStatements with jOOQ

    This is also modeled in jOOQ. However, the difference to JDBC is that closing a statement is the default action, whereas keeping it open has to be configured explicitly. This is better than JDBC, because the default action should be the one that is used most often. Keeping open statements is rarely done in average applications. Here's an example of how to keep open PreparedStatements with jOOQ:

    - + query = create.selectOne().keepStatement(true); @@ -10608,7 +10608,7 @@ finally {

    The above example shows how a query can be executed twice against the same underlying PreparedStatement. Unlike in other execution scenarios, you must not forget to close this query now

    - +

    Beware of resource leaks

    While jOOQ allows for explicitly keeping open PreparedStatement references in Query instances, the JDBC Connection may still be closed independently without jOOQ or the PreparedStatement noticing. It is the user's responsibility to close all resources according to the specification and behaviour of the concrete JDBC driver and the underlying database. @@ -10622,7 +10622,7 @@ finally {

    JDBC knows a couple of execution flags and modes, which can be set through the jOOQ API as well. jOOQ essentially supports these flags and execution modes:

    - + - + extends Query { // [...] @@ -10655,25 +10655,25 @@ finally { // The maximum number of rows to be fetched by JDBC // ----------------------------------------------------------- ResultQuery maxRows(int rows); - + }]]>

    Using ResultSet concurrency with ExecuteListeners

    An example of why you might want to manually set a ResultSet's concurrency flag to something non-default is given here:

    - + - +

    In the above example, your custom is triggered before jOOQ loads a new Record from the JDBC ResultSet. With the concurrency being set to ResultSet.CONCUR_UPDATABLE, you can now modify the database cursor through the standard JDBC ResultSet API.

    @@ -10731,22 +10731,22 @@ try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO author(id stmt.setString(2, "Erich"); stmt.setString(3, "Gamma"); stmt.addBatch(); - + stmt.setInt(1, 2); stmt.setString(2, "Richard"); stmt.setString(3, "Helm"); stmt.addBatch(); - + stmt.setInt(1, 3); stmt.setString(2, "Ralph"); stmt.setString(3, "Johnson"); stmt.addBatch(); - + stmt.setInt(1, 4); stmt.setString(2, "John"); stmt.setString(3, "Vlissides"); stmt.addBatch(); - + int[] result = stmt.executeBatch(); }]]>
    @@ -10755,7 +10755,7 @@ try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO author(id

    jOOQ supports executing queries in batch mode as follows:

    - + - +

    When creating a batch execution with a single query and multiple bind values, you will still have to provide jOOQ with dummy bind values for the original query. In the above example, these are set to null. For subsequent calls to bind(), there will be no type safety provided by jOOQ.

    @@ -10791,18 +10791,18 @@ create.batch(create.insertInto(AUTHOR, ID, FIRST_NAME, LAST_NAME ).values((Inte

    Instead of actually phrasing a select statement, you can also use the convenience methods:

    - + - +

    Inlining sequence references in SQL

    You can inline sequence references in jOOQ SQL statements. The following are examples of how to do that:

    - + The general distinction between (stored) procedures and (stored) functions can be summarised like this:

    - +

    Procedures

    • Are called using JDBC CallableStatement
    • Have no return value
    • Usually support OUT parameters
    - +

    Functions

    • Can be used in SQL statements
    • Have a return value
    • Usually don't support OUT parameters
    - +

    Exceptions to these rules

    • DB2, H2, and HSQLDB don't allow for JDBC escape syntax when calling functions. Functions must be used in a SELECT statement
    • @@ -10863,19 +10863,19 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

      To simplify things a little bit, jOOQ handles both procedures and functions the same way, using a more general type.

      - +

      Using jOOQ for standalone calls to stored procedures and functions

      If you're using jOOQ's , it will generate objects for you. Let's consider the following example:

      - +

      The generated artefacts can then be used as follows:

      - + - +

      But you can also call the procedure using a generated convenience method in a global Routines class:

      @@ -10902,7 +10902,7 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]>

      For more details about for procedures, see the manual's section about .

      - +

      Inlining stored function references in SQL

      Unlike procedures, functions can be inlined in SQL statements to generate or , if you're using . Assume you have a function like this: @@ -10910,11 +10910,11 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]> - +

      The generated artefacts can then be used as follows:

      - + boolean exists = create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]> - +

      For more info about inlining stored function references in SQL statements, please refer to the manual's section about .

      @@ -10955,7 +10955,7 @@ create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]>

      Oracle UDTs can have object-oriented structures including member functions and procedures. With Oracle, you can do things like this:

      - + {"name":"field-n","type":"type-n"}], "records":[[value-1-1,value-1-2,...,value-1-n], [value-2-1,value-2-2,...,value-2-n]]} - +

      Note: This format has changed in jOOQ 2.6.0

      @@ -11270,7 +11270,7 @@ Query query = error.query();]]>
    - +
    Importing JSON @@ -11329,12 +11329,12 @@ create.loadInto(BOOK)

    CRUD always uses the same patterns, regardless of the nature of underlying tables. This again, leads to a lot of boilerplate code, if you have to issue your statements yourself. Like Hibernate / JPA and other ORMs, jOOQ facilitates CRUD using a specific API involving types.

    - +

    Primary keys and updatability

    In normalised databases, every table has a primary key by which a tuple/record within that table can be uniquely identified. In simple cases, this is a (possibly auto-generated) number called ID. But in many cases, primary keys include several non-numeric columns. An important feature of such keys is the fact that in most databases, they are enforced using an index that allows for very fast random access to the table. A typical way to access / modify / delete a book is this:

    - + - +

    Normalised databases assume that a primary key is unique "forever", i.e. that a key, once inserted into a table, will never be changed or re-inserted after deletion. In order to use jOOQ's operations correctly, you should design your database accordingly.

    @@ -11355,7 +11355,7 @@ DELETE FROM BOOK WHERE ID = 5;]]>

    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:

    - + - +

    See the manual's section about for some more insight on "attached" objects.

    - +

    Storing

    Storing a record will perform an or an . In general, new records are always inserted, whereas records loaded from the database are always updated. This is best visualised in code: @@ -11394,7 +11394,7 @@ BookRecord book2 = create.fetchOne(BOOK, BOOK.ID.equal(id)); // Update the record: UPDATE BOOK SET TITLE = 'Animal Farm' WHERE ID = [id] book2.setTitle("Animal Farm"); book2.store();]]> - +

    Some remarks about storing:

    @@ -11404,18 +11404,18 @@ book2.store();]]>
  • When loading records from , jOOQ will assume the record is a new record. It will hence attempt to INSERT it.
  • When you activate , storing a record may fail, if the underlying database record has been changed in the mean time.
  • - +

    Deleting

    Deleting a record will remove it from the database. Here's how you delete records:

    - + - +

    Refreshing

    Refreshing a record from the database means that jOOQ will issue a to refresh all record values that are not the primary key. This is particularly useful when you use jOOQ's feature, in case a modified record is "stale" and cannot be stored to the database, because the underlying database record has changed in the mean time. @@ -11434,7 +11434,7 @@ book.refresh();]]>

    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 :

    - + The "original" value, i.e. the value as it was originally fetched from the database or null, if the record was never in the database
  • The "changed" flag, indicating if the value was ever changed through the Record API.
  • - +

    The purpose of the above information is for jOOQ's to know, which values need to be stored to the database, and which values have been left untouched.

    @@ -11470,19 +11470,19 @@ for (BookRecord book : create.fetch(BOOK, BOOK.PUBLISHED_IN.equal(1948))) {

    Many databases support the concept of IDENTITY values, or key values. This is reflected by JDBC's method. jOOQ abstracts using this method as many databases and JDBC drivers behave differently with respect to generated keys. Let's assume the following SQL Server BOOK table:

    - +

    If you're using jOOQ's , the above table will generate a with an IDENTITY column. This information is used by jOOQ internally, to update IDs after calling :

    - +

    and contain foreign key navigation methods. These navigation methods allow for "navigating" inbound or outbound foreign key references by executing an appropriate query. An example is given here:

    - + books = author.fetchChildren(FK_BOOK_AUTHOR);]]>

    Tables without a PRIMARY KEY are considered non-updatable by jOOQ, as jOOQ has no way of uniquely identifying such a record within the database. If you're using jOOQ's , such tables will generate classes, instead of classes. When you fetch from such a table, the returned records will not allow for calling any of the methods.

    - +

    Note, that some databases use internal rowid or object-id values to identify such records. jOOQ does not support these vendor-specific record meta-data.

    @@ -11613,7 +11613,7 @@ Result books = author.fetchChildren(FK_BOOK_AUTHOR);]]>
    - +

    Optimised optimistic locking using TIMESTAMP fields

    If you're using jOOQ's , you can take indicate TIMESTAMP or UPDATE COUNTER fields for every generated table in the . Let's say we have this table:

    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:

    - +

    As before, without the added TIMESTAMP column, optimistic locking is transparent to the API.

    - +

    Optimised optimistic locking using VERSION fields

    Instead of using TIMESTAMPs, you may also use numeric VERSION fields, containing version numbers that are incremented by jOOQ upon store() calls. @@ -11682,7 +11682,7 @@ book2.store();]]>

    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:

    - + books = create.fetch(BOOK); @@ -11698,7 +11698,7 @@ create.batchStore(books);]]>

    - +
    CRUD SPI: RecordListener @@ -11709,11 +11709,11 @@ create.batchStore(books);]]>
  • Adding a central ID generation algorithm, generating UUIDs for all of your records.
  • Adding a central record initialisation mechanism, preparing the database prior to inserting a new record.
  • - +

    An example of such a RecordListener is given here:

    - + - +

    Now, configure jOOQ's runtime to load your listener

    @@ -11753,7 +11753,7 @@ DSLContext create = DSL.using(configuration);]]>

    If you're using jOOQ's , you can configure it to generate and DAOs for you. jOOQ then generates one DAO per , i.e. per table with a single-column primary key. Generated DAOs implement a common jOOQ type called . This type contains the following methods:

    - + corresponds to the DAO's related table //

    corresponds to the DAO's related generated POJO type // corresponds to the DAO's related table's primary key type. @@ -11764,23 +11764,23 @@ public interface DAO, P, T> { void insert(P object) throws DataAccessException; void insert(P... objects) throws DataAccessException; void insert(Collection

    objects) throws DataAccessException; - + // These methods allow for updating POJOs based on their primary key void update(P object) throws DataAccessException; void update(P... objects) throws DataAccessException; void update(Collection

    objects) throws DataAccessException; - + // These methods allow for deleting POJOs based on their primary key void delete(P... objects) throws DataAccessException; void delete(Collection

    objects) throws DataAccessException; void deleteById(T... ids) throws DataAccessException; void deleteById(Collection ids) throws DataAccessException; - + // These methods allow for checking record existence boolean exists(P object) throws DataAccessException; boolean existsById(T id) throws DataAccessException; long count() throws DataAccessException; - + // These methods allow for retrieving POJOs by primary key or by some other field List

    findAll() throws DataAccessException; P findById(T id) throws DataAccessException; @@ -11809,7 +11809,7 @@ public class BookDao extends DAOImpl {

    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:

    - +

    Note how the lambda expression receives a new, derived configuration that should be used within the local scope:

    - + { // Wrap configuration in a new DSLContext: DSL.using(configuration).insertInto(...); DSL.using(configuration).insertInto(...); - + // Or, reuse the new DSLContext within the transaction scope: DSLContext ctx = DSL.using(configuration); ctx.insertInto(...); ctx.insertInto(...); - + // ... but avoid using the scope from outside the transaction: create.insertInto(...); create.insertInto(...); }); ]]> - +

    - While some implementations (e.g. ones based on ThreadLocals, e.g. Spring or JTA) may allow you to reuse the globally scoped reference, the jOOQ transaction API design allows for TransactionProvider implementations that require your transactional code to use the new, locally scoped Configuration, instead. + While some implementations (e.g. ones based on ThreadLocals, e.g. Spring or JTA) may allow you to reuse the globally scoped reference, the jOOQ transaction API design allows for TransactionProvider implementations that require your transactional code to use the new, locally scoped Configuration, instead.

    @@ -12030,7 +12030,7 @@ class SpringTransaction implements Transaction {

    With jOOQ, it's simple. All of jOOQ's exceptions are "system exceptions", hence they are all unchecked.

    - +

    jOOQ's DataAccessException

    jOOQ uses its own to wrap any underlying that might have occurred. Note that all methods in jOOQ that may cause such a DataAccessException document this both in the Javadoc as well as in their method signature. @@ -12046,7 +12046,7 @@ class SpringTransaction implements Transaction {

  • InvalidResultException: An operation was performed expecting only one result, but several results were returned.
  • MappingException: Something went wrong when loading a record from a or when mapping a record into a POJO
  • - +

    Override jOOQ's exception handling

    The following section about documents means of overriding jOOQ's exception handling, if you wish to deal separately with some types of constraint violations, or if you raise business errors from your database, etc. @@ -12063,7 +12063,7 @@ class SpringTransaction implements Transaction {

    For convenience and better backwards-compatibility, consider extending instead of implementing this interface.

    - +

    Example: Query statistics ExecuteListener

    Here is a sample implementation of an ExecuteListener, that is simply counting the number of queries per type that are being executed using jOOQ: @@ -12080,11 +12080,11 @@ public class StatisticsListener extends DefaultExecuteListener { public void start(ExecuteContext ctx) { synchronized (STATISTICS) { Integer count = STATISTICS.get(ctx.type()); - + if (count == null) { count = 0; } - + STATISTICS.put(ctx.type(), count + 1); } } @@ -12127,7 +12127,7 @@ for (ExecuteType type : ExecuteType.values()) {

    Please read the for more details

    - +

    Example: Custom Logging ExecuteListener

    The following depicts an example of a custom ExecuteListener, which pretty-prints all queries being executed by jOOQ to stdout: @@ -12150,7 +12150,7 @@ public class PrettyPrinter extends DefaultExecuteListener { // Create a new DSLContext for logging rendering purposes // This DSLContext doesn't need a connection, only the SQLDialect... DSLContext create = DSL.using(ctx.dialect(), - + // ... and the flag for pretty-printing new Settings().withRenderFormatted(true)); @@ -12158,12 +12158,12 @@ public class PrettyPrinter extends DefaultExecuteListener { if (ctx.query() != null) { System.out.println(create.renderInlined(ctx.query())); } - + // If we're executing a routine else if (ctx.routine() != null) { System.out.println(create.renderInlined(ctx.routine())); } - + // If we're executing anything else (e.g. plain SQL) else if (!StringUtils.isBlank(ctx.sql())) { System.out.println(ctx.sql()); @@ -12173,12 +12173,12 @@ public class PrettyPrinter extends DefaultExecuteListener {

    See also the manual's sections about for more sample implementations of actual ExecuteListeners.

    - +

    Example: Bad query execution ExecuteListener

    You can also use ExecuteListeners to interact with your SQL statements, for instance when you want to check if executed or statements contain a WHERE clause. This can be achieved trivially with the following sample ExecuteListener:

    - + 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:

    - + @@ -12230,7 +12230,7 @@ public class DeleteOrUpdateWithoutWhereException extends RuntimeException {}

    With the above configuration, let's fetch some data with jOOQ

    - +

    @@ -12278,14 +12278,14 @@ Finishing : Total: 4.814ms, +3.375ms

  • 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
  • - +

    Optimise wisely

    Don't be put off by the above paragraphs. You should optimise wisely, i.e. only in places where you really need very high throughput to your database. jOOQ's overhead compared to plain JDBC is typically less than 1ms per query.

    - +
    Alternative execution models @@ -12295,7 +12295,7 @@ Finishing : Total: 4.814ms, +3.375ms

    - +
    Using jOOQ with JPA @@ -12304,11 +12304,11 @@ Finishing : Total: 4.814ms, +3.375ms

    These sections will show how to use jOOQ with JPA's native query API in order to fetch tuples or managed entities using the Java EE standards.

    - +

    In all of the following sections, let's assume we have the following JPA entities to model our database:

    - + - +
    Using jOOQ with JPA Native Query @@ -12411,7 +12411,7 @@ nativeQuery(em, DSL.using(configuration) books.forEach((Object[] book) -> System.out.println(book[0] + " " + book[1] + " wrote " + book[2]));]]>
    - +
    Using jOOQ with JPA entities @@ -12419,7 +12419,7 @@ books.forEach((Object[] book) -> System.out.println(book[0] + " " + book[1] + "

    The simplest way to fetch entities via the native query API is by passing the entity class along to the native query method. The following example maps jOOQ query results to JPA entities (). Just add the following utility method:

    - + List nativeQuery(EntityManager em, org.jooq.Query query, Class type) { // Extract the SQL statement from the jOOQ query: @@ -12438,7 +12438,7 @@ books.forEach((Object[] book) -> System.out.println(book[0] + " " + book[1] + "

    Note, if you're using or , make sure to take those into account as well. E.g. as follows:

    - + nativeQuery(EntityManager em, org.jooq.Query query, Class type) { // Extract the SQL statement from the jOOQ query: @@ -12461,7 +12461,7 @@ static Object convertToDatabaseType(Param param) {

    With the above simple API, we're ready to write complex jOOQ queries and map their results to JPA entities:

    - + authors = nativeQuery(em, DSL.using(configuration) @@ -12472,14 +12472,14 @@ nativeQuery(em, authors.forEach(author -> { System.out.println(author.firstName + " " + author.lastName + " wrote"); - + books.forEach(book -> { System.out.println(" " + book.title); }); });]]>
    - +
    Using jOOQ with JPA EntityResult @@ -12487,11 +12487,11 @@ authors.forEach(author -> {

    While JPA specifies how the mapping should be implemented (e.g. using ), there are no limitations regarding how you want to generate the SQL statement. The following, simple example shows how you can produce JPABook and JPAAuthor entities () from a jOOQ-generated SQL statement.

    - +

    In order to do so, we'll need to specify the . This can be done on any entity, and in this case, we're using :

    - + { } ) } -)]]> - +)]]> +

    Note how we need to map between:

    @@ -12521,11 +12521,11 @@ authors.forEach(author -> {
  • , which corresponds to the entity's attribute name
  • , which corresponds to the SQL result's column name
  • - +

    With the above boilerplate in place, we can now fetch entities using jOOQ and JPA:

    - + List nativeQuery(EntityManager em, org.jooq.Query query, String resultSetMapping) { // Extract the SQL statement from the jOOQ query: @@ -12543,7 +12543,7 @@ authors.forEach(author -> {

    Note, if you're using or , make sure to take those into account as well. E.g. as follows:

    - + List nativeQuery(EntityManager em, org.jooq.Query query, String resultSetMapping) { // Extract the SQL statement from the jOOQ query: @@ -12564,11 +12564,11 @@ static Object convertToDatabaseType(Param param) { }]]>

    Using the above API

    - +

    Now that we have everything setup, we can use the above API to run a jOOQ query to fetch JPA entities like this:

    - + result = nativeQuery(em, DSL.using(configuration @@ -12582,7 +12582,7 @@ nativeQuery(em, ) .from(AUTHOR) .join(BOOK).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) - .orderBy(BOOK.ID)), + .orderBy(BOOK.ID)), "bookmapping" // The name of the SqlResultSetMapping ); @@ -12591,11 +12591,11 @@ result.forEach((Object[] entities) -> { JPABook book = (JPABook) entities[0]; System.out.println(author.firstName + " " + author.lastName + " wrote " + book.title); -});]]> +});]]>

    The entities are now ready to be modified and persisted again.

    - +

    Caveats:

    @@ -12607,7 +12607,7 @@ result.forEach((Object[] entities) -> {
    -
    +
    @@ -12661,7 +12661,7 @@ result.forEach((Object[] entities) -> {

    You need to tell jOOQ some things about your database connection. Here's an example of how to do it for an Oracle database

    - + @@ -12670,7 +12670,7 @@ result.forEach((Object[] entities) -> { jdbc:oracle:thin:@[your jdbc connection parameters] [your database user] [your database password] - + user[db-user] @@ -12682,9 +12682,9 @@ result.forEach((Object[] entities) -> { org.jooq.util.oracle.OracleDatabase @@ -12718,9 +12718,9 @@ result.forEach((Object[] entities) -> { Use the pipe to separate several expressions) Watch out for case-sensitivity. Depending on your database, this might be important! - + You can create case-insensitive regular expressions using this syntax: (?i:expr) - + Whitespace is ignored and comments are possible. --> .* @@ -12751,7 +12751,7 @@ result.forEach((Object[] entities) -> { @@ -12772,13 +12772,13 @@ result.forEach((Object[] entities) -> {

    Code generation works by calling this class with the above property file as argument.

    - + org.jooq.util.GenerationTool /jooq-config.xml

    Be sure that these elements are located on the classpath:

    - +
    • The XML configuration file
    • jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar
    • @@ -12803,7 +12803,7 @@ result.forEach((Object[] entities) -> {
    • this example uses jOOQ's log4j support by adding log4j.xml and log4j.jar to the project classpath.
    • the actual jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar artefacts may contain version numbers in the file names.
    - +
    Eclipse configuration
    @@ -12961,9 +12961,9 @@ result.forEach((Object[] entities) -> { false @@ -12976,7 +12976,7 @@ result.forEach((Object[] entities) -> { production schema. Use this to override your local development schema name for source code generation. If not specified, this will be the same as the input-schema. - + This will be ignored if outputSchemaToDefault is set to true --> [your database schema / owner / name] @@ -13085,30 +13085,30 @@ result.forEach((Object[] entities) -> { false - + true - + false ]]>
    @@ -13117,7 +13117,7 @@ result.forEach((Object[] entities) -> {

    Some of the above properties depend on other properties to work correctly. For instance, when generating immutable pojos, pojos must be generated. jOOQ will enforce such properties even if you tell it otherwise. Here is a list of property interdependencies:

    - +
    • When daos = true, then jOOQ will set relations = true
    • When daos = true, then jOOQ will set records = true
    • @@ -13126,7 +13126,7 @@ result.forEach((Object[] entities) -> {
    - +
    Programmatic generator configuration @@ -13134,7 +13134,7 @@ result.forEach((Object[] entities) -> {

    In the previous sections, we have covered how to set up jOOQ's code generator using XML, either by running a standalone Java application, or by using Maven. However, it is also possible to use jOOQ's GenerationTool programmatically. The XSD file used for the configuration (http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd) is processed using XJC to produce Java artefacts. The below example uses those artefacts to produce the equivalent configuration of the previous :

    - +

    For the above example, you will need all of jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, and jooq-codegen-{jooq-version}.jar, on your classpath.

    - +

    Manually loading the XML file

    - +

    Alternatively, you can also load parts of the configuration from an XML file using JAXB and programmatically modify other parts using the code generation API:

    - + org.h2.Driver ]]> - +

    Load the above using standard JAXB API:

    - +

    - +
    Custom generator strategies @@ -13207,7 +13207,7 @@ GeberationTool.generate(configuration);]]>

    jOOQ allows you to override default implementations of the code generator or the generator strategy. Specifically, the latter can be very useful if you want to inject custom behaviour into jOOQ's code generator with respect to naming classes, members, methods, and other Java objects.

    - + @@ -13432,58 +13432,58 @@ public class Book implements java.io.Serializable { - + MY_SCHEMA - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - +
    - + MY_TABLE - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomBaseClass com.example.MyOptionalCustomInterface
    - + - + MY_FIELD - + --> MatcherRule --> MatcherRule @@ -13491,30 +13491,30 @@ public class Book implements java.io.Serializable { --> MatcherRule - + - + MY_ROUTINE - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + - + MY_SEQUENCE - + --> MatcherRule @@ -13530,19 +13530,19 @@ public class Book implements java.io.Serializable { CAMEL - + PREFIX_$0_SUFFIX ]]> - +

    Some examples

    The following example shows a matcher strategy that adds a "T_" prefix to all table classes and to table identifiers: @@ -13553,7 +13553,7 @@ public class Book implements java.io.Serializable { - + UPPER @@ -13588,13 +13588,13 @@ public class Book implements java.io.Serializable { ]]> - +

    For more information about each XML tag, please refer to the http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd XSD file.

    - +
    Custom code sections @@ -13641,7 +13641,7 @@ public class Book implements java.io.Serializable {

    Any of the below methods can be overridden:

    - + Tables.java: This file contains all table objects in the form of static member references to the actual singleton object
  • UDTs.java: This file contains all UDT objects in the form of static member references to the actual singleton object
  • - +

    Referencing global artefacts

    When referencing global artefacts from your client application, you would typically static import them as such:

    - + @@ -13737,7 +13737,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate a implementation that looks like this:

    - + { // The singleton instance @@ -13753,7 +13753,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE) public Book as(java.lang.String alias) { return new Book(alias); } - + // [...] }]]> @@ -13772,7 +13772,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)
  • instanceFields: This flag controls the "static" keyword on table columns, as well as aliasing convenience
  • records: The generated record type is referenced from tables allowing for type-safe single-table record fetching
  • - +

    Flags controlling table generation

    Table generation cannot be deactivated @@ -13786,7 +13786,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate an implementation that looks like this:

    - + - +

    Flags influencing generated records

    These flags from the influence generated records: @@ -13844,7 +13844,7 @@ implements IBook {

  • interfaces: If interfaces are generated, records will implement them
  • jpaAnnotations: JPA annotations are used on generated records
  • - +

    Flags controlling record generation

    Record generation can be deactivated using the records flag @@ -13858,7 +13858,7 @@ implements IBook {

    Every table in your database will generate a POJO implementation that looks like this:

    - + - +

    Flags influencing generated POJOs

    These flags from the influence generated POJOs: @@ -13907,7 +13907,7 @@ public class Book implements java.io.Serializable

  • jpaAnnotations: JPA annotations are used on generated records
  • validationAnnotations: JSR-303 validation annotations are used on generated records
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the pojos flag @@ -13921,16 +13921,16 @@ public class Book implements java.io.Serializable

    Every table in your database will generate an interface that looks like this:

    - + - +

    Flags influencing generated interfaces

    These flags from the influence generated interfaces: @@ -13939,7 +13939,7 @@ public class Book implements java.io.Serializable

  • dateAsTimestamp: This influences all relevant getters and setters
  • unsignedTypes: This influences all relevant getters and setters
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the interfaces flag @@ -13954,7 +13954,7 @@ public class Book implements java.io.Serializable

    Every table in your database will generate a implementation that looks like this:

    - + { // Generated constructors @@ -13978,10 +13978,10 @@ public class Book implements java.io.Serializable public List fetchByAuthorId(Integer... values) { return fetch(BOOK.AUTHOR_ID, values); } - + // [...] }]]> - +

    Flags controlling DAO generation

    DAO generation can be activated using the daos flag @@ -13995,13 +13995,13 @@ public class Book implements java.io.Serializable

    Every sequence in your database will generate a implementation that looks like this:

    - + S_AUTHOR_ID = new SequenceImpl("S_AUTHOR_ID", TEST, SQLDataType.INTEGER); }]]> - +

    Flags controlling sequence generation

    Sequence generation cannot be deactivated @@ -14039,7 +14039,7 @@ public class Book implements java.io.Serializable public BigDecimal getResult() { return getValue(RESULT); } - + // [...] }]]> @@ -14061,7 +14061,7 @@ public class Book implements java.io.Serializable

    Every UDT in your database will generate a implementation that looks like this:

    - + { // The singleton UDT instance @@ -14074,10 +14074,10 @@ public class Book implements java.io.Serializable createField("CITY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); public static final UDTField COUNTRY = createField("COUNTRY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); - + // [...] }]]> - +

    Besides the implementation, a implementation is also generated

    @@ -14092,7 +14092,7 @@ public class Book implements java.io.Serializable public String getCity() {...} public void setCountry(String value) {...} public String getCountry() {...} - + // [...] }]]>
    @@ -14121,20 +14121,20 @@ public class Book implements java.io.Serializable BOOLEAN .*\.IS_VALID - + .* @@ -14165,7 +14165,7 @@ public class Book implements java.io.Serializable GregorianCalendar - + java.util.GregorianCalendar @@ -14181,21 +14181,21 @@ public class Book implements java.io.Serializable GregorianCalendar .*\.DATE_OF_.* - + .* @@ -14229,15 +14229,15 @@ create.selectFrom(AUTHOR)
    - - + +
    Custom data type binding

    The previous section discussed the case where your custom data type is mapped onto a standard JDBC type as contained in . In some cases, however, you want to map your own type onto a type that is not explicitly supported by JDBC, such as for instance, PostgreSQL's various advanced data types like JSON or HSTORE, or PostGIS types. For this, you can register an for relevant columns in your code generator. Consider the following trivial implementation of a binding for PostgreSQL's JSON data type, which binds the JSON string in PostgreSQL to a Google GSON object:

    - + {

    The above implementation intercepts all the interaction on a JDBC level, such that jOOQ will never need to know how to crrectly serialise / deserialise your custom data type. Similar to what we've seen in the previous section about , we can now register such a binding to the code generator. Note that you will reuse the same types of XML elements (<customType/> and <forcedType/>):

    - + JsonElement - + com.google.gson.JsonElement @@ -14347,26 +14347,26 @@ public class PostgresJSONGsonBinding implements Binding { JsonElement .*JSON.* - + .* -]]> +]]>

    See also the section about to learn about an alternative use of <forcedTypes/>. @@ -14386,7 +14386,7 @@ public class PostgresJSONGsonBinding implements Binding {

    - +
    Mapping generated schemata and tables @@ -14407,23 +14407,23 @@ public class PostgresJSONGsonBinding implements Binding {
    - +
    Code generation for large schemas

    Databases can become very large in real-world applications. This is not a problem for jOOQ's code generator, but it can be for the Java compiler. jOOQ generates some classes for . These classes can hit two sorts of limits of the compiler / JVM:

    - +
    • Methods (including static / instance initialisers) are allowed to contain only 64kb of bytecode.
    • Classes are allowed to contain at most 64k of constant literals
    - +

    While there exist workarounds for the above two limitations (delegating initialisations to nested classes, inheriting constant literals from implemented interfaces), the preferred approach is either one of these:

    - +
    • Distribute your database objects in several schemas. That is probably a good idea anyway for such large databases
    • to exclude excess database objects
    • @@ -14498,7 +14498,7 @@ public class PostgresJSONGsonBinding implements Binding {

      In such a setup, you might have a pre-existing schema implemented using JPA-annotated entities. Your real database schema might not be accessible while developing, or it is not a first-class citizen in your application (i.e. you follow a Java-first approach). This section explains how you can generate jOOQ classes from such a JPA model. Consider this model:

      - + With that dependency in place, you can now specify the JPADatabase in your code generator configuration:

      - + org.jooq.util.jpa.JPADatabase @@ -14584,7 +14584,7 @@ public class Book {

      An example schema definition containing simple schema, table, column definitions can be seen below:

      - + @@ -14645,7 +14645,7 @@ public class Book { ... - + TEST @@ -14660,18 +14660,18 @@ public class Book {

      The above file can be made available to the code generator configuration by using the XMLDatabase as follows:

      - + org.jooq.util.xml.XMLDatabase - + dialect ORACLE - + xml-file @@ -14682,16 +14682,16 @@ public class Book { ]]>

      - If you already have a different XML format for your database, you can either XSL transform your own format into the one above via an additional Maven plugin, or pass the location of an XSL file to the XMLDatabase by providing an additional property: + If you already have a different XML format for your database, you can either XSL transform your own format into the one above via an additional Maven plugin, or pass the location of an XSL file to the XMLDatabase by providing an additional property:

      - + org.jooq.util.xml.XMLDatabase - + ... - + xsl-file @@ -14702,7 +14702,7 @@ public class Book { ]]>

      - This XML configuration can now be checked in and versioned, and modified independently from your live database schema. + This XML configuration can now be checked in and versioned, and modified independently from your live database schema.

    @@ -14717,14 +14717,14 @@ public class Book { - - + ]]> @@ -14743,7 +14743,7 @@ public class Book { generate-sources - @@ -14755,7 +14755,7 @@ public class Book { - + @@ -14769,7 +14769,7 @@ public class Book { ]]> - +
    Running the code generator with Gradle @@ -14777,7 +14777,7 @@ public class Book {

    We recommend using the Gradle plugin by Etienne Studer (from Gradle Inc.). It provides a concise DSL that allows you to tune all configuration properties supported by each jOOQ version. Please direct any support questions or issues you may find directly to the third party plugin vendor.

    - +

    Alternatively, the XML MarkupBuilder can be used

    If you don't want to use the above third party plugin, there's also the possibility to use jOOQ's standalone code generator for simplicity. The following working example build.gradle script should work out of the box: @@ -14871,11 +14871,11 @@ org.jooq.util.GenerationTool.generate(

    When writing unit tests for your data access layer, you have probably used some generic mocking tool offered by popular providers like Mockito, jmock, mockrunner, or even DBUnit. With jOOQ, you can take advantage of the built-in JDBC mock API that allows you to emulate a simple database on the JDBC level for precisely those SQL/JDBC use cases supported by jOOQ.

    - +

    - Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider. + Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider.

    - +

    Mocking the JDBC API

    JDBC is a very complex API. It takes a lot of time to write a useful and correct mock implementation, implementing at least these interfaces: @@ -14888,16 +14888,16 @@ org.jooq.util.GenerationTool.generate(

  • - +

    Optionally, you may even want to implement interfaces, such as , , , and many others. In addition to the above, you might need to find a way to simultaneously support incompatible JDBC minor versions, such as 4.0, 4.1

    - +

    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 :

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    As you can see, the configuration setup is simple. Now, the MockDataProvider acts as your single point of contact with JDBC / jOOQ. It unifies any of these execution modes, transparently:

    - +
    • Statements without results
    • Statements without results but with generated keys
    • @@ -14920,16 +14920,16 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
    • Batch statements with single queries and multiple bind value sets
    • Batch statements with multiple queries and no bind values
    - +

    The above are the execution modes supported by jOOQ. Whether you're using any of jOOQ's various fetching modes (e.g. , , , ) is irrelevant, as those modes are all built on top of the standard JDBC API.

    - +

    Implementing MockDataProvider

    Now, here's how to implement MockDataProvider:

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc // 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 String sql = ctx.sql(); - + // Exceptions are propagated through the JDBC and jOOQ APIs if (sql.toUpperCase().startsWith("DROP")) { throw new SQLException("Statement not supported: " + sql); } - + // You decide, whether any given statement returns results, and how many else if (sql.toUpperCase().startsWith("SELECT")) { - + // Always return one author record Result result = create.newResult(AUTHOR); result.add(create.newRecord(AUTHOR)); @@ -14957,12 +14957,12 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc result.get(0).setValue(AUTHOR.LAST_NAME, "Orwell"); mock[0] = new MockResult(1, result); } - + // You can detect batch statements easily else if (ctx.batch()) { // [...] } - + return mock; } }]]> @@ -14974,17 +14974,17 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • : The number of affected rows
  • : The result set
  • - +

    You should return as many MockResult objects as there were query executions (in ) or results (in ). Instead of an awkward JDBC ResultSet, however, you can construct a "friendlier" with your own record types. The jOOQ mock API will use meta data provided with this Result in order to create the necessary JDBC

    - +

    See the for a list of rules that you should follow.

    - +
    SQL 2 jOOQ Parser @@ -14994,20 +14994,20 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    Gudu Software Ltd has been selling enterprise quality SQL software to hundreds of customers to help them migrate from one database to another using the General SQL Parser. Now you can take advantage of their knowledge to parse your SQL statements and transform them directly into jOOQ statements using a free trial version of SQL 2 jOOQ!

    - +

    It's as simple as this!

    - +
    • Create a JDBC connection
    • Create a new SQL2jOOQ converter object
    • Convert your SQL code
    • Get the result
    - +

    See it in action:

    - + If all goes well, the above program yields:

    - + > result = create.select( Actor.ACTOR.FIRST_NAME, Actor.ACTOR.LAST_NAME ) @@ -15071,21 +15071,21 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    Please take note of the fact that the sql2jooq library is Open Source, but it depends on the commercial gsp.jar parser, whose trial licensing terms can be seen here:

    - +

    https://github.com/sqlparser/sql2jooq/blob/master/sql2jooq/LICENSE-GSQLPARSER.txt

    - +

    For more information about the General SQL Parser, please refer to the product blog.

    - +

    Please report any issues, ideas, wishes to the jOOQ user group or the sql2jooq GitHub project.

    - +
    jOOQ Console @@ -15134,7 +15134,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • Sybase Adaptive Server Enterprise 15.5
  • Sybase SQL Anywhere 12
  • - +

    For an up-to-date list of currently supported RDBMS, please refer to http://www.jooq.org/legal/licensing/#databases.

    @@ -15155,7 +15155,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME, This chapter should document the most important notes about SQL, JDBC and jOOQ data types.

    - +
    BLOBs and CLOBs @@ -15165,7 +15165,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    Unsigned integer types @@ -15189,7 +15189,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
    - +
    INTERVAL data types @@ -15200,11 +15200,11 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • YEAR TO MONTH: This interval type models a number of months and years
  • DAY TO SECOND: This interval type models a number of days, hours, minutes, seconds and milliseconds
  • - +

    Both interval types ship with a variant of subtypes, such as DAY TO HOUR, HOUR TO SECOND, etc. jOOQ models these types as Java objects extending : (where Number.intValue() corresponds to the absolute number of months) and (where Number.intValue() corresponds to the absolute number of milliseconds)

    - +

    Interval arithmetic

    In addition to the documented previously, interval arithmetic is also supported by jOOQ. Essentially, the following operations are supported: @@ -15219,7 +15219,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    XML data types @@ -15228,7 +15228,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    Geospacial data types @@ -15238,7 +15238,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    CURSOR data types @@ -15247,22 +15247,22 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    > cursor;]]> - +

    In fact, such a cursor will be fetched immediately by jOOQ and wrapped in an object.

    - +
    ARRAY and TABLE data types

    The SQL standard specifies ARRAY data types, that can be mapped to Java arrays as such:

    - + intArray;]]> - +

    The above array type is supported by these SQL dialects:

    @@ -15271,33 +15271,33 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • HSQLDB
  • Postgres
  • - +

    Oracle typed arrays

    Oracle has strongly-typed arrays and table types (as opposed to the previously seen anonymously typed arrays). These arrays are wrapped by types.

    - +
    Oracle DATE data type

    - Oracle's DATE data type does not conform to the SQL standard. It is really a TIMESTAMP(0), i.e. a TIMESTAMP with a fractional second precision of zero. The most appropriate JDBC type for Oracle DATE types is . + Oracle's DATE data type does not conform to the SQL standard. It is really a TIMESTAMP(0), i.e. a TIMESTAMP with a fractional second precision of zero. The most appropriate JDBC type for Oracle DATE types is .

    - +

    Performance implications

    - +

    When binding TIMESTAMP variables to SQL statements, instead of truncating such variables to DATE, the cost based optimiser may choose to widen the database column from DATE to TIMESTAMP using an Oracle INTERNAL_FUNCTION(), which prevents index usage. Details about this behaviour can be seen in this Stack Overflow question.

    - +

    Use a data type binding to work around this issue

    - +

    The best way to work around this issue is to implement a , which generates the CAST expression for every bind variable:

    - + ctx) throws SQLException { render.keyword("cast").sql('(') @@ -15306,15 +15306,15 @@ public final void sql(BindingSQLContext ctx) throws SQLException { }]]>

    Deprecated functionality

    - +

    Historic versions of jOOQ used to support a <dateAsTimestamp/> flag, which can be used with the out-of-the-box as a :

    - + true - + @@ -15333,7 +15333,7 @@ public final void sql(BindingSQLContext ctx) throws SQLException {

    For more information, please refer to . -

    +

    @@ -15345,12 +15345,12 @@ public final void sql(BindingSQLContext ctx) throws SQLException {

    jOOQ takes SQL as an external domain-specific language and maps it onto Java, creating an internal domain-specific language. Internal DSLs cannot 100% implement their external language counter parts, as they have to adhere to the syntax rules of their host or target language (i.e. Java). This section explains the various problems and workarounds encountered and implemented in jOOQ.

    - +

    SQL allows for "keywordless" syntax

    SQL syntax does not always need keywords to form expressions. The clause takes various argument assignments:

    - + UPDATE t SET a = 1, b = 2 update(t).set(a, 1).set(b, 2) @@ -15368,12 +15368,12 @@ public final void sql(BindingSQLContext ctx) throws SQLException {

    In this case, ROW is an actual (optional) SQL keyword, implemented by at least PostgreSQL.

    - +

    SQL contains "composed" keywords

    As most languages, SQL does not attribute any meaning to whitespace. However, whitespace is important when forming "composed" keywords, i.e. SQL clauses composed of several keywords. jOOQ follows standard Java method naming conventions to map SQL keywords (case-insensitive) to Java methods (case-sensitive, camel-cased). Some examples:

    - + GROUP BY ORDER BY @@ -15386,7 +15386,7 @@ whenMatchedThenUpdate()

    Future versions of jOOQ may use all-uppercased method names in addition to the camel-cased ones (to prevent collisions with Java keywords):

    - + GROUP BY ORDER BY @@ -15417,7 +15417,7 @@ WHEN_MATCHED_THEN_UPDATE()

    The above example omits THEN and END keywords in Java. Future versions of jOOQ may comprise a more complete DSL, including such keywords again though, to provide a more 1:1 match for the SQL language.

    - +

    SQL contains "superfluous" syntactic elements

    Some SQL constructs are hard to map to Java, but they are also not really necessary. SQL often expects syntactic parentheses where they wouldn't really be needed, or where they feel slightly inconsistent with the rest of the SQL language. @@ -15454,7 +15454,7 @@ WHEN_MATCHED_THEN_UPDATE()

    jOOQ replaces those keywords by "synonyms":

    - + CASE .. ELSE PIVOT .. FOR .. IN .. @@ -15482,7 +15482,7 @@ pivot(..).on(..).in(..)

    Most SQL operators have to be mapped to descriptive method names in Java, as Java does not allow operator overloading:

    - + , != @@ -15511,7 +15511,7 @@ set(a, b)

    This is less of a syntactic SQL feature than a semantic one. In SQL, objects can be referenced before (i.e. "lexicographically before") they are declared. This is particularly true for

    - + @@ -15522,7 +15522,7 @@ select(t.a).from(t)]]>

    A more sophisticated example are common table expressions (CTE), which are currently not supported by jOOQ:

    - + WITH t(a, b) AS ( SELECT 1, 2 FROM DUAL ) @@ -15534,7 +15534,7 @@ FROM t

    - +
    jOOQ's BNF pseudo-notation @@ -15543,7 +15543,7 @@ FROM t

    - +
    Quality Assurance @@ -15555,16 +15555,16 @@ FROM t
  • To add lots of type-safety to your inline SQL
  • To increase productivity when writing inline SQL using your favourite IDE's autocompletion capabilities
  • - +

    With jOOQ being in the core of your application, you want to be sure that you can trust jOOQ. That is why jOOQ is heavily unit and integration tested with a strong focus on integration tests:

    - +

    Unit tests

    Unit tests are performed against dummy JDBC interfaces using http://jmock.org/. These tests verify that various implementations render correct SQL and bind variables correctly.

    - +

    Integration tests

    This is the most important part of the jOOQ test suites. Some 1500 queries are currently run against a standard integration test database. Both the test database and the queries are translated into every one of the 14 supported SQL dialects to ensure that regressions are unlikely to be introduced into the code base. @@ -15575,17 +15575,17 @@ FROM t

    jOOQ integration tests run the weirdest and most unrealistic queries. As a side-effect of these extensive integration test suites, many corner-case bugs for JDBC drivers and/or open source databases have been discovered, feature requests submitted through jOOQ and reported mainly to CUBRID, Derby, H2, HSQLDB.

    - +

    Code generation tests

    For every one of the 14 supported integration test databases, source code is generated and the tiniest differences in generated source code can be discovered. In case of compilation errors in generated source code, new test tables/views/columns are added to avoid regressions in this field.

    - +

    API Usability tests and proofs of concept

    jOOQ is used in jOOQ-meta as a proof of concept. This includes complex queries such as the following Postgres query

    - + These rather complex queries show that the jOOQ API is fit for advanced SQL use-cases, compared to the rather simple, often unrealistic queries in the integration test suite.

    - +

    Clean API and implementation. Code is kept DRY

    As a general rule of thumb throughout the jOOQ code, everything is kept DRY. Some examples: @@ -15650,19 +15650,19 @@ for (Record record : create.select(

    - +
    Migrating to jOOQ 3.0

    This section is for all users of jOOQ 2.x who wish to upgrade to the next major release. In the next sub-sections, the most important changes are explained. Some code hints are also added to help you fix compilation errors.

    - +

    Type-safe row value expressions

    Support for has been added in jOOQ 2.6. In jOOQ 3.0, many API parts were thoroughly (but often incompatibly) changed, in order to provide you with even more type-safety.

    - +

    Here are some affected API parts:

    @@ -15672,11 +15672,11 @@ for (Record record : create.select(
  • IN predicates and comparison predicates taking subselects changed incompatibly
  • INSERT and MERGE statements now take typesafe VALUES() clauses
  • - +

    Some hints related to row value expressions:

    - + record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result> result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch(); @@ -15684,31 +15684,31 @@ Result> result = create.select(BOOK.TITLE, BOOK.ID).fro // But Record2 extends Record. You don't have to use the additional typesafety: Record record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch();]]> - +

    SelectQuery and SelectXXXStep are now generic

    In order to support type-safe row value expressions and type-safe Record[N] types, SelectQuery is now generic: SelectQuery<R>

    - +

    SimpleSelectQuery and SimpleSelectXXXStep API were removed

    The duplication of the SELECT API is no longer useful, now that SelectQuery and SelectXXXStep are generic.

    - +

    Factory was split into DSL (query building) and DSLContext (query execution)

    The pre-existing Factory class has been split into two parts:

    - +
    1. 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
    2. 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 renamed to DSLContext. An example:

    - + - +

    Quantified comparison predicates

    Field.equalAny(...) and similar methods have been removed in favour of Field.equal(any(...)). This greatly simplified the Field API. An example:

    - + > subselect = any(select(BOOK.ID).from(BOOK)); Condition condition = BOOK.ID.equal(subselect);]]> - +

    FieldProvider

    The FieldProvider marker interface was removed. Its methods still exist on FieldProvider subtypes. Note, they have changed names from getField() to field() and from getIndex() to indexOf()

    - +

    GroupField

    GroupField has been introduced as a DSL marker interface to denote fields that can be passed to GROUP BY clauses. This includes all org.jooq.Field types. However, fields obtained from ROLLUP(), CUBE(), and GROUPING SETS() functions no longer implement Field. Instead, they only implement GroupField. An example:

    - + field1a = Factory.rollup(...); // OK Field field2a = Factory.one(); // OK @@ -15754,19 +15754,19 @@ GroupField field1b = DSL.rollup(...); // OK Field field1c = DSL.rollup(...); // Compilation error GroupField field2b = DSL.one(); // OK Field field2c = DSL.one(); // OK]]> - +

    NULL predicate

    Beware! Previously, Field.equal(null) was translated internally to an IS NULL predicate. This is no longer the case. Binding Java "null" to a comparison predicate will result in a regular comparison predicate (which never returns true). This was changed for several reasons:

    - +
    • To most users, this was a surprising "feature".
    • Other predicates didn't behave in such a way, e.g. the IN predicate, the BETWEEN predicate, or the LIKE predicate.
    • Variable binding behaved unpredictably, as IS NULL predicates don't bind any variables.
    • The generated SQL depended on the possible combinations of bind values, which creates unnecessary hard-parses every time a new unique SQL statement is rendered.
    - +

    Here is an example how to check if a field has a given value, without applying SQL's ternary NULL logic:

    @@ -15779,7 +15779,7 @@ Condition condition1 = BOOK.TITLE.equal(possiblyNull); // jOOQ 3.0 Condition condition2 = BOOK.TITLE.equal(possiblyNull).or(BOOK.TITLE.isNull().and(val(possiblyNull).isNull())); Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    Configuration

    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 @@ -15793,7 +15793,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> In order to resolve confusion that used to arise because of different lifecycle durations, these types are now no longer formally connected through inheritance.

    - +

    ConnectionProvider

    In order to allow for simpler connection / data source management, jOOQ externalised connection handling in a new ConnectionProvider type. The previous two connection modes are maintained backwards-compatibly (JDBC standalone connection mode, pooled DataSource mode). Other connection modes can be injected using: @@ -15803,24 +15803,24 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    These are some side-effects of the above change

    - +
    • 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. This resolves many class loader issues that were encountered before. It also helps listener implementations control their lifecycles themselves.

    - +

    Data type API

    The data type API has been changed drastically in order to enable some new DataType-related features. These changes include: @@ -15830,16 +15830,16 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]>[SQLDialect]DataType and SQLDataType no longer implement DataType. They're mere constant containers

  • Various minor API changes have been done.
  • - +

    Object renames

    These objects have been moved / renamed:

    - +
    • jOOU: a library used to represent unsigned integer types was moved from org.jooq.util.unsigned to org.jooq.util.types (which already contained INTERVAL data types)
    - +

    Feature removals

    Here are some minor features that have been removed in jOOQ 3.0 @@ -15933,7 +15933,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> --> diff --git a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.7.xml b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.7.xml index a0f86357d6..a312424a99 100644 --- a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.7.xml +++ b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.7.xml @@ -126,7 +126,7 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ's reason for being - compared to SQL / JDBC

    So why not just use SQL? @@ -149,14 +149,14 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ is different

    SQL was never meant to be abstracted. To be confined in the narrow boundaries of heavy mappers, hiding the beauty and simplicity of relational data. SQL was never meant to be object-oriented. SQL was never meant to be anything other than... SQL!

    - + - +
    Getting started with jOOQ @@ -346,12 +346,12 @@ limitations under the License.

    This section helps you correctly interpret this manual in the context of jOOQ.

    - +

    Code blocks

    The following are code blocks:

    - + @@ -367,7 +367,7 @@ org.jooq.property=value]]>

    These are useful to provide examples in code. Often, with jOOQ, it is even more useful to compare SQL code with its corresponding Java/jOOQ code. When this is done, the blocks are aligned side-by-side, with SQL usually being on the left, and an equivalent jOOQ DSL query in Java usually being on the right:

    - + @@ -379,17 +379,17 @@ create.selectOne().fetch()]]>

    The contents of code blocks follow conventions, too. If nothing else is mentioned next to any given code block, then the following can be assumed:

    - - + + - +

    Your naming may differ, of course. For instance, you could name the "create" instance "db", instead.

    - +

    Execution

    - +

    When you're coding PL/SQL, T-SQL or some other procedural SQL language, SQL statements are always executed immediately at the semi-colon. This is not the case in jOOQ, because as an internal DSL, jOOQ can never be sure that your statement is complete until you call fetch() or execute(). The manual tries to apply fetch() and execute() as thoroughly as possible. If not, it is implied:

    @@ -429,7 +429,7 @@ create.update(T).set(T.V, 1).execute();]]>

    jOOQ allows to override runtime behaviour using . If nothing is specified, the default runtime settings are assumed.

    - +

    Sample database

    jOOQ query examples run against the sample database. See the manual's section about to learn more about the sample database. @@ -464,7 +464,7 @@ CREATE TABLE book ( title VARCHAR2(400) NOT NULL, published_in NUMBER(7) NOT NULL, language_id NUMBER(7) NOT NULL, - + CONSTRAINT fk_book_author FOREIGN KEY (author_id) REFERENCES author(id), CONSTRAINT fk_book_language FOREIGN KEY (language_id) REFERENCES language(id) ); @@ -477,7 +477,7 @@ CREATE TABLE book_to_book_store ( name VARCHAR2(400) NOT NULL, book_id INTEGER NOT NULL, stock INTEGER, - + PRIMARY KEY(name, book_id), CONSTRAINT fk_b2bs_book_store FOREIGN KEY (name) REFERENCES book_store (name) ON DELETE CASCADE, CONSTRAINT fk_b2bs_book FOREIGN KEY (book_id) REFERENCES book (id) ON DELETE CASCADE @@ -488,7 +488,7 @@ CREATE TABLE book_to_book_store (

    In addition to the above, you may assume the following sample data:

    - + Effectively, jOOQ was originally designed to replace any other database abstraction framework short of the ones handling connection pooling (and more sophisticated )

    - +

    Use jOOQ the way you prefer

    ... but open source is community-driven. And the community has shown various ways of using jOOQ that diverge from its original intent. Some use cases encountered are: @@ -547,7 +547,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]>Using jOOQ for SQL building and Spring Data for SQL execution

  • Using jOOQ without the to build the basis of a framework for dynamic SQL execution.
  • - +

    The following sections explain about various use cases for using jOOQ in your application.

    @@ -560,7 +560,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]> This is the most simple of all use cases, allowing for construction of valid SQL for any database. In this use case, you will not use and probably not even . Instead, you'll use to wrap strings, literals and other user-defined objects into an object-oriented, type-safe AST modelling your SQL statements. An example is given here:

    - + - +

    The SQL string built with the jOOQ query DSL can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools (note that since jOOQ uses PreparedStatement by default, this will generate a bind variable for "1948". ).

    @@ -597,7 +597,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID)) .where(BOOK.PUBLISHED_IN.equal(1948)) .getSQL();]]> - +

    The SQL string that you can generate as such can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools.

    @@ -617,7 +617,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    Instead of any tool mentioned in the previous chapters, you can also use jOOQ directly to execute your jOOQ-generated SQL statements. This will add a lot of convenience on top of the previously discussed API for typesafe SQL construction, when you can re-use the information from generated classes to fetch records and custom data types. An example is given here:

    - + > result = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) @@ -671,10 +671,10 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { // Skip previously distinguished authors if ((int) author.getDistinguished() == 1) continue; - + // Check if the author has written more than 5 books if (author.fetchChildren(Keys.FK_BOOK_AUTHOR).size() > 5) { - + // Mark the author as a "distinguished" author author.setDistinguished(1); author.store(); @@ -691,7 +691,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {
    - +
    jOOQ for PROs @@ -729,7 +729,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { This manual section is intended for new users, to help them get a running application with jOOQ, quickly.

    - +
    Step 1: Preparation @@ -738,13 +738,13 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { If you haven't already downloaded it, download jOOQ:
    http://www.jooq.org/download

    - +

    Alternatively, you can create a Maven dependency to download jOOQ artefacts:

    - +

    Open Source Edition

    - + org.jooq jooq @@ -760,9 +760,9 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { jooq-codegen {jooq-version} ]]> - +

    Commercial Editions (Java 8+)

    - + org.jooq.pro @@ -779,9 +779,9 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { jooq-codegen {jooq-version} ]]> - +

    Commercial Editions (Java 6+)

    - + org.jooq.pro-java-6 @@ -798,22 +798,22 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { jooq-codegen {jooq-version} ]]> - +

    Commercial Editions (Free Trial)

    - + - org.jooq + org.jooq.trial jooq {jooq-version} - org.jooq + org.jooq.trial jooq-meta {jooq-version} - org.jooq + org.jooq.trial jooq-codegen {jooq-version} ]]> @@ -821,7 +821,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    Note that only the jOOQ Open Source Edition is available from Maven Central. If you're using the jOOQ Professional Edition or the jOOQ Enterprise Edition, you will have to manually install jOOQ in your local Nexus, or in your local Maven cache. For more information, please refer to the licensing pages.

    - +

    Please refer to the manual's section about to learn how to use jOOQ's code generator with Maven.

    @@ -836,14 +836,14 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    - +
    Step 2: Your database

    We're going to create a database called "library" and a corresponding "author" table. Connect to MySQL via your command line client and type the following:

    - + CREATE DATABASE `library`; USE `library`; @@ -857,7 +857,7 @@ CREATE TABLE `author` (
    - +
    Step 3: Code generation @@ -869,7 +869,7 @@ CREATE TABLE `author` (

    The easiest way to generate a schema is to copy the jOOQ jar files (there should be 3) and the MySQL Connector jar file to a temporary directory. Then, create a library.xml that looks like this:

    - + @@ -926,7 +926,7 @@ CREATE TABLE `author` (

    generator.target.directory - the directory to output to.

    - +

    Once you have the JAR files and library.xml in your temp directory, type this on a Windows machine:

    @@ -946,7 +946,7 @@ CREATE TABLE `author` (

    Note: jOOQ will try loading the library.xml from your classpath. This is also why there is a trailing period (.) on the classpath. If the file cannot be found on the classpath, jOOQ will look on the file system from the current working directory.

    - +

    Replace the filenames with your actual filenames. In this example, jOOQ {jooq-version} is being used. If everything has worked, you should see this in your console output:

    @@ -1008,17 +1008,17 @@ INFO: Packages fetched : 0 (0 included, 0 excluded) Nov 1, 2011 7:25:08 PM org.jooq.impl.JooqLogger info INFO: GENERATION FINISHED! : Total: 791.688ms, +9.143ms - +
    - +
    Step 4: Connect to your database

    Let's just write a vanilla main class in the project containing the generated classes:

    - +
    - +
    Step 5: Querying

    Let's add a simple query constructed with jOOQ's query DSL:

    - + result = create.select().from(AUTHOR).fetch();]]> @@ -1068,7 +1068,7 @@ Result result = create.select().from(AUTHOR).fetch();]]>

    - +
    Step 6: Iterating @@ -1087,7 +1087,7 @@ Result result = create.select().from(AUTHOR).fetch();]]>

    The full program should now look like this:

    - +
    - +
    Step 7: Explore! @@ -1183,7 +1183,7 @@ public class Main {
  • Another example using Spring and Guice for transaction management can be downloaded from GitHub.
  • Another, excellent tutorial by Petri Kainulainen can be found here.
  • - +

    Add the required Maven dependencies

    For this example, we'll create the following Maven dependencies @@ -1199,11 +1199,11 @@ public class Main { org.jooq jooq @@ -1269,7 +1269,7 @@ public class Main {

    The above dependencies are configured together using a Spring Beans configuration:

    - + - + - + @@ -1327,7 +1327,7 @@ public class Main { - + ]]> @@ -1378,7 +1378,7 @@ public class QueryTest {

    The following example shows how you can use Spring's TransactionManager to explicitly handle transactions:

    - +
    - +
    Using jOOQ with Flyway

    Flyway - Database Migrations Made EasyWhen performing database migrations, we at Data Geekery recommend using jOOQ with Flyway - Database Migrations Made Easy. In this chapter, we're going to look into a simple way to get started with the two frameworks.

    - +

    Philosophy

    - +

    There are a variety of ways how jOOQ and Flyway could interact with each other in various development setups. In this tutorial we're going to show just one variant of such framework team play - a variant that we find particularly compelling for most use cases.

    - +

    The general philosophy behind the following approach can be summarised as this:

    - +
    • 1. Database increment
    • 2. Database migration
    • 3. Code re-generation
    • 4. Development
    - +

    The four steps above can be repeated time and again, every time you need to modify something in your database. More concretely, let's consider:

    - +
    • 1. Database increment - You need a new column in your database, so you write the necessary DDL in a Flyway script
    • 2. Database migration - This Flyway script is now part of your deliverable, which you can share with all developers who can migrate their databases with it, the next time they check out your change
    • @@ -1524,23 +1524,23 @@ public class TransactionTest { ]]>

      0. Maven Project Configuration - Dependencies

      - +

      While jOOQ and Flyway could be used in standalone migration scripts, in this tutorial, we'll be using Maven for the standard project setup. You will also find the source code of this tutorial on GitHub at https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-flyway-example, and the full pom.xml file here.

      - +

      These are the dependencies that we're using in our Maven configuration:

      - + org.jooq jooq @@ -1618,11 +1618,11 @@ public class TransactionTest { org.jooq jooq-codegen-maven @@ -1879,14 +1879,14 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre;

    - +
    Using jOOQ with JAX-RS

    In some use-cases, having a lean, single-tier server-side architecture is desirable. Typically, such architectures expose a RESTful API implementing client code and the UI using something like AngularJS.

    - +

    In Java, the standard API for RESTful applications is JAX-RS, which is part of JEE 7, along with a standard JSON implementation. But you can use JAX-RS also outside of a JEE container. The following example shows how to set up a simple license server using these technologies:

    @@ -1899,9 +1899,9 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre;

    For the example, we'll use a PostgreSQL database.

    - +

    Creating the license server database

    - +

    We'll keep the example simple and use a LICENSE table to store all license keys and associated information, whereas a LOG_VERIFY table is used to log access to the license server. Here's the DDL:

    @@ -1913,7 +1913,7 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre; LICENSEE TEXT NOT NULL, -- The e-mail address of the licensee LICENSE TEXT NOT NULL, -- The license key VERSION VARCHAR(50) NOT NULL DEFAULT '.*', -- The licensed version(s), a regular expression - + CONSTRAINT PK_LICENSE PRIMARY KEY (ID), CONSTRAINT UK_LICENSE UNIQUE (LICENSE) ); @@ -1926,7 +1926,7 @@ CREATE TABLE LICENSE_SERVER.LOG_VERIFY ( REQUEST_IP VARCHAR(50) NOT NULL, -- The request IP verifying the license VERSION VARCHAR(50) NOT NULL, -- The version that is being verified MATCH BOOLEAN NOT NULL, -- Whether the verification was successful - + CONSTRAINT PK_LOG_VERIFY PRIMARY KEY (ID) );]]> @@ -1948,13 +1948,13 @@ $$ LANGUAGE PLPGSQL;

    The actual algorithm might be using a secret salt to hash the function arguments. For the sake of a tutorial, a constant string will suffice.

    - +

    Setting up the project

    - +

    We're going to be setting up the

    - + 9966 - + org.jooq jooq-codegen-maven @@ -2027,14 +2027,14 @@ $$ LANGUAGE PLPGSQL; servlet-api 2.5 - + org.jooq jooq @@ -2056,13 +2056,13 @@ $$ LANGUAGE PLPGSQL;

    With the above setup, we're now pretty ready to start developing our license service as a JAX-RS service.

    - +

    The license service class

    - +

    Once we've run the , we can write the following service class:

    - + /license/verify checks if a given licensee has access to version using a license. * @@ -2122,7 +2122,7 @@ public class LicenseService { @Override public String run(DSLContext ctx) { String v = (version == null || version.equals("")) ? "" : version; - + // Use the jOOQ query DSL API to generate a log entry return ctx.insertInto(LOG_VERIFY) @@ -2143,10 +2143,10 @@ public class LicenseService { } }); } - + // [...] }]]> - +

    The INSERT INTO LOG_VERIFY query is actually rather interesting. In plain SQL, it would look like this:

    @@ -2175,7 +2175,7 @@ RETURNING MATCH;]]> .set(new DefaultConnectionProvider(c)) .set(SQLDialect.POSTGRES) .set(new Settings().withExecuteLogging(false))); - + return runnable.run(ctx); } catch (Exception e) { @@ -2184,13 +2184,13 @@ RETURNING MATCH;]]> return "Service Unavailable - Please contact support@datageekery.com for help"; } } - + private interface CtxRunnable { String run(DSLContext ctx); }]]>

    Configuring Spring and Jetty

    - +

    All we need now is to configure Spring...

    @@ -2248,7 +2248,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/sch

    Using the license server

    - +

    You can now use the license server at the following URLs

    @@ -2265,7 +2265,7 @@ http://localhost:8088/jooq-jax-rs-example/license/verify?mail=test@example.com&l

    Let's verify what happened, in the database:

    - + - +

    Downloading the complete example

    - +

    The complete example can be downloaded for free and under the terms of the Apache Software License 2.0 from here:
    https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-jax-rs-example @@ -2295,21 +2295,21 @@ select * from license_server.log_verify

    - +
    jOOQ and Java 8

    Java 8 has introduced a great set of enhancements, among which lambda expressions and the new Streams API. These new constructs align very well with jOOQ's fluent API as can be seen in the following examples:

    - +

    jOOQ and lambda expressions

    jOOQ's API is fully Java-8-ready, which basically means that it is a SAM (Single Abstract Method) type, which can be instanciated using a lambda expression. Consider this example:

    - + - +

    The above example shows how jOOQ's method can receive a lambda expression that implements to map from jOOQ to your custom types.

    - +

    jOOQ and the Streams API

    @@ -2370,7 +2370,7 @@ select * from license_server.log_verify // Just emit a CREATE TABLE statement System.out.println( "CREATE TABLE " + table + " ("); - + // Map each "Column" type into a String // containing the column specification, // and join them using comma and @@ -2381,15 +2381,15 @@ select * from license_server.log_verify " " + col.type) .collect(Collectors.joining(",\n")) ); - + System.out.println(");"); } );]]> - +

    The above example is explained more in depth in this blog post: http://blog.jooq.org/2014/04/11/java-8-friday-no-more-need-for-orms/. For more information about Java 8, consider these resources:

    - +
    - +
    jOOQ and Nashorn

    With Java 8 and the new built-in JavaScript engine Nashorn, a whole new ecosystem of software can finally make easy use of jOOQ in server-side JavaScript. A very simple example can be seen here:

    - +

    - More details about how to use jOOQ, JDBC, and SQL with Nashorn can be seen here. + More details about how to use jOOQ, JDBC, and SQL with Nashorn can be seen here.

    - +
    jOOQ and Scala @@ -2622,7 +2622,7 @@ print(
  • Type inference using "var" and "val" keywords
  • Lambda expressions and for-comprehension syntax for record iteration and data type conversion
  • - +

    But jOOQ also leverages other useful Scala features, such as

    @@ -2630,15 +2630,15 @@ print(
  • implicit defs for operator overloading
  • Scala Macros (soon to come)
  • - +

    All of the above heavily improve jOOQ's querying DSL API experience for Scala developers.

    - +

    A short example jOOQ application in Scala might look like this:

    - +
    - - + +
    jOOQ and Groovy @@ -2701,7 +2701,7 @@ object Test { //

    A short example jOOQ application in Groovy might look like this:

    - +
    - - + +
    jOOQ and Kotlin @@ -2752,7 +2752,7 @@ DSL.using(sql.connection)

    A short example jOOQ application in Kotlin might look like this:

    - + ) { properties.getProperty("db.url"), properties.getProperty("db.username"), properties.getProperty("db.password") - + // The below "use" method is an adapted version of the one in kotlin.io // See also: https://github.com/JetBrains/kotlin/pull/807 ).use { @@ -2798,7 +2798,7 @@ fun main(args: Array) {

    - +
    jOOQ and NoSQL @@ -2816,7 +2816,7 @@ fun main(args: Array) {

    - +
    Dependencies @@ -2834,7 +2834,7 @@ fun main(args: Array) {
    - +
    Build your own @@ -2863,7 +2863,7 @@ fun main(args: Array) {
    - +
    jOOQ and backwards-compatibility @@ -2875,7 +2875,7 @@ fun main(args: Array) {
  • If a minor release includes backwards-compatible, API-relevant new features, [Y] is incremented by one and [Z] is reset to zero.
  • If a major release includes backwards-incompatible, API-relevant new features, [X] is incremented by one and [Y], [Z] are reset to zero.
  • - +

    jOOQ's understanding of backwards-compatibility

    Backwards-compatibility is important to jOOQ. You've chosen jOOQ as a strategic SQL engine and you don't want your SQL to break. That is why there is at most one major release per year, which changes only those parts of jOOQ's API and functionality, which were agreed upon on the user group. During the year, only minor releases are shipped, adding new features in a backwards-compatible way @@ -2888,15 +2888,15 @@ fun main(args: Array) {

  • Overloading methods for convenience
  • Changing the type hierarchy of interfaces
  • - +

    It becomes obvious that it would be impossible to add new language elements (e.g. new , new ) to the API without breaking any client code that actually implements those interfaces. Hence, the following rule should be observed:

    - +

    jOOQ's DSL interfaces should not be implemented by client code! Extend only those extension points that are explicitly documented as "extendable" (e.g. )

    - +

    jOOQ-codegen and jOOQ-meta

    While a reasonable amount of care is spent to maintain these two modules under the rules of semantic versioning, it may well be that minor releases introduce backwards-incompatible changes. This will be announced in the respective release notes and should be the exception. @@ -2924,7 +2924,7 @@ fun main(args: Array) { - +

    The query DSL type @@ -2955,7 +2955,7 @@ fun main(args: Array) { // ... which is in fact the same as: DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    DSL subclasses @@ -2974,7 +2974,7 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME));
    - + @@ -2983,14 +2983,14 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    The DSLContext class

    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.

    - +

    Fluent creation of a DSLContext object

    The DSLContext object can be created fluently from the : @@ -3005,7 +3005,7 @@ DSLContext create = DSL.using(connection, dialect);]]>

    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

    A Configuration can be supplied with these objects: @@ -3024,7 +3024,7 @@ DSLContext create = DSL.using(connection, dialect);]]> - +

    Wrapping a Configuration object, a DSLContext can construct , for later . An example is given here:

    @@ -3066,7 +3066,7 @@ DSL.using(connection, dialect) CONNECT BY clause to the query */ -@Support({ SQLDialect.CUBRID, SQLDialect.}) +@Support({ SQLDialect.CUBRID, SQLDialect.ORACLE }) SelectConnectByConditionStep connectBy(Condition condition);]]>

    @@ -3088,7 +3088,7 @@ SelectSelectStep select(Field... fields);]]>

    Nevertheless, the IS DISTINCT FROM predicate is supported by jOOQ in all dialects, as its semantics can be expressed with an equivalent . For more details, see the manual's section about the .

    - +

    jOOQ and the Oracle SQL dialect

    Oracle SQL is much more expressive than many other SQL dialects. It features many unique keywords, clauses and functions that are out of scope for the SQL standard. Some examples for this are @@ -3112,13 +3112,13 @@ SelectSelectStep select(Field... fields);]]>

    In jOOQ 3.1, the notion of a SQLDialect.family() was introduced, in order to group several similar into a common family. An example for this is SQL Server, which is supported by jOOQ in various versions:

    - +
    • : The "version-less" SQL Server version. This always maps to the latest supported version of SQL Server
    • : The SQL Server version 2012
    • : The SQL Server version 2008
    - +

    In the above list, SQLSERVER is both a dialect and a family of three dialects. This distinction is used internally by jOOQ to distinguish whether to use the clause (SQL Server 2012), or whether to emulate it using ROW_NUMBER() OVER() (SQL Server 2008).

    @@ -3135,7 +3135,7 @@ SelectSelectStep select(Field... fields);]]>

    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.

    - +

    Interact with JDBC DataSources

    If you're in a J2EE or Spring context, however, you may wish to use a instead. Connections obtained from such a DataSource will be closed after query execution by jOOQ. The semantics of such a close operation should be the returning of the connection into a connection pool, not the actual closing of the underlying connection. Typically, this makes sense in an environment using distributed JTA transactions. An example of using DataSources with jOOQ can be seen in the tutorial section about . @@ -3143,17 +3143,17 @@ SelectSelectStep select(Field... fields);]]>

    Note, in this case, jOOQ will internally use a , which you can reference directly if you prefer that.

    - +

    Inject custom behaviour

    If your specific environment works differently from any of the above approaches, you can inject your own custom implementation of a ConnectionProvider into jOOQ. This is the API contract you have to fulfil:

    - + @@ -3163,19 +3163,19 @@ 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...

    - +
    - +

    Here is an example of how to use the custom data API. Let's assume that you have written an , that prevents INSERT statements, when a given flag is set to true:

    @@ -3185,10 +3185,10 @@ public class NoInsertListener extends DefaultExecuteListener { @Override public void start(ExecuteContext ctx) { - + // This listener is active only, when your custom flag is set to true 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) { throw new DataAccessException("No INSERT statements allowed"); @@ -3199,11 +3199,11 @@ public class NoInsertListener extends DefaultExecuteListener {

    See the manual's section about to learn more about how to implement an ExecuteListener.

    - +

    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:

    - + ExecuteListeners are a useful tool to...

    - +
    • implement custom logging
    • apply triggers written in Java
    • collect query execution statistics
    - +

    ExecuteListeners are hooked into your by returning them from an :

    @@ -3261,7 +3261,7 @@ configuration.set( new DefaultExecuteListenerProvider(new PerformanceLoggingListener()), new DefaultExecuteListenerProvider(new NoInsertListener()) );]]>
    - +

    See the manual's section about to see examples of such listener implementations.

    @@ -3305,22 +3305,22 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - +

    All Settings

    - +

    This section of the manual explains all the available Settings flags as available from the XSD specification.

    - + false - + ... @@ -3331,17 +3331,17 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - UPPER_CASED : UPPER - lower_cased : LOWER - CasedAsReportedByTheDatabase : AS_IS - + Defaults to "QUOTED" --> LOWER UPPER - + false @@ -3349,54 +3349,54 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - question marks : INDEXED - named parameters : NAMED - inlined values : INLINED - + Defaults to "INDEXED". - + This value is overridden by statementType == STATIC_STATEMENT, in case of which, this defaults to INLINED --> INDEXED - + PREPARED_STATEMENT - + true false true false ]]> - +

    More details

    - +

    Please refer to the jOOQ runtime configuration XSD for more details:
    http://www.jooq.org/xsd/jooq-runtime-{runtime-xsd-version}.xsd

    - +
    Runtime schema and table mapping @@ -3404,7 +3404,7 @@ DSLContext create = DSL.using(connection, dialect, settings);]]>

    You may wish to design your database in a way that you have several instances of your schema. This is useful when you want to cleanly separate data belonging to several customers / organisation units / branches / users and put each of those entities' data in a separate database or schema.

    - +

    In our AUTHOR example this would mean that you provide a book reference database to several companies, such as My Book World and Books R Us. In that case, you'll probably have a schema setup like this:

    @@ -3434,7 +3434,7 @@ create.selectFrom(AUTHOR).fetch();

    The query executed with a Configuration equipped with the above mapping will in fact produce this SQL statement:

    - + SELECT * FROM MY_BOOK_WORLD.AUTHOR

    Even if AUTHOR was generated from DEV. @@ -3509,7 +3509,7 @@ create.selectFrom(AUTHOR).fetch();

    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

    @@ -3543,7 +3543,7 @@ create.selectFrom(AUTHOR).fetch();

    Here is an example to illustrate what that means:

    - + 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) @@ -3615,7 +3615,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); @@ -3642,7 +3642,7 @@ query.addJoin(BOOK, BOOK.AUTHOR_ID.equal(AUTHOR.ID));]]>

    Note, that for historic reasons, the DSL API mixes mutable and immutable behaviour with respect to the internal representation of the being constructed. While creating , (such as functions) assumes immutable behaviour, creating does not. In other words, the following can be said:

    - + select2 = create.selectOne().fetch();]]>

    jOOQ does not explicitly support the asterisk operator in projections. However, you can omit the projection as in these examples:

    - +

    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:

    - + select(Collection> fields); public static SelectSelectStep select(Field... fields); @@ -3924,14 +3924,14 @@ public static SelectSelectStep> select(Field SelectSelectStep> select(Field field1, Field field2); public static SelectSelectStep> select(Field field1, Field field2, Field field3); // [...]]]> - +

    Since the generic R type is bound to some , the associated T type information can be used in various other contexts, e.g. the . Such a SELECT statement can be assigned typesafely:

    > s1 = create.select(BOOK.ID, BOOK.TITLE); Select> s2 = create.select(BOOK.ID, trim(BOOK.TITLE));]]> - +

    For more information about typesafe record types with degree up to {max-row-degree}, see the manual's section about .

    @@ -3957,7 +3957,7 @@ create.selectOne().from(BOOK.as("b"), AUTHOR.as("a")).fetch();]]>

    Read more about aliasing in the manual's section about .

    - +

    More advanced table expressions

    Apart from simple tables, you can pass any arbitrary to the jOOQ FROM clause. This may include in Oracle: @@ -4015,11 +4015,11 @@ DSL.using(SQLDialect.POSTGRES).selectOne().fetch();]]>

  • NATURAL LEFT [ OUTER ] JOIN
  • NATURAL RIGHT [ OUTER ] JOIN
  • - +

    Besides, jOOQ also supports

    - +
    • CROSS APPLY (T-SQL and Oracle 12c specific)
    • OUTER APPLY (T-SQL and Oracle 12c specific)
    • @@ -4149,7 +4149,7 @@ ON BOOK.AUTHOR_ID = AUTHOR.ID

      SEMI JOIN and ANTI JOIN

      - Very few databases (e.g. Apache Impala) ship with a built-in syntax for { LEFT | RIGHT } SEMI JOIN and { LEFT | RIGHT } ANTI JOIN, which are much more concise versions of the SQL standard IN / EXISTS and NOT IN / NOT EXISTS predicates. The idea is that the JOIN syntax is expressed where it belongs, in the FROM clause, not in the WHERE clause. + Very few databases (e.g. Apache Impala) ship with a built-in syntax for { LEFT | RIGHT } SEMI JOIN and { LEFT | RIGHT } ANTI JOIN, which are much more concise versions of the SQL standard IN / EXISTS and NOT IN / NOT EXISTS predicates. The idea is that the JOIN syntax is expressed where it belongs, in the FROM clause, not in the WHERE clause.

      Since jOOQ 3.7, these types of JOIN are also supported and they're emulated using EXISTS and NOT EXISTS respectively. @@ -4157,7 +4157,7 @@ ON BOOK.AUTHOR_ID = AUTHOR.ID

      Here's how SEMI JOIN translates to EXISTS.

      - + - +

      T-SQL's CROSS APPLY and OUTER APPLY

      T-SQL has long known what the SQL standard calls lateral derived tables, lateral joins using the APPLY keyword. To every row resulting from the table expression on the left, we apply the table expression on the right. This is extremely useful for table-valued functions, which are also supported by jOOQ. Some examples:

      - + - +

      The above example shows standard usage of the LATERAL keyword to connect a derived table to the previous table in the . A similar statement can be written in T-SQL:

      - + - +

      While not all forms of LATERAL JOIN have an equivalent APPLY syntax, the inverse is true, and jOOQ can thus emulate OUTER APPLY and CROSS APPLY using LATERAL JOIN.

      - +

      LATERAL JOIN or CROSS APPLY are particularly useful together with , which are also supported by jOOQ.

      @@ -4345,12 +4345,12 @@ ORDER BY 1

      Note that this syntax is also supported in the CUBRID database and might be emulated in other dialects supporting common table expressions in the future.

      - +

      ORDER SIBLINGS

      The Oracle database allows for specifying a SIBLINGS keyword in the . Instead of ordering the overall result, this will only order siblings among each other, keeping the hierarchy intact. An example is given here:

      - + - +
    @@ -4394,7 +4394,7 @@ GROUP BY AUTHOR_ID

    Note, as defined in the SQL standard, when grouping, you may no longer project any columns that are not a formal part of the GROUP BY clause, or .

    - +

    MySQL's deviation from the SQL standard

    MySQL has a peculiar way of not adhering to this standard behaviour. This is documented in the MySQL manual. In short, with MySQL, you can also project any other field that is not part of the GROUP BY clause. The projected values will just be arbitrary values from within the group. You cannot rely on any ordering. For example: @@ -4429,7 +4429,7 @@ GROUP BY () .groupBy() .fetch();]]> - +

    ROLLUP(), CUBE() and GROUPING SETS()

    Some databases support the SQL standard grouping functions and some extensions thereof. See the manual's section about for more details. @@ -4450,7 +4450,7 @@ FROM BOOK GROUP BY AUTHOR_ID HAVING COUNT(*) >= 2 ]]>  -= 4

    - +
    The WINDOW clause

    The SQL:2003 standard as well as PostgreSQL and Sybase SQL Anywhere support a WINDOW clause that allows for specifying WINDOW frames for reuse in and .

    - +   - +

    Note that in order to create such a window definition, we need to first create a using .

    Even if only PostgreSQL and Sybase SQL Anywhere natively support this great feature, jOOQ can emulate it by expanding any and types that you pass to the window() method - if the database supports window functions at all.

    - +

    Some more information about and the WINDOW clause can be found on our blog: http://blog.jooq.org/2013/11/03/probably-the-coolest-sql-feature-window-functions/

    @@ -4648,8 +4648,8 @@ ORDER BY CASE TITLE

    The SQL standard defines that a "query expression" can be ordered, and that query expressions can contain , whose subqueries cannot be ordered. While this is defined as such in the SQL standard, many databases allowing for the in one way or another, do not adhere to this part of the SQL standard. Hence, jOOQ allows for ordering all SELECT statements, regardless whether they are constructed as a part of a UNION or not. Corner-cases are handled internally by jOOQ, by introducing synthetic subselects to adhere to the correct syntax, where this is needed.

    - - + +

    Oracle's ORDER SIBLINGS BY clause

    jOOQ also supports Oracle's SIBLINGS keyword to be used with ORDER BY clauses for @@ -4701,7 +4701,7 @@ SELECT TOP 1 * FROM BOOK

    Things get a little more tricky in those databases that have no native idiom for OFFSET pagination (actual queries may vary):

    - + 1]]>

    As you can see, jOOQ will take care of the incredibly painful ROW_NUMBER() OVER() (or ROWNUM for Oracle) filtering in subselects for you, you'll just have to write limit(1).offset(2) in any dialect.

    - +

    Side-note: If you're interested in understanding why we chose ROWNUM for Oracle, please refer to this very interesting benchmark, comparing the different approaches of doing pagination in Oracle: http://www.inf.unideb.hu/~gabora/pagination/results.html.

    @@ -4748,7 +4748,7 @@ WHERE RN > 1]]>

    - +
    The SEEK clause @@ -4758,7 +4758,7 @@ WHERE RN > 1]]>

    A much faster and more stable way to perform paging is the so-called keyset paging method also called seek method. jOOQ supports a synthetic seek() clause, that can be used to perform keyset paging. Imagine we have these data:

    - + 1]]>

    Now, if we want to display page 6 to the user, instead of going to page 6 by using a record OFFSET, we could just fetch the record strictly after the last record on page 5, which yields the values (533, 2). This is how you would do it with SQL or with jOOQ:

    - + As you can see, the jOOQ SEEK clause is a synthetic clause that does not really exist in SQL. However, the jOOQ syntax is far more intuitive for a variety of reasons:

    - +
    • It replaces OFFSET where you would expect
    • It doesn't force you to mix regular predicates with "seek" predicates
    • It is typesafe
    • It emulates for you, in those databases that do not support them
    - +

    This query now yields:

    - + Note that you cannot combine the SEEK clause with the OFFSET clause.

    - +

    More information about this great feature can be found in the jOOQ blog:

    @@ -4829,11 +4829,11 @@ LIMIT 5
  • http://blog.jooq.org/2013/10/26/faster-sql-paging-with-jooq-using-the-seek-method/
  • http://blog.jooq.org/2013/11/18/faster-sql-pagination-with-keysets-continued/
  • - +

    Further information about offset pagination vs. keyset pagination performance can be found on our partner page:

    - +
    No more offset @@ -4945,7 +4945,7 @@ SELECT * FROM author ORDER BY id DESC;]]>

    SQL allows to perform set operations as understood in standard set theory on result sets. These operations include unions, intersections, subtractions. For two subselects to be combinable by such a set operator, each subselect must return a of the same degree and type.

    - +

    UNION and UNION ALL

    These operators combine two results into one. While UNION removes all duplicate records resulting from this combination, UNION ALL leaves subselect results as they are. Typically, you should prefer UNION ALL over UNION, if you don't really need to remove duplicates. The following example shows how to use such a UNION operation in jOOQ. @@ -4960,16 +4960,16 @@ SELECT * FROM BOOK WHERE ID = 5 .unionAll( create.selectFrom(BOOK).where(BOOK.ID.equal(5))) .fetch();]]> - +

    INTERSECT [ ALL ] and EXCEPT [ ALL ]

    INTERSECT is the operation that produces only those values that are returned by both subselects. EXCEPT (or MINUS in Oracle) is the operation that returns only those values that are returned exclusively in the first subselect. Both operators will remove duplicates from their results.

    - +

    Just like with UNION ALL, these operators have an optional ALL keyword that allows for keeping duplicate rows after intersection or subtraction, which is supported in jOOQ 3.7+.

    - +

    jOOQ's set operators and how they're different from standard SQL

    As previously mentioned in the manual's section about the , jOOQ has slightly changed the semantics of these set operators. While in SQL, a subselect may not contain any or (unless you wrap the subselect into a ), jOOQ allows you to do so. In order to select both the youngest and the oldest author from the database, you can issue the following statement with jOOQ (rendered to the MySQL dialect): @@ -4990,7 +4990,7 @@ ORDER BY 1 .orderBy(AUTHOR.DATE_OF_BIRTH.desc()).limit(1)) .orderBy(1) .fetch();]]> - +

    In case your database doesn't support ordered UNION subselects, the subselects are nested in derived tables:

    @@ -5008,12 +5008,12 @@ SELECT * FROM ( ORDER BY 1]]> - +

    Projection typesafety for degrees between 1 and {max-row-degree}

    Two subselects that are combined by a set operator are required to be of the same degree and, in most databases, also of the same type. jOOQ 3.0's introduction of helps compile-checking these constraints:

    - + > s1 = select(BOOK.ID, BOOK.TITLE).from(BOOK); Select> s2 = selectOne(); @@ -5049,7 +5049,7 @@ s1.union(s4); // OK. The two Record[N] types match]]>

    Note that you can pass any string in the .hint() clause. If you use that clause, the passed string will always be put in between the SELECT [DISTINCT] keywords and the actual projection list. This can be useful in other databases too, such as MySQL, for instance:

    - +
    - +
    Lexical and logical SELECT clause order

    SQL has a lexical and a logical order of SELECT clauses. The lexical order of SELECT clauses is inspired by the English language. As SQL statements are commands for the database, it is natural to express a statement in an imperative tense, such as "SELECT this and that!".

    - +

    Logical SELECT clause order

    The logical order of SELECT clauses, however, does not correspond to the syntax. In fact, the logical order is this:

    - +
    • : First, all data sources are defined and joined
    • : Then, data is filtered as early as possible
    • @@ -5087,11 +5087,11 @@ FROM table1
    • : Then, a paging view is created for the ordered tuples
    • : Finally, pessimistic locking is applied
    - +

    The SQL Server documentation also explains this, with slightly different clauses:

    - +
    • FROM
    • ON
    • @@ -5105,16 +5105,16 @@ FROM table1
    • ORDER BY
    • TOP
    - +

    As can be seen, databases have to logically reorder a SQL statement in order to determine the best execution plan.

    - +

    Alternative syntaxes: LINQ, SLICK

    Some "higher-level" abstractions, such as C#'s LINQ or Scala's SLICK try to inverse the lexical order of SELECT clauses to what appears to be closer to the logical order. The obvious advantage of moving the SELECT clause to the end is the fact that the projection type, which is the record type returned by the SELECT statement can be re-used more easily in the target environment of the internal domain specific language.

    - +

    A LINQ example:

    @@ -5127,11 +5127,11 @@ Where p.UnitsInStock <= p.ReorderLevel AndAlso Not p.Discontinued // SELECT clause Select p]]> - +

    A SLICK example:

    - + INSERT statement is used to insert new records into a database table. The following sections describe the various operation modes of the jOOQ INSERT statement.

    - +
    INSERT .. VALUES - +

    INSERT .. VALUES with a single row

    Records can either be supplied using a VALUES() constructor, or a SELECT statement. jOOQ supports both types of INSERT statements. An example of an INSERT statement using a VALUES() constructor is given here: @@ -5189,7 +5189,7 @@ VALUES (100, 'Hermann', 'Hesse'); create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME); step.values("A", "B", "C"); // ^^^ Doesn't compile, the expected type is Integer]]> - +

    INSERT .. VALUES with multiple rows

    The SQL standard specifies that multiple rows can be supplied to the VALUES() constructor in an INSERT statement. Here's an example of a multi-record INSERT @@ -5227,14 +5227,14 @@ SELECT 101, 'Alfred', 'Döblin' FROM DUAL;

    - +
    INSERT .. DEFAULT VALUES

    A lesser-known syntactic feature of SQL is the INSERT .. DEFAULT VALUES statement, where a single record is inserted, containing only DEFAULT values for every row. It is written as such:

    - + create.insertInto(AUTHOR) .defaultValues() .execute(); - +

    This can make a lot of sense in situations where you want to "reserve" a row in the database for an subsequent within the same transaction. Or if you just want to send an event containing trigger-generated default values, such as IDs or timestamps.

    @@ -5252,18 +5252,18 @@ DEFAULT VALUES;

    -  create.insertInto( AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, ...) .values( - defaultValue(AUTHOR.ID), - defaultValue(AUTHOR.FIRST_NAME), + defaultValue(AUTHOR.ID), + defaultValue(AUTHOR.FIRST_NAME), defaultValue(AUTHOR.LAST_NAME), ...) .execute(); @@ -5272,7 +5272,7 @@ VALUES (

    - +
    INSERT .. SET @@ -5289,13 +5289,13 @@ VALUES ( .set(AUTHOR.FIRST_NAME, "Alfred") .set(AUTHOR.LAST_NAME, "Döblin") .execute(); - +

    As you can see, this syntax is a bit more verbose, but also more readable, as every field can be matched with its value. Internally, the two syntaxes are strictly equivalent. -

    +

    - +
    INSERT .. SELECT @@ -5303,22 +5303,22 @@ VALUES (

    In some occasions, you may prefer the INSERT SELECT syntax, for instance, when you copy records from one table to another:

    - + create.insertInto(AUTHOR_ARCHIVE) .select(selectFrom(AUTHOR).where(AUTHOR.DECEASED.isTrue())) .execute();
    - +
    INSERT .. ON DUPLICATE KEY

    The synthetic ON DUPLICATE KEY UPDATE clause

    - +

    The MySQL database supports a very convenient way to INSERT or UPDATE a record. This is a non-standard extension to the SQL syntax, which is supported by jOOQ and emulated in other RDBMS, where this is possible (i.e. if they support the SQL standard ). Here is an example how to use the ON DUPLICATE KEY UPDATE clause:

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, update the author's name create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -5328,11 +5328,11 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .execute();

    The synthetic ON DUPLICATE KEY IGNORE clause

    - +

    The MySQL database also supports an INSERT IGNORE INTO clause. This is supported by jOOQ using the more convenient SQL syntax variant of ON DUPLICATE KEY IGNORE:

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, ignore the INSERT statement create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -5342,11 +5342,11 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME)

    If the underlying database doesn't have any way to "ignore" failing INSERT statements, (e.g. MySQL via INSERT IGNORE), jOOQ can emulate the statement using a , or using INSERT .. SELECT WHERE NOT EXISTS:

    - +

    Emulating IGNORE with MERGE

    - +

    - The above jOOQ statement can be emulated with the following, equivalent SQL statement: + The above jOOQ statement can be emulated with the following, equivalent SQL statement:

    MERGE INTO AUTHOR @@ -5354,11 +5354,11 @@ USING (SELECT 1 FROM DUAL) ON (AUTHOR.ID = 3) WHEN NOT MATCHED THEN INSERT (ID, LAST_NAME) VALUES (3, 'Koontz') - +

    Emulating IGNORE with INSERT .. SELECT WHERE NOT EXISTS

    - +

    - The above jOOQ statement can be emulated with the following, equivalent SQL statement: + The above jOOQ statement can be emulated with the following, equivalent SQL statement:

    INSERT INTO AUTHOR (ID, LAST_NAME) @@ -5370,11 +5370,11 @@ WHERE NOT EXISTS ( )
    - +
    INSERT .. RETURNING - +

    The Postgres database has native support for an INSERT .. RETURNING clause. This is a very powerful concept that is emulated for all other dialects using JDBC's method. Take this example:

    @@ -5454,7 +5454,7 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    jOOQ supports formal in various contexts, among which the UPDATE statement. Only one row value expression can be updated at a time. Here's an example:

    - + The above row value expressions usages are completely typesafe.

    - +

    UPDATE .. RETURNING

    The Firebird and Postgres databases support a RETURNING clause on their UPDATE statements, similar as the RETURNING clause in . This is useful to fetch trigger-generated values in one go. An example is given here:

    - + The H2 database ships with a somewhat less powerful but a little more intuitive syntax for its own version of the MERGE statement. An example more or less equivalent to the previous one can be seen here:

    - + -- Check if there is already an author called 'Hitchcock' -- If there is, rename him to John. If there isn't add him. @@ -5591,7 +5591,7 @@ VALUES ('John', 'Hitchcock') This syntax can be fully emulated by jOOQ for all other databases that support the SQL standard MERGE statement. For more information about the H2 MERGE syntax, see the documentation here:
    http://www.h2database.com/html/grammar.html#merge

    - +

    Typesafety of VALUES() for degrees up to {max-row-degree}

    Much like the , the MERGE statement's VALUES() clause provides typesafety for degrees up to {max-row-degree}, in both the standard syntax variant as well as the H2 variant. @@ -5697,7 +5697,7 @@ create.alterSequence(S_AUTHOR_ID).restartWith(n).execute();]]>

    - +
    The CREATE statement @@ -5709,7 +5709,7 @@ create.alterSequence(S_AUTHOR_ID).restartWith(n).execute();]]>

    Indexes

    - @@ -5785,7 +5785,7 @@ WHERE 50 < (
    - +
    The DROP statement @@ -5871,7 +5871,7 @@ create.dropViewIfExists(V_AUTHOR).execute();]]>

    Most of the times, when thinking about a you're probably thinking about an actual table in your database schema. If you're using jOOQ's , you will have all tables from your database schema available to you as type safe Java objects. You can then use these tables in SQL , or in other , just like any other table expression. An example is given here:

    - + - +

    The above example shows how AUTHOR and BOOK tables are joined in a . It also shows how you can access by dereferencing the relevant Java attributes of their tables.

    @@ -5924,11 +5924,11 @@ create.select() .and(a.FIRST_NAME.equal("Paulo"))) .orderBy(b.TITLE) .fetch();]]> - +

    As you can see in the above example, calling as() on generated tables returns an object of the same type as the table. This means that the resulting object can be used to dereference fields from the aliased table. This is quite powerful in terms of having your Java compiler check the syntax of your SQL statements. If you remove a column from a table, dereferencing that column from that table alias will cause compilation errors.

    - +

    Dereferencing columns from other table expressions

    Only few table expressions provide the SQL syntax typesafety as shown above, where generated tables are used. Most tables, however, expose their fields through field() methods: @@ -5940,12 +5940,12 @@ Table a = AUTHOR.as("a"); // Get fields from a: Field id = a.field("ID"); Field firstName = a.field("FIRST_NAME");]]> - +

    Derived column lists

    The SQL standard specifies how a table can be renamed / aliased in one go along with its columns. It references the term "derived column list" for the following syntax (as supported by Postgres, for instance):

    - + In jOOQ, you would simply specify a varargs list of column aliases as such:

    - + The that can be used in are the most powerful and best supported means of creating new in SQL. Informally, the following can be said:

    - + A(colA1, ..., colAn) "join" B(colB1, ..., colBm) "produces" C(colA1, ..., colAn, colB1, ..., colBm)

    @@ -6020,7 +6020,7 @@ create.select().from(values(

    jOOQ supports all of these JOIN types (including semi-join and anti-join) directly on any :

    - + table) @@ -6079,7 +6079,7 @@ TableOnStep join(Name)]]>

    Some databases allow for expressing in-memory temporary tables using a VALUES() constructor. This constructor usually works the same way as the VALUES() clause known from the or from the . With jOOQ, you can also use the VALUES() table constructor, to create tables that can be used in a :

    - + Note, that it is usually quite useful to provide column aliases ("derived column lists") along with the table alias for the VALUES() constructor.

    - +

    The above statement is emulated by jOOQ for those databases that do not support the VALUES() constructor, natively (actual emulations may vary):

    - + A can appear almost anywhere a can. Such a "nested SELECT" is often called a "derived table". Apart from many convenience methods accepting objects directly, a SELECT statement can always be transformed into a object using the asTable() method.

    - +

    Example: Scalar subquery

    - + If you are closely coupling your application to an Oracle database, you can take advantage of some Oracle-specific features, such as the PIVOT clause, used for statistical analyses. The formal syntax definition is as follows:

    - + -- SELECT .. FROM table PIVOT (aggregateFunction [, aggregateFunction] FOR column IN (expression [, expression])) -- WHERE .. - +

    The PIVOT clause is available from the type, as pivoting is done directly on a table. Currently, only Oracle's PIVOT clause is supported. Support for SQL Server's slightly different PIVOT clause will be added later. Also, jOOQ may emulate PIVOT for other dialects in the future.

    @@ -6271,7 +6271,7 @@ WHERE NOT EXISTS (

    The SQL standard specifies how SQL databases should implement ARRAY and TABLE types, as well as CURSOR types. Put simply, a CURSOR is a pointer to any materialised . Depending on the cursor's features, this table expression can be scrolled through in both directions, records can be locked, updated, removed, inserted, etc. Often, CURSOR types contain s, whereas ARRAY and TABLE types contain simple scalar values, although that is not a requirement

    - +

    ARRAY types in SQL are similar to Java's array types. They contain a "component type" or "element type" and a "dimension". This sort of ARRAY type is implemented in H2, HSQLDB and Postgres and supported by jOOQ as such. Oracle uses strongly-typed arrays, which means that an ARRAY type (VARRAY or TABLE type) has a name and possibly a maximum capacity associated with it.

    @@ -6294,7 +6294,7 @@ FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(null, null, 'ALLSTATS'));

    - +
    Table-valued functions @@ -6317,11 +6317,11 @@ BEGIN ORDER BY id RETURN END]]> - +

    The jOOQ code generator will now produce a from the above, which can be used as a SQL function:

    - + r1 = create.selectFrom(fBooks(null)).fetch(); @@ -6329,7 +6329,7 @@ Result r1 = create.selectFrom(fBooks(null)).fetch(); create.select(BOOK.ID, F_BOOKS.TITLE) .from(BOOK.crossApply(fBooks(BOOK.ID))) .fetch();]]> - +
    ¨ @@ -6403,12 +6403,12 @@ DSL.using(SQLDialect.SYBASE ).selectOne().getSQL();]]>

    Column expressions can be used in various SQL clauses in order to refer to one or several columns. This chapter explains how to form various types of column expressions with jOOQ. A particular type of column expression is given in the section about , where an expression may have a degree of more than one.

    - +

    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:

    - + field1 = BOOK.TITLE; @@ -6464,7 +6464,7 @@ ORDER BY BOOK.TITLE

    Just like , columns can be renamed using aliases. Here is an example:

    - + SELECT FIRST_NAME || ' ' || LAST_NAME author, COUNT(*) books FROM AUTHOR JOIN BOOK ON AUTHOR.ID = AUTHOR_ID @@ -6473,7 +6473,7 @@ GROUP BY FIRST_NAME, LAST_NAME;

    Here is how it's done with jOOQ:

    - + Record record = create.select( concat(AUTHOR.FIRST_NAME, val(" "), AUTHOR.LAST_NAME).as("author"), count().as("books")) @@ -6481,14 +6481,14 @@ GROUP BY FIRST_NAME, LAST_NAME; .join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID)) .groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .fetchAny(); - +

    When you alias Fields like above, you can access those Fields' values using the alias name:

    - + System.out.println("Author : " + record.getValue("author")); System.out.println("Books : " + record.getValue("books")); - +
    @@ -6501,7 +6501,7 @@ System.out.println("Books : " + record.getValue("books"));

    Sometimes, this automatic mapping might not be what you needed, or jOOQ cannot know the type of a field. In those cases you would write SQL type CAST like this:

    - + -- Let's say, your Postgres column LAST_NAME was VARCHAR(30) -- Then you could do this: SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL @@ -6509,27 +6509,27 @@ SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL

    in jOOQ, you can write something like that:

    - + create.select(TAuthor.LAST_NAME.cast(PostgresDataType.TEXT)).fetch();

    The same thing can be achieved by casting a Field directly to String.class, as TEXT is the default data type in Postgres to map to Java's String

    - + create.select(TAuthor.LAST_NAME.cast(String.class)).fetch(); - +

    The complete CAST API in consists of these three methods:

    - + { // Cast this field to the type of another field Field cast(Field field); - + // Cast this field to a given DataType Field cast(DataType type); - + // Cast this field to the default DataType for a given Class Field cast(Class type); } @@ -6552,14 +6552,14 @@ public class DSL {

    A slightly different use case than are data type coercions, which are not rendered through to generated SQL. Sometimes, you may want to pretend that a numeric value is really treated as a string value, for instance when binding a numeric :

    - + field1 = val(1).coerce(String.class); Field field2 = val("1").coerce(Integer.class);]]>

    In the above example, field1 will be treated by jOOQ as a Field<String>, binding the numeric literal 1 as a VARCHAR value. The same applies to field2, whose string literal "1" will be bound as an INTEGER value.

    - +

    This technique is better than performing unsafe or rawtype casting in Java, if you cannot access the "right" field type from any given expression.

    @@ -6579,15 +6579,15 @@ Field field2 = val("1").coerce(Integer.class);]]>

    In order to express a SQL query like this one:

    - + SELECT ((1 + 2) * (5 - 3) / 2) % 10 FROM DUAL - +

    You can write something like this in jOOQ:

    - + create.select(val(1).add(2).mul(val(5).sub(3)).div(2).mod(10)).fetch(); - +

    Operator precedence

    jOOQ does not know any operator precedence (see also ). All operations are evaluated from left to right, as with any object-oriented API. The two following expressions are the same: @@ -6615,14 +6615,14 @@ Field field2 = val("1").coerce(Integer.class);]]> - +

    String concatenation

    The SQL standard defines the concatenation operator to be an infix operator, similar to the ones we've seen in the chapter about . This operator looks like this: ||. Some other dialects do not support this operator, but expect a concat() function, instead. jOOQ renders the right operator / function, depending on your :

    - + SELECT 'A' || 'B' || 'C' FROM DUAL -- Or in MySQL: @@ -6650,13 +6650,13 @@ create.select(concat("A", "B", "C")).fetch();
  • NVL: Get the first non-null value among two arguments.
  • NVL2: Get the second argument if the first is null, or the third argument, otherwise.
  • - +

    Please refer to the for more details.

    - +
    Numeric functions @@ -6666,7 +6666,7 @@ create.select(concat("A", "B", "C")).fetch();

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ABS: Get the absolute value of a value.
    • ACOS: Get the arc cosine of a value.
    • @@ -6697,7 +6697,7 @@ create.select(concat("A", "B", "C")).fetch();
    • TANH: Get the hyperbolic tangent of a value.
    • TRUNC: Truncate the decimals off a given value.
    - +

    Please refer to the for more details.

    @@ -6722,13 +6722,13 @@ create.select(concat("A", "B", "C")).fetch();
  • SHL: Shift bits to the left
  • SHR: Shift bits to the right
  • - +

    Some background about bitwise operation emulation

    As stated before, not all databases support all of these bitwise operations. jOOQ emulates them wherever this is possible. More details can be seen in this blog post:
    http://blog.jooq.org/2011/10/30/the-comprehensive-sql-bitwise-operations-compatibility-list/

    - +
    @@ -6741,7 +6741,7 @@ create.select(concat("A", "B", "C")).fetch();

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ASCII: Get the ASCII code of a character.
    • BIT_LENGTH: Get the length of a string in bits.
    • @@ -6762,16 +6762,16 @@ create.select(concat("A", "B", "C")).fetch();
    • TRIM: Trim a string on both sides.
    • UPPER: Get a string in upper case letters.
    - +

    Please refer to the for more details.

    - +

    Regular expressions, REGEXP, REGEXP_LIKE, etc.

    Various databases have some means of searching through columns using regular expressions if the does not provide sufficient pattern matching power. While there are many different functions and operators in the various databases, jOOQ settled for the SQL:2008 standard REGEX_LIKE operator. Being an operator (and not a function), you should use the corresponding method on :

    - +

    @@ -6780,7 +6780,7 @@ create.select(concat("A", "B", "C")).fetch(); - +

    Case sensitivity with strings @@ -6793,20 +6793,20 @@ create.select(concat("A", "B", "C")).fetch();

    For these ad-hoc ordering use-cases, most people resort to using LOWER() or UPPER() as follows:

    - + -- Case-insensitive filtering: -SELECT * FROM BOOK +SELECT * FROM BOOK WHERE upper(TITLE) = 'ANIMAL FARM' -- Case-insensitive ordering: -SELECT * +SELECT * FROM AUTHOR ORDER BY upper(FIRST_NAME), upper(LAST_NAME) // Case-insensitive filtering: create.selectFrom(BOOK) .where(upper(BOOK.TITLE).eq("ANIMAL FARM")).fetch(); - + // Case-insensitive ordering: create.selectFrom(AUTHOR) .orderBy(upper(AUTHOR.FIRST_NAME), upper(AUTHOR.LAST_NAME)) @@ -6823,7 +6823,7 @@ create.selectFrom(AUTHOR)

    This is a list of date and time functions supported by jOOQ's :

    - +
    • CURRENT_DATE: Get current date as a DATE object.
    • CURRENT_TIME: Get current time as a TIME object.
    • @@ -6833,7 +6833,7 @@ create.selectFrom(AUTHOR)
    • TIMESTAMP_ADD: Add a number of days or an interval to a timestamp.
    • TIMESTAMP_DIFF: Get the difference as an INTERVAL DAY TO SECOND between two dates.
    - +

    Intervals in jOOQ

    jOOQ fills a gap opened by JDBC, which neglects an important SQL data type as defined by the SQL standards: INTERVAL types. See the manual's section about for more details. @@ -6985,7 +6985,7 @@ GROUP BY AUTHOR_ID WindowOverStep rank(); WindowOverStep denseRank(); WindowOverStep percentRank(); - + // Windowing functions WindowIgnoreNullsStep firstValue(Field field); WindowIgnoreNullsStep lastValue(Field field); @@ -7003,13 +7003,13 @@ GROUP BY AUTHOR_ID // Statistical functions WindowOverStep cumeDist(); WindowOverStep ntile(int number); - + // Inverse distribution functions OrderedAggregateFunction precentileCont(Number number); OrderedAggregateFunction precentileCont(Field number); OrderedAggregateFunction precentileDisc(Number number); OrderedAggregateFunction precentileDisc(Field number);]]> - +

    SQL distinguishes between various window function types (e.g. "ranking functions"). Depending on the function, SQL expects mandatory PARTITION BY or ORDER BY clauses within the OVER() clause. jOOQ does not enforce those rules for two reasons:

    @@ -7024,14 +7024,14 @@ GROUP BY AUTHOR_ID

    Here are some simple examples of window functions with jOOQ:

    - + -- Sample uses of ROW_NUMBER() ROW_NUMBER() OVER() ROW_NUMBER() OVER(PARTITION BY 1) ROW_NUMBER() OVER(ORDER BY BOOK.ID) ROW_NUMBER() OVER(PARTITION BY BOOK.AUTHOR_ID ORDER BY BOOK.ID) - + -- Sample uses of FIRST_VALUE FIRST_VALUE(BOOK.ID) OVER() FIRST_VALUE(BOOK.ID IGNORE NULLS) OVER() @@ -7042,14 +7042,14 @@ rowNumber().over() rowNumber().over().partitionByOne() rowNumber().over().partitionBy(BOOK.AUTHOR_ID) rowNumber().over().partitionBy(BOOK.AUTHOR_ID).orderBy(BOOK.ID) - + // Sample uses of firstValue() firstValue(BOOK.ID).over() firstValue(BOOK.ID).ignoreNulls().over() firstValue(BOOK.ID).respectNulls().over()
    - +

    An advanced window function example

    Window functions can be used for things like calculating a "running total". The following example fetches transactions and the running total for every transaction going back to the beginning of the transaction table (ordered by booked_at). Window functions are accessible from the previously seen type using the over() method: @@ -7077,7 +7077,7 @@ firstValue(BOOK.ID).respectNulls().over()

    In the previous chapter about , we have seen the concept of "ordered-set aggregate functions", such as Oracle's LISTAGG(). These functions have a window function / analytical function variant, as well. For example:

    - + SELECT LISTAGG(TITLE, ', ') WITHIN GROUP (ORDER BY TITLE) @@ -7162,7 +7162,7 @@ ORDER BY 1 NULLS LAST, 2 NULLS LAST

    In English, the ROLLUP() grouping function provides N+1 groupings, when N is the number of arguments to the ROLLUP() function. Each grouping has an additional group field from the ROLLUP() argument field list. The results of the second query might look something like this:

    - + GROUPING SETS() and other grouping functions:
    http://msdn.microsoft.com/en-us/library/bb510427(v=sql.105)

    - +

    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:

    - + ... fields); GroupField cube(Field... fields); @@ -7265,7 +7265,7 @@ Field groupingId(Field...);]]>

    MySQL and CUBRID don't know any grouping functions, but they support a WITH ROLLUP clause, that is equivalent to simple ROLLUP() grouping functions. jOOQ emulates ROLLUP() in MySQL and CUBRID, by rendering this WITH ROLLUP clause. The following two statements mean the same:

    - + Some databases support user-defined functions, which can be embedded in any SQL statement, if you're using jOOQ's . Let's say you have the following simple function in Oracle SQL:

    - + The above function will be made available from a generated class. You can use it like any other :

    - + - +

    Note that user-defined functions returning or data types can also be used wherever can be used, if they are

    @@ -7317,7 +7317,7 @@ END echo;

    Some databases support user-defined aggregate functions, which can then be used along with or as . An example for such a database is Oracle. With Oracle, you can define the following OBJECT type (the example was taken from the Oracle 11g documentation):

    - +

    jOOQ's will detect such aggregate functions and generate them differently from regular . They implement the type, as mentioned in the manual's section about . Here's how you can use the SECOND_MAX() aggregate function with jOOQ:

    - +
    - +
    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:

    - + Row1 row(T1 t1) { ... } public static Row2 row(T1 t1, T2 t2) { ... } @@ -7547,12 +7547,12 @@ public static RowN row(Object... values) { ... }]]>

    See the relevant sections for more details about how to use row value expressions in predicates.

    - +

    Using row value expressions in UPDATE statements

    The also supports a variant where row value expressions are updated, rather than single columns. See the relevant section for more details

    - +

    Higher-degree row value expressions

    jOOQ chose to explicitly support degrees up to {max-row-degree} to match Scala's typesafe tuple, function and product support. Unlike Scala, however, jOOQ also supports higher degrees without the additional typesafety. @@ -7576,7 +7576,7 @@ public static RowN row(Object... values) { ... }]]>

  • The of a
  • The 's ON clause
  • - +

    Boolean types in SQL

    Before SQL:1999, boolean types did not really exist in SQL. They were modelled by 0 and 1 numeric/char values. With SQL:1999, true booleans were introduced and are now supported by most databases. In short, these are possible boolean values: @@ -7672,7 +7672,7 @@ Condition combined2 = combined1.andNot(c); // The left-hand side of the AND NOT

    Here are all boolean operators on the interface:

    - + < to test for being strictly less
  • <= to test for being less or equal
  • - +

    Unfortunately, Java does not support operator overloading, hence these operators are also implemented as methods in jOOQ, like any other SQL syntax elements. The relevant parts of the interface are these:

    - + ); // = (some column expression) eq or equal(Select>); // = (some scalar SELECT statement) @@ -7734,12 +7734,12 @@ ge or greaterOrEqual(Select>); // >= (some scalar SELECT st

    Note that every operator is represented by two methods. A verbose one (such as equal()) and a two-character one (such as eq()). Both methods are the same. You may choose either one, depending on your taste. The manual will always use the more verbose one.

    - +

    jOOQ's convenience methods using comparison operators

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using comparison predicates:

    - +
    - +
    Boolean operator precedence @@ -7766,7 +7766,7 @@ BOOK.TITLE.notEqualIgnoreCase("animal farm")]]>

    In SQL, the two expressions wouldn't be the same, as SQL natively knows operator precedence.

    - + A AND B OR C AND D OR E -- Precedence is applied (((A AND B) OR C) AND D) OR E -- Precedence is overridden @@ -7780,7 +7780,7 @@ BOOK.TITLE.notEqualIgnoreCase("animal farm")]]>

    All variants of the that we've seen in the previous chapter also work for . If your database does not support row value expression comparison predicates, jOOQ emulates them the way they are defined in the SQL standard:

    - + (X, Y))]]>

    jOOQ supports all of the above row value expression comparison predicates, both with and at the right-hand side:

    - +
    - +
    Quantified comparison predicate @@ -7877,7 +7877,7 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    It is interesting to note that the SQL standard defines the in terms of the ANY-quantified predicate. The following two expressions are equivalent:

    - + @@ -7888,14 +7888,14 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    - +
    NULL predicate

    In SQL, you cannot compare NULL with any value using , as the result would yield NULL again, which is neither TRUE nor FALSE (see also the manual's section about ). In order to test a for NULL, use the NULL predicate as such:

    - + @@ -7933,7 +7933,7 @@ NOT((A, B) IS NOT NULL)]]>

    The SQL standard contains a nice truth table for the above rules:

    - + +-----------------------+-----------+---------------+---------------+-------------------+ | Expression | R IS NULL | R IS NOT NULL | NOT R IS NULL | NOT R IS NOT NULL | +-----------------------+-----------+---------------+---------------+-------------------+ @@ -7947,13 +7947,13 @@ NOT((A, B) IS NOT NULL)]]>

    In jOOQ, you would simply use the isNull() and isNotNull() methods on row value expressions. Again, as with the , the row value expression NULL predicate is emulated by jOOQ, if your database does not natively support it:

    - +
    - +
    DISTINCT predicate @@ -7980,7 +7980,7 @@ BOOK.TITLE.isNotDistinctFrom(BOOK.SUB_TITLE)]]>

    If your database does not natively support the DISTINCT predicate, jOOQ emulates it with an equivalent , modelling the above truth table:

    - + ... or better, if the INTERSECT set operation is supported:

    - + - +
    @@ -8021,7 +8021,7 @@ EXISTS(SELECT a INTERSECT SELECT b)

    The BETWEEN predicate can be seen as syntactic sugar for a pair of . According to the SQL standard, the following two predicates are equivalent:

    - + = [B] AND [A] <= [C]]]> @@ -8042,7 +8042,7 @@ BOOK.PUBLISHED_IN.notBetween(1920).and(1940)]]>

    The SQL standard defines the SYMMETRIC keyword to be used along with BETWEEN to indicate that you do not care which bound of the range is larger than the other. A database system should simply swap range bounds, in case the first bound is greater than the second one. jOOQ supports this keyword as well, emulating it if necessary.

    - + @@ -8053,7 +8053,7 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The emulation is done trivially:

    - + @@ -8068,27 +8068,27 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The SQL BETWEEN predicate also works well for . Much like the , it is defined in terms of a pair of regular :

    - + = [B] AND [A] <= [C] ([A] >= [B] AND [A] <= [C]) OR ([A] >= [C] AND [A] <= [B])]]> - +

    The above can be factored out according to the rules listed in the manual's section about .

    - +

    jOOQ supports the BETWEEN [SYMMETRIC] predicate and emulates it in all SQL dialects where necessary. An example is given here:

    - + - + - +
    LIKE predicate @@ -8109,7 +8109,7 @@ TITLE NOT LIKE '%abc%']]> - +

    Escaping operands with the LIKE predicate

    Often, your pattern may contain any of the wildcard characters "_" and "%", in case of which you may want to escape them. jOOQ does not automatically escape patterns in like() and notLike() methods. Instead, you can explicitly define an escape character as such: @@ -8128,12 +8128,12 @@ BOOK.TITLE.notLike("%The !%-Sign Book%", '!')]]>

    Please refer to your database manual for more details about escaping patterns with the LIKE predicate.

    - +

    jOOQ's convenience methods using the LIKE predicate

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using the LIKE predicate. Typical operations are "contains predicates", "starts with predicates", "ends with predicates", etc. Here is the full convenience API wrapping LIKE predicates:

    - + >) // Construct a NOT IN predicate from a subse

    A sample IN predicate might look like this:

    - + @@ -8186,12 +8186,12 @@ TITLE NOT IN ('Animal Farm', '1984')]]>
    BOOK.TITLE.notIn("Animal Farm", "1984")]]>
    - +

    NOT IN and NULL values

    Beware that you should probably not have any NULL values in the right hand side of a NOT IN predicate, as the whole expression would evaluate to NULL, which is rarely desired. This can be shown informally using the following reasoning:

    - + -- The following conditional expressions are formally or informally equivalent A NOT IN (B, C) A != ANY(B, C) @@ -8232,7 +8232,7 @@ NULL -- [ANY] AND NULL yields NULL -- Using a subselect (BOOK.ID, BOOK.TITLE) IN ( SELECT T.ID, T.TITLE - FROM T + FROM T )]]> - +

    In both cases, i.e. when using an IN list or when using a subselect, the type of the predicate is checked. Both sides of the predicate must be of equal degree and row type.

    - +

    - Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value. + Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value.

    - +
    EXISTS predicate @@ -8266,7 +8266,7 @@ row(BOOK.ID, BOOK.TITLE).in(
  • From a using
  • From a using , and from other clauses
  • - +

    An example of an EXISTS predicate can be seen here:

    @@ -8285,7 +8285,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

    - +

    Performance of IN vs. EXISTS

    In theory, the two types of predicates can perform equally well. If your database system ships with a sophisticated cost-based optimiser, it will be able to transform one predicate into the other, if you have all necessary constraints set (e.g. referential constraints, not null constraints). However, in reality, performance between the two might differ substantially. An interesting blog post investigating this topic on the MySQL database can be seen here:
    @@ -8293,7 +8293,7 @@ notExists(create.selectOne().from(BOOK)

    - +
    OVERLAPS predicate @@ -8331,7 +8331,7 @@ row(Date.valueOf('2010-01-01'), new DayToSecond(2)).overlaps(Date.valueOf('2010-

    Unlike the standard (or any database implementing the standard), jOOQ also supports the OVERLAPS predicate for comparing arbitrary . For instance, (1, 3) OVERLAPS (2, 4) will yield true in jOOQ. This is emulated as such

    - +
    - +
    Dynamic SQL

    In most cases, , , and as introduced in the previous chapters will be embedded into different SQL statement clauses as if the statement were a static SQL statement (e.g. in a view or stored procedure):

    - + - +

    It is, however, interesting to think of all of the above expressions as what they are: expressions. And as such, nothing keeps users from extracting expressions and referencing them from outside the statement. The following statement is exactly equivalent:

    @@ -8375,26 +8375,26 @@ create.select(select) .groupBy(groupBy) .orderBy() .fetch();]]> - +

    Each individual expression, and collection of expressions can be seen as an independent entity that can be

    - +
    1. Constructed dynamically
    2. Reused across queries
    - +

    Dynamic construction is particularly useful in the case of the , for dynamic predicate building. For instance:

    - +

    The dynamic SQL building power may be one of the biggest advantages of using a runtime query model like the one offered by jOOQ. Queries can be created dynamically, of arbitrary complexity. In the above example, we've just constructed a dynamic . The same can be done for any other clauses, including dynamic , or adding additional as needed.

    @@ -8430,7 +8430,7 @@ create.select()
  • - +

    You'll probably find other examples. If verbosity scares you off, don't worry. The verbose use-cases for jOOQ are rather rare, and when they come up, you do have an option. Just write SQL the way you're used to!

    @@ -8460,7 +8460,7 @@ Condition condition(String sql, Object... bindings); // Construct a condition taking other jOOQ object arguments // Example: condition("a = {0}", val(1)); 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 DSL:

    @@ -8518,7 +8518,7 @@ Result fetch(String sql, QueryPart... parts);]]>

    Apart from the general factory methods, plain SQL is also available in various other contexts. For instance, when adding a .where("a = b") clause to a query. Hence, there exist several convenience methods where plain SQL can be inserted usefully. This is an example displaying all various use-cases in one single query:

    - + LAST_NAME = create.field("a.LAST_NAME"); @@ -8639,7 +8639,7 @@ Name name = name("AUTHOR", "TITLE");]]> On a JDBC level, you can also reuse the SQL string and prepared statement object instead of constructing it again, as you can bind new values to the prepared statement. jOOQ currently does not cache prepared statements, internally. - +

    The following sections explain how you can introduce bind values in jOOQ, and how you can control the way they are rendered and bound to SQL.

    @@ -8652,7 +8652,7 @@ Name name = name("AUTHOR", "TITLE");]]>

    JDBC only knows indexed bind values. A typical example for using bind values with JDBC is this:

    - + With dynamic SQL, keeping track of the number of question marks and their corresponding index may turn out to be hard. jOOQ abstracts this and lets you provide the bind value right where it is needed. A trivial example is this:

    - + 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

    Should you decide to run the above query outside of jOOQ, using your own , you can do so as follows:

    - + select = create.select().from(BOOK).where(BOOK.ID.equal(5)).and(BOOK.TITLE.equal("Animal Farm")); // Render the SQL statement: @@ -8805,25 +8805,25 @@ create.select()
    SQL injection - +

    SQL injection is serious

    SQL injection is a serious problem that needs to be taken care of thoroughly. A single vulnerability can be enough for an attacker to dump your whole database, and potentially seize your database server. We've blogged about the severity of this threat on the jOOQ blog.

    - +

    SQL injection happens because a programming language (SQL) is used to dynamically create arbitrary server-side statements based on user input. Programmers must take lots of care not to mix the language parts (SQL) with the user input ()

    - +

    SQL injection in jOOQ

    With jOOQ, SQL is usually created via a type safe, non-dynamic Java abstract syntax tree, where bind variables are a part of that abstract syntax tree. It is not possible to expose SQL injection vulnerabilities this way.

    - +

    However, jOOQ offers convenient ways of introducing in various places of the jOOQ API (which are annotated using since jOOQ 3.6). While jOOQ's API allows you to specify bind values for use with plain SQL, you're not forced to do that. For instance, both of the following queries will lead to the same, valid result:

    - +

    A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] FROM AUTHOR JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID @@ -8966,15 +8966,15 @@ public final void accept(Context context) {

    As mentioned in the previous chapter about , there are some elements in the that are used for formatting / pretty-printing rendered SQL. In order to obtain pretty-printed SQL, just use the following :

    - - + +

    And then, use the above DSLContext to render pretty-printed SQL:

    - + A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] WHERE AUTHOR.ID = ? -- [...] @@ -9067,11 +9067,11 @@ public final void bind(BindContext context) throws DataAccessException {

    Converters

    - +

    The simplest use-case of injecting custom data types is by using . A Converter can convert from a database type <T> to a user-defined type <U> and vice versa. You'll be implementing this SPI:

    - + { // Your conversion logic goes into these two methods, that can convert @@ -9082,8 +9082,8 @@ public final void bind(BindContext context) throws DataAccessException { // You need to provide Class instances for each type, too: Class fromType(); Class toType(); -}]]> - +}]]> +

    If, for instance, you want to use Java 8's for SQL DATE and for SQL TIMESTAMP, you write a converter like this:

    @@ -9114,14 +9114,14 @@ public class LocalDateConverter implements Converter { public Class toType() { return LocalDate.class; } -}]]> +}]]>

    This converter can now be used in a variety of jOOQ API, most importanly to create a new data type:

    - + type = SQLDataType.DATE.asConvertedDataType(new LocalDateConverter());]]> - +

    And data types, in turn, can be used with any , i.e. with any , including or based ones:

    @@ -9134,15 +9134,15 @@ Field date1 = DSL.field("my_table.my_column", type); // Name based Field date2 = DSL.field(name("my_table", "my_column"), type);]]> - +

    Bindings

    - +

    While converters are very useful for simple use-cases, is useful when you need to customise data type interactions at a JDBC level, e.g. when you want to bind a PostgreSQL JSON data type. Custom bindings implement the following SPI:

    - + extends Serializable { // A converter that does the conversion between the database type T @@ -9162,11 +9162,11 @@ Field date2 = DSL.field(name("my_table", "my_column"), type);]]> ctx) throws SQLException; void get(BindingGetSQLInputContext ctx) throws SQLException; }]]> - +

    Below is full fledged example implementation that uses Google Gson to model JSON documents in Java

    - + { public void get(BindingGetSQLInputContext ctx) throws SQLException { throw new SQLFeatureNotSupportedException(); } -}]]> - +}]]> +

    Code generation

    There is a special section in the manual explaining how to automatically tie your Converters and Bindings to your generated code. The relevant sections are:

    - +
    - +
    Custom syntax elements

    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:

    - + extends AbstractField {} public abstract class CustomCondition extends AbstractCondition {} public abstract class CustomTable> extends TableImpl {} @@ -9277,7 +9277,7 @@ public abstract class CustomRecord> extends TableRecord

    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 method, as discussed before:

    - + 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 showing how to create a field multiplying another field by 2

    - + IDx2 = new CustomField(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(" * ?"); @@ -9317,10 +9317,10 @@ final Field IDx2 = new CustomField(BOOK.ID.getName(), BOOK.ID. @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(DSL.val(2)); } @@ -9339,7 +9339,7 @@ create.select(IDx2).from(BOOK);]]>

    Many vendor-specific functions are not officially supported by jOOQ, but you can implement such support yourself using CustomField, for instance. Here's an example showing how to implement Oracle's TO_CHAR() function, emulating it in SQL Server using CONVERT():

    - + { @@ -9376,7 +9376,7 @@ class ToChar extends CustomField {

    The above CustomField implementation can be exposed from your own custom DSL class:

    - + toChar(Field field, String format) { return new ToChar(field, DSL.inline(format)); @@ -9384,7 +9384,7 @@ class ToChar extends CustomField { }]]>
    - +
    Plain SQL QueryParts @@ -9398,10 +9398,10 @@ class ToChar extends CustomField {

    The above distinction is best explained using an example:

    - + Note that for historic reasons the two API usages can also be mixed, although this is not recommended and the exact behaviour is unspecified.

    - +

    Plain SQL templating specification

    - +

    Templating with QueryPart placeholders (or bind value placeholders) requires a simple parsing logic to be applied to SQL strings. The jOOQ template parser behaves according to the following rules:

    @@ -9436,13 +9436,13 @@ create.selectFrom(BOOK).where(
  • QueryPart placeholders ({number}) are replaced by the matching QueryPart.
  • Keywords ({identifier}) are treated like keywords and rendered in the correct case according to .
  • - +

    Tools for templating

    - +

    A variety of API is provided to create template elements that are intended for use with the above templating mechanism. These tools can be found in

    - +

    - +
    Custom SQL transformation @@ -9488,7 +9488,7 @@ create.attach(select);]]> With jOOQ 3.2's SPI, it is possible to perform custom SQL transformation to implement things like shared-schema multi-tenancy, or a security layer centrally preventing access to certain data. This SPI is extremely powerful, as you can make ad-hoc decisions at runtime regarding local or global transformation of your SQL statement. The following sections show a couple of simple, yet real-world use-cases.

    - +
    Logging abbreviated bind values @@ -9496,7 +9496,7 @@ create.attach(select);]]>

    When implementing a logger, one needs to carefully assess how much information should really be disclosed on what logger level. In log4j and similar frameworks, we distinguish between FATAL, ERROR, WARN, INFO, DEBUG, and TRACE. In DEBUG level, jOOQ's logs all executed statements including inlined bind values as such:

    - + with bind values : select * from "BOOK" where "BOOK"."TITLE" like 'How I stopped worrying%']]> @@ -9512,7 +9512,7 @@ public class BindValueAbbreviator extends DefaultVisitListener { @Override public void visitStart(VisitContext context) { - + // Transform only when rendering values if (context.renderContext() != null) { QueryPart part = context.queryPart(); @@ -9526,16 +9526,16 @@ public class BindValueAbbreviator extends DefaultVisitListener { // e.g. using commons-lang's StringUtils.abbreviate() if (value instanceof String && ((String) value).length() > maxLength) { anyAbbreviations = true; - + // ... and replace it in the current rendering context (not in the Query) context.queryPart(val(abbreviate((String) value, maxLength))); } - + // If the bind value is a byte[] (or Blob) of a given length, abbreviate it // e.g. by removing bytes from the array else if (value instanceof byte[] && ((byte[]) value).length > maxLength) { anyAbbreviations = true; - + // ... and replace it in the current rendering context (not in the Query) context.queryPart(val(Arrays.copyOf((byte[]) value, maxLength))); } @@ -9545,10 +9545,10 @@ public class BindValueAbbreviator extends DefaultVisitListener { @Override public void visitEnd(VisitContext context) { - + // If any abbreviations were performed before... if (anyAbbreviations) { - + // ... and if this is the top-level QueryPart, then append a SQL comment to indicate the abbreviation if (context.queryPartsLength() == 1) { context.renderContext().sql(" -- Bind values may have been abbreviated"); @@ -9573,14 +9573,14 @@ public class BindValueAbbreviator extends DefaultVisitListener {
    - +
    SQL building in Scala

    jOOQ-Scala is a maven module used for leveraging some advanced Scala features for those users that wish to use jOOQ with Scala.

    - +

    Using Scala's implicit defs to allow for operator overloading

    The most obvious Scala feature to use in jOOQ are implicit defs for implicit conversions in order to enhance the type with SQL-esque operators. @@ -9588,7 +9588,7 @@ public class BindValueAbbreviator extends DefaultVisitListener {

    The following depicts a trait which wraps all fields:

    - + The following depicts a trait which wraps numeric fields:

    - + An example query using such overloaded operators would then look like this:

    - +

    In a previous section of the manual, we've seen how jOOQ can be used to that can be executed with any API including JDBC or ... jOOQ. This section of the manual deals with various means of actually executing SQL with jOOQ.

    - +

    SQL execution with JDBC

    JDBC calls executable objects "". It distinguishes between three types of statements: @@ -9728,7 +9728,7 @@ fetch]]>

    Today, the JDBC API may look weird to users being used to object-oriented design. While statements hide a lot of SQL dialect-specific implementation details quite well, they assume a lot of knowledge about the internal state of a statement. For instance, you can use the method, to add a the prepared statement being created to an "internal list" of batch statements. Instead of returning a new type, this method forces user to reflect on the prepared statement's internal state or "mode".

    - +

    jOOQ is wrapping JDBC

    These things are abstracted away by jOOQ, which exposes such concepts in a more object-oriented way. For more details about jOOQ's batch query execution, see the manual's section about . @@ -9736,7 +9736,7 @@ fetch]]>

    The following sections of this manual will show how jOOQ is wrapping JDBC for SQL execution

    - +

    Alternative execution modes

    Just because you can, doesn't mean you must. At the end of this chapter, we'll show how you can use jOOQ to generate SQL statements that are then executed with other APIs, such as Spring's JdbcTemplate, or Hibernate. For more information see the . @@ -9755,7 +9755,7 @@ fetch]]>

  • Both APIs return the number of affected records in non-result queries. JDBC: , jOOQ:
  • Both APIs return a scrollable result set type from result queries. JDBC: , jOOQ:
  • - +

    Differences to JDBC

    Some of the most important differences between JDBC and jOOQ are listed here: @@ -9771,14 +9771,14 @@ fetch]]>

    - +
    Query vs. ResultQuery

    Unlike JDBC, jOOQ has a lot of knowledge about a SQL query's structure and internals (see the manual's section about ). Hence, jOOQ distinguishes between these two fundamental types of queries. While every can be executed, only can return results (see the manual's section about to learn more about fetching results). With plain SQL, the distinction can be made clear most easily:

    - + result = resultQuery.fetch();]]>
  • : Some databases allow for returning many result sets from a single query. JDBC can handle this but it's very verbose. A list of results should be returned instead.
  • : Some queries take too long to execute to wait for their results. You should be able to spawn query execution in a separate process.
  • - +

    Convenience and how ResultQuery, Result, and Record share API

    The term "fetch" is always reused in jOOQ when you can fetch data from the database. An provides many overloaded means of fetching data:

    - +

    Various modes of fetching

    These modes of fetching are also documented in subsequent sections of the manual

    - + fetch(); @@ -9844,7 +9844,7 @@ List> fetchMany(); // Execute a ResultQuery with jOOQ, but return a JDBC ResultSet, not a jOOQ object ResultSet fetchResultSet();]]> - +

    Fetch convenience

    These means of fetching are also available from and APIs @@ -9890,11 +9890,11 @@ ResultSet fetchResultSet();]]>

    These means of fetching are also available from and APIs

    - + Map fetchMap(Field key); Map fetchMap(Field key, Field value); @@ -9934,7 +9934,7 @@ ResultSet fetchResultSet();]]>

    Yet, still, sometimes you wish to use strongly typed records, when you know that you're selecting only from a single table:

    - +

    Fetching strongly or weakly typed records

    When fetching data only from a single table, the type is known to jOOQ if you use jOOQ's to generate for your database tables. In order to fetch such strongly typed records, you will have to use the : @@ -9946,7 +9946,7 @@ BookRecord book = create.selectFrom(BOOK).where(BOOK.ID.equal(1)).fetchOne(); // Typesafe field access is now possible: 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:

    @@ -9954,11 +9954,11 @@ System.out.println("Published in: " + book.getPublishedIn());]]>
  • - +

    Mapping custom row types to strongly typed records

    - +

    Sometimes, you may want to explicitly select only a subset of your columns, but still use strongly typed records. Alternatively, you may want to join a one-to-one relationship and receive the two individual strongly typed records after the join.

    @@ -10019,7 +10019,7 @@ System.out.println("Author : " + author.getFirstName() + " " + author.getLa

    By default, jOOQ returns an object, which is essentially a of . Often, you will find yourself wanting to transform this result object into a type that corresponds more to your specific needs. Or you just want to list all values of one specific column. Here are some examples to illustrate those use cases:

    - + titles1 = create.select().from(BOOK).fetch().getValues(BOOK.TITLE); List titles2 = create.select().from(BOOK).fetch(BOOK.TITLE); @@ -10054,7 +10054,7 @@ Map> group4 = create.selectFrom(BOOK).fetchGroups(BO

    In a more functional operating mode, you might want to write callbacks that receive records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + () {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -10089,7 +10089,7 @@ create.selectFrom(BOOK)

    In a more functional operating mode, you might want to write callbacks that map records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + ids = create.selectFrom(BOOK) @@ -10101,12 +10101,12 @@ create.selectFrom(BOOK) return book.getId(); } }); - + // Or more concisely create.selectFrom(BOOK) .orderBy(BOOK.ID) .fetch(new RecordMapper() {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -10132,7 +10132,7 @@ create.selectFrom(BOOK)

    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. See the manual's section about to see how to modify jOOQ's standard POJO mapping behaviour.

    - +

    Using JPA-annotated POJOs

    jOOQ tries to find JPA annotations on your POJO types. If it finds any, they are used as the primary source for mapping meta-information. Only the annotation is used and understood by jOOQ. An example: @@ -10142,7 +10142,7 @@ create.selectFrom(BOOK) public class MyBook { @Column(name = "ID") public int myId; - + @Column(name = "TITLE") public String myTitle; } @@ -10151,16 +10151,16 @@ public class MyBook { MyBook myBook = create.select().from(BOOK).fetchAny().into(MyBook.class); List myBooks = create.select().from(BOOK).fetch().into(MyBook.class); List myBooks = create.select().from(BOOK).fetchInto(MyBook.class);]]> - +

    Just as with any other JPA implementation, you can put the annotation on any class member, including attributes, setters and getters. Please refer to the Javadoc for more details.

    - +

    Using simple POJOs

    If jOOQ does not find any JPA-annotations, columns are mapped to the "best-matching" constructor, attribute or setter. An example illustrates this:

    - + myBooks = create.select().from(BOOK).fetchInto(MyBook1.class);]]><

    Please refer to the Javadoc for more details.

    - +

    Using "immutable" POJOs

    If jOOQ does not find any default constructor, columns are mapped to the "best-matching" constructor. This allows for using "immutable" POJOs with jOOQ. An example illustrates this:

    - + myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchInto( public class MyBook3 { public final String title; public final int id; - + @ConstructorProperties({ "title", "id"}) public MyBook2(String title, int id) { this.title = title; @@ -10215,7 +10215,7 @@ MyBook3 myBook = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchA List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetch().into(MyBook3.class); List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchInto(MyBook3.class); ]]> - +

    Please refer to the Javadoc for more details.

    @@ -10224,12 +10224,12 @@ List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchI

    jOOQ also allows for fetching data into abstract classes or interfaces, or in other words, "proxyable" types. This means that jOOQ will return a wrapped in a implementing your custom type. An example of this is given here:

    - + - +

    Note: Because of your manual setting of ID = 10, jOOQ's store() method will asume that you want to insert a new record. See the manual's section about for more details on this.

    - +

    Interaction with DAOs

    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: @@ -10296,21 +10296,21 @@ bookDao.update(book); // Delete it again bookDao.delete(book);]]> - +

    More complex data structures

    jOOQ currently doesn't support more complex data structures, the way Hibernate/JPA attempt to map relational data onto POJOs. While future developments in this direction are not excluded, jOOQ claims that generic mapping strategies lead to an enormous additional complexity that only serves very few use cases. You are likely to find a solution using any of jOOQ's various , with only little boiler-plate code on the client side.

    - +
    POJOs with RecordMappers

    In the previous sections we have seen how to create types to map jOOQ records onto arbitrary objects. We have also seen how jOOQ provides default algorithms to map jOOQ records onto . Your own custom domain model might be much more complex, but you want to avoid looking up the most appropriate RecordMapper every time you need one. For this, you can provide jOOQ's with your own implementation of the interface. An example is given here:

    - + } } } - + // Books might be joined with their authors, create a 1:1 mapping if (type == Book.class) { return new BookMapper(); @@ -10347,12 +10347,12 @@ bookDao.delete(book);]]>

    The above is a very simple example showing that you will have complete flexibility in how to override jOOQ's record to POJO mapping mechanisms.

    - +

    Using third party libraries

    A couple of useful libraries exist out there, which implement custom, more generic mapping algorithms. Some of them have been specifically made to work with jOOQ. Among them are:

    - +
    • ModelMapper (with an explicit jOOQ integration)
    • SimpleFlatMapper (with an explicit jOOQ integration)
    • @@ -10367,14 +10367,14 @@ bookDao.delete(book);]]>

      Unlike JDBC's , jOOQ's does not represent an open database cursor with various fetch modes and scroll modes, that needs to be closed after usage. jOOQ's results are simple in-memory Java objects, containing all of the result values. If your result sets are large, or if you have a lot of network latency, you may wish to fetch records one-by-one, or in small chunks. jOOQ supports a type for that purpose. In order to obtain such a reference, use the method. An example is given here:

      - + cursor = create.selectFrom(BOOK).fetchLazy()) { // Cursor has similar methods as Iterator while (cursor.hasNext()) { BookRecord book = cursor.fetchOne(); - + Util.doThingsWithBook(book); } }]]> @@ -10382,7 +10382,7 @@ try (Cursor cursor = create.selectFrom(BOOK).fetchLazy()) {

      As a holds an internal reference to an open , it may need to be closed at the end of iteration. If a cursor is completely scrolled through, it will conveniently close the underlying ResultSet. However, you should not rely on that.

      - +

      Cursors ship with all the other fetch features

      Like or , gives access to all of the other fetch features that we've seen so far, i.e. @@ -10402,7 +10402,7 @@ try (Cursor cursor = create.selectFrom(BOOK).fetchLazy()) {

      jOOQ 3.7+ supports Java 8, and with Java 8, it supports . This opens up a range of possibilities of combining the declarative aspects of SQL with the functional aspects of the new Stream API. Much like , such a Stream keeps an internal reference to a JDBC , which means that the Stream has to be treated like a resource. Here's an example of using such a stream:

      - + stream = create.selectFrom(BOOK).stream()) { stream.forEach(Util::doThingsWithBook); @@ -10447,7 +10447,7 @@ try (Stream stream = create.selectFrom(BOOK).stream()) { " " + col.getValue()) .collect(Collectors.joining(",\n")) ); - + System.out.println(");"); });]]> @@ -10488,7 +10488,7 @@ CREATE TABLE COLUMNS( REMARKS VARCHAR, SOURCE_DATA_TYPE SMALLINT );]]> - +
    @@ -10520,7 +10520,7 @@ CREATE TABLE COLUMNS(

    The correct (and verbose) way to do this with JDBC is as follows:

    - +

    As previously discussed in the chapter about , jOOQ does not rely on an internal state of any JDBC object, which is "externalised" by Javadoc. Instead, it has a straight-forward API allowing you to do the above in a one-liner:

    - + @@ -10561,22 +10561,22 @@ Results results = create.fetchMany("sp_help 'author'");]]>
    Later fetching

    Using Java 8 CompletableFutures

    - +

    Java 8 has introduced the new type, which allows for functional composition of asynchronous execution units. When applying this to SQL and jOOQ, you might be writing code as follows:

    - + + .supplyAsync(() -> DSL.using(configuration) .insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .values(3, "Hitchcock") .execute() ) - + // This will supply an AuthorRecord value for the newly inserted author .handleAsync((rows, throwable) -> DSL.using(configuration) @@ -10589,30 +10589,30 @@ CompletableFuture record.changed(true); return record.insert(); }) - + // This will supply an int value indicating the number of deleted rows - .handleAsync((rows, throwable) -> + .handleAsync((rows, throwable) -> DSL.using(configuration) .delete(AUTHOR) .where(AUTHOR.ID.eq(3)) .execute() ) .join();]]> - +

    The above example will execute four actions one after the other, but asynchronously in the JDK's default or common . -

    - +

    +

    For more information, please refer to the Javadoc and official documentation. -

    - +

    +

    Using deprecated API

    - +

    Some queries take very long to execute, yet they are not crucial for the continuation of the main program. For instance, you could be generating a complicated report in a Swing application, and while this report is being calculated in your database, you want to display a background progress bar, allowing the user to pursue some other work. This can be achived simply with jOOQ, by creating a , a type that extends . An example is given here:

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(); @@ -10628,7 +10628,7 @@ Result result = future.get();]]>

    Note, that instead of letting jOOQ spawn a new thread, you can also provide jOOQ with your own :

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(service);]]> @@ -10642,7 +10642,7 @@ FutureResult future = create.selectFrom(BOOK).where(... complex pred

    When interacting with legacy applications, you may prefer to have jOOQ return a , rather than jOOQ's own types. This can be done simply, in two ways:

    - + cursor = create.fetchLazy(rs);]]>

    You can also tighten the interaction with jOOQ's data type system and features, by passing the record type to the above fetch methods:

    - + result = create.fetch (rs, Integer.class, String.class); Cursor result = create.fetchLazy(rs, Integer.class, String.class); @@ -10706,7 +10706,7 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Apart from a few extra features (), jOOQ only supports basic types as supported by the JDBC API. In your application, you may choose to transform these data types into your own ones, without writing too much boiler-plate code. This can be done using jOOQ's types. A converter essentially allows for two-way conversion between two Java data types <T> and <U>. By convention, the <T> type corresponds to the type in your database whereas the <U> type corresponds to your own user type. The Converter API is given here:

    - + extends Serializable { /** @@ -10733,12 +10733,12 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Such a converter can be used in many parts of the jOOQ API. Some examples have been illustrated in the manual's section about .

    - +

    A Converter for GregorianCalendar

    Here is a some more elaborate example involving a Converter for :

    - + { @@ -10769,12 +10769,12 @@ public class CalendarConverter implements Converter dates1 = create.selectFrom(BOOK).fetch().getValues(BOOK.PUBLISHING_DATE, new CalendarConverter()); List dates2 = create.selectFrom(BOOK).fetch(BOOK.PUBLISHING_DATE, new CalendarConverter()); ]]> - +

    Enum Converters

    jOOQ ships with a built-in default , that you can use to map VARCHAR values to enum literals or NUMBER values to enum ordinals (both modes are supported). Let's say, you want to map a YES / NO / MAYBE column to a custom Enum:

    - + - +

    Using Converters in generated source code

    jOOQ also allows for generated source code to reference your own custom converters, in order to permanently replace a <T> type by your own, custom <U> type. See the manual's section about for details. @@ -10836,20 +10836,20 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE) .join(AUTHOR).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) .intern(BOOK.AUTHOR_ID) .fetch();]]> - +

    You can specify as many fields as you want for interning. The above has the following effect:

    - +
    • If the interned Field is of type , then is called upon each string
    • If the interned Field is of any other type, then the call is ignored
    - +

    Future versions of jOOQ will implement interning of data for non-String data types by collecting values in , removing duplicate instances.

    - +

    Note, that jOOQ will not use interned data for identity comparisons: string1 == string2. Interning is used only to reduce the memory footprint of objects.

    @@ -10857,7 +10857,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)
    - +
    Static statements vs. Prepared Statements @@ -10867,7 +10867,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)

    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:

    - + @@ -10897,7 +10897,7 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    Whichever aproach is more optimal for you cannot be decided by jOOQ. In most cases, prepared statements are probably better. But you always have the option of forcing jOOQ to render inlined bind values.

    - +

    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 @@ -10911,15 +10911,15 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    As previously discussed in the chapter about , reusing PreparedStatements is handled a bit differently in jOOQ from how it is handled in JDBC

    - +

    Keeping open PreparedStatements with JDBC

    With JDBC, you can easily reuse a by not closing it between subsequent executions. An example is given here:

    - + The above technique can be quite useful when you want to reuse expensive database resources. This can be the case when your statement is executed very frequently and your database would take non-negligible time to soft-parse the prepared statement and generate a new statement / cursor resource.

    - +

    Keeping open PreparedStatements with jOOQ

    This is also modeled in jOOQ. However, the difference to JDBC is that closing a statement is the default action, whereas keeping it open has to be configured explicitly. This is better than JDBC, because the default action should be the one that is used most often. Keeping open statements is rarely done in average applications. Here's an example of how to keep open PreparedStatements with jOOQ:

    - + query = create.selectOne().keepStatement(true)) { Result result1 = query.fetch(); // This will lazily create a new PreparedStatement @@ -10954,7 +10954,7 @@ try (ResultQuery query = create.selectOne().keepStatement(true)) {

    JDBC knows a couple of execution flags and modes, which can be set through the jOOQ API as well. jOOQ essentially supports these flags and execution modes:

    - + query = create.selectOne().keepStatement(true)) { // The query execution timeout. // ----------------------------------------------------------- Query queryTimeout(int timeout); - + }]]> - + extends Query { // [...] @@ -10987,25 +10987,25 @@ try (ResultQuery query = create.selectOne().keepStatement(true)) { // The maximum number of rows to be fetched by JDBC // ----------------------------------------------------------- ResultQuery maxRows(int rows); - + }]]>

    Using ResultSet concurrency with ExecuteListeners

    An example of why you might want to manually set a ResultSet's concurrency flag to something non-default is given here:

    - + - +

    In the above example, your custom is triggered before jOOQ loads a new Record from the JDBC ResultSet. With the concurrency being set to ResultSet.CONCUR_UPDATABLE, you can now modify the database cursor through the standard JDBC ResultSet API.

    @@ -11063,22 +11063,22 @@ try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO author(id stmt.setString(2, "Erich"); stmt.setString(3, "Gamma"); stmt.addBatch(); - + stmt.setInt(1, 2); stmt.setString(2, "Richard"); stmt.setString(3, "Helm"); stmt.addBatch(); - + stmt.setInt(1, 3); stmt.setString(2, "Ralph"); stmt.setString(3, "Johnson"); stmt.addBatch(); - + stmt.setInt(1, 4); stmt.setString(2, "John"); stmt.setString(3, "Vlissides"); stmt.addBatch(); - + int[] result = stmt.executeBatch(); }]]>
    @@ -11087,7 +11087,7 @@ try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO author(id

    jOOQ supports executing queries in batch mode as follows:

    - + - +

    When creating a batch execution with a single query and multiple bind values, you will still have to provide jOOQ with dummy bind values for the original query. In the above example, these are set to null. For subsequent calls to bind(), there will be no type safety provided by jOOQ.

    @@ -11123,18 +11123,18 @@ create.batch(create.insertInto(AUTHOR, ID, FIRST_NAME, LAST_NAME ).values((Inte

    Instead of actually phrasing a select statement, you can also use the convenience methods:

    - + - +

    Inlining sequence references in SQL

    You can inline sequence references in jOOQ SQL statements. The following are examples of how to do that:

    - + The general distinction between (stored) procedures and (stored) functions can be summarised like this:

    - +

    Procedures

    • Are called using JDBC CallableStatement
    • Have no return value
    • Usually support OUT parameters
    - +

    Functions

    • Can be used in SQL statements
    • Have a return value
    • Usually don't support OUT parameters
    - +

    Exceptions to these rules

    • DB2, H2, and HSQLDB don't allow for JDBC escape syntax when calling functions. Functions must be used in a SELECT statement
    • @@ -11195,19 +11195,19 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

      To simplify things a little bit, jOOQ handles both procedures and functions the same way, using a more general type.

      - +

      Using jOOQ for standalone calls to stored procedures and functions

      If you're using jOOQ's , it will generate objects for you. Let's consider the following example:

      - +

      The generated artefacts can then be used as follows:

      - + - +

      But you can also call the procedure using a generated convenience method in a global Routines class:

      @@ -11234,7 +11234,7 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]>

      For more details about for procedures, see the manual's section about .

      - +

      Inlining stored function references in SQL

      Unlike procedures, functions can be inlined in SQL statements to generate or , if you're using . Assume you have a function like this: @@ -11242,11 +11242,11 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]> - +

      The generated artefacts can then be used as follows:

      - + boolean exists = create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]> - +

      For more info about inlining stored function references in SQL statements, please refer to the manual's section about .

      @@ -11287,7 +11287,7 @@ create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]>

      Oracle UDTs can have object-oriented structures including member functions and procedures. With Oracle, you can do things like this:

      - + {"schema":"schema-n","table":"table-n","name":"field-n","type":"type-n"}], "records":[[value-1-1,value-1-2,...,value-1-n], [value-2-1,value-2-2,...,value-2-n]]} - +

      Note: This format has been modified in jOOQ 2.6.0 and 3.7.0

      @@ -11602,7 +11602,7 @@ Query query = error.query();]]>
    - +
    Importing JSON @@ -11636,7 +11636,7 @@ create.loadInto(BOOK)

    - +
    Importing Records @@ -11666,7 +11666,7 @@ DSL.using(configuration1)

    - +
    Importing Arrays @@ -11712,12 +11712,12 @@ DSL.using(configuration1)

    CRUD always uses the same patterns, regardless of the nature of underlying tables. This again, leads to a lot of boilerplate code, if you have to issue your statements yourself. Like Hibernate / JPA and other ORMs, jOOQ facilitates CRUD using a specific API involving types.

    - +

    Primary keys and updatability

    In normalised databases, every table has a primary key by which a tuple/record within that table can be uniquely identified. In simple cases, this is a (possibly auto-generated) number called ID. But in many cases, primary keys include several non-numeric columns. An important feature of such keys is the fact that in most databases, they are enforced using an index that allows for very fast random access to the table. A typical way to access / modify / delete a book is this:

    - + - +

    Normalised databases assume that a primary key is unique "forever", i.e. that a key, once inserted into a table, will never be changed or re-inserted after deletion. In order to use jOOQ's operations correctly, you should design your database accordingly.

    @@ -11738,7 +11738,7 @@ DELETE FROM BOOK WHERE ID = 5;]]>

    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:

    - + - +

    See the manual's section about for some more insight on "attached" objects.

    - +

    Storing

    Storing a record will perform an or an . In general, new records are always inserted, whereas records loaded from the database are always updated. This is best visualised in code: @@ -11777,7 +11777,7 @@ BookRecord book2 = create.fetchOne(BOOK, BOOK.ID.equal(id)); // Update the record: UPDATE BOOK SET TITLE = 'Animal Farm' WHERE ID = [id] book2.setTitle("Animal Farm"); book2.store();]]> - +

    Some remarks about storing:

    @@ -11787,18 +11787,18 @@ book2.store();]]>
  • When loading records from , jOOQ will assume the record is a new record. It will hence attempt to INSERT it.
  • When you activate , storing a record may fail, if the underlying database record has been changed in the mean time.
  • - +

    Deleting

    Deleting a record will remove it from the database. Here's how you delete records:

    - + - +

    Refreshing

    Refreshing a record from the database means that jOOQ will issue a to refresh all record values that are not the primary key. This is particularly useful when you use jOOQ's feature, in case a modified record is "stale" and cannot be stored to the database, because the underlying database record has changed in the mean time. @@ -11817,7 +11817,7 @@ book.refresh();]]>

    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 :

    - + The "original" value, i.e. the value as it was originally fetched from the database or null, if the record was never in the database
  • The "changed" flag, indicating if the value was ever changed through the Record API.
  • - +

    The purpose of the above information is for jOOQ's to know, which values need to be stored to the database, and which values have been left untouched.

    @@ -11853,19 +11853,19 @@ for (BookRecord book : create.fetch(BOOK, BOOK.PUBLISHED_IN.equal(1948))) {

    Many databases support the concept of IDENTITY values, or key values. This is reflected by JDBC's method. jOOQ abstracts using this method as many databases and JDBC drivers behave differently with respect to generated keys. Let's assume the following SQL Server BOOK table:

    - +

    If you're using jOOQ's , the above table will generate a with an IDENTITY column. This information is used by jOOQ internally, to update IDs after calling :

    - +

    and contain foreign key navigation methods. These navigation methods allow for "navigating" inbound or outbound foreign key references by executing an appropriate query. An example is given here:

    - + books = author.fetchChildren(FK_BOOK_AUTHOR);]]>

    Tables without a PRIMARY KEY are considered non-updatable by jOOQ, as jOOQ has no way of uniquely identifying such a record within the database. If you're using jOOQ's , such tables will generate classes, instead of classes. When you fetch from such a table, the returned records will not allow for calling any of the methods.

    - +

    Note, that some databases use internal rowid or object-id values to identify such records. jOOQ does not support these vendor-specific record meta-data.

    @@ -11996,7 +11996,7 @@ Result books = author.fetchChildren(FK_BOOK_AUTHOR);]]>
    - +

    Optimised optimistic locking using TIMESTAMP fields

    If you're using jOOQ's , you can take indicate TIMESTAMP or UPDATE COUNTER fields for every generated table in the . Let's say we have this table:

    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:

    - +

    As before, without the added TIMESTAMP column, optimistic locking is transparent to the API.

    - +

    Optimised optimistic locking using VERSION fields

    Instead of using TIMESTAMPs, you may also use numeric VERSION fields, containing version numbers that are incremented by jOOQ upon store() calls. @@ -12065,7 +12065,7 @@ book2.store();]]>

    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:

    - + books = create.fetch(BOOK); @@ -12081,7 +12081,7 @@ create.batchStore(books);]]>

    - +
    CRUD SPI: RecordListener @@ -12092,11 +12092,11 @@ create.batchStore(books);]]>
  • Adding a central ID generation algorithm, generating UUIDs for all of your records.
  • Adding a central record initialisation mechanism, preparing the database prior to inserting a new record.
  • - +

    An example of such a RecordListener is given here:

    - + - +

    Now, configure jOOQ's runtime to load your listener

    @@ -12136,7 +12136,7 @@ DSLContext create = DSL.using(configuration);]]>

    If you're using jOOQ's , you can configure it to generate and DAOs for you. jOOQ then generates one DAO per , i.e. per table with a single-column primary key. Generated DAOs implement a common jOOQ type called . This type contains the following methods:

    - + corresponds to the DAO's related table //

    corresponds to the DAO's related generated POJO type // corresponds to the DAO's related table's primary key type. @@ -12147,23 +12147,23 @@ public interface DAO, P, T> { void insert(P object) throws DataAccessException; void insert(P... objects) throws DataAccessException; void insert(Collection

    objects) throws DataAccessException; - + // These methods allow for updating POJOs based on their primary key void update(P object) throws DataAccessException; void update(P... objects) throws DataAccessException; void update(Collection

    objects) throws DataAccessException; - + // These methods allow for deleting POJOs based on their primary key void delete(P... objects) throws DataAccessException; void delete(Collection

    objects) throws DataAccessException; void deleteById(T... ids) throws DataAccessException; void deleteById(Collection ids) throws DataAccessException; - + // These methods allow for checking record existence boolean exists(P object) throws DataAccessException; boolean existsById(T id) throws DataAccessException; long count() throws DataAccessException; - + // These methods allow for retrieving POJOs by primary key or by some other field List

    findAll() throws DataAccessException; P findById(T id) throws DataAccessException; @@ -12192,7 +12192,7 @@ public class BookDao extends DAOImpl {

    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:

    - +

    Note how the lambda expression receives a new, derived configuration that should be used within the local scope:

    - + { // Wrap configuration in a new DSLContext: DSL.using(configuration).insertInto(...); DSL.using(configuration).insertInto(...); - + // Or, reuse the new DSLContext within the transaction scope: DSLContext ctx = DSL.using(configuration); ctx.insertInto(...); ctx.insertInto(...); - + // ... but avoid using the scope from outside the transaction: create.insertInto(...); create.insertInto(...); }); ]]> - +

    - While some implementations (e.g. ones based on ThreadLocals, e.g. Spring or JTA) may allow you to reuse the globally scoped reference, the jOOQ transaction API design allows for TransactionProvider implementations that require your transactional code to use the new, locally scoped Configuration, instead. + While some implementations (e.g. ones based on ThreadLocals, e.g. Spring or JTA) may allow you to reuse the globally scoped reference, the jOOQ transaction API design allows for TransactionProvider implementations that require your transactional code to use the new, locally scoped Configuration, instead.

    @@ -12413,7 +12413,7 @@ class SpringTransaction implements Transaction {

    With jOOQ, it's simple. All of jOOQ's exceptions are "system exceptions", hence they are all unchecked.

    - +

    jOOQ's DataAccessException

    jOOQ uses its own to wrap any underlying that might have occurred. Note that all methods in jOOQ that may cause such a DataAccessException document this both in the Javadoc as well as in their method signature. @@ -12429,7 +12429,7 @@ class SpringTransaction implements Transaction {

  • InvalidResultException: An operation was performed expecting only one result, but several results were returned.
  • MappingException: Something went wrong when loading a record from a or when mapping a record into a POJO
  • - +

    Override jOOQ's exception handling

    The following section about documents means of overriding jOOQ's exception handling, if you wish to deal separately with some types of constraint violations, or if you raise business errors from your database, etc. @@ -12446,7 +12446,7 @@ class SpringTransaction implements Transaction {

    For convenience and better backwards-compatibility, consider extending instead of implementing this interface.

    - +

    Example: Query statistics ExecuteListener

    Here is a sample implementation of an ExecuteListener, that is simply counting the number of queries per type that are being executed using jOOQ: @@ -12463,11 +12463,11 @@ public class StatisticsListener extends DefaultExecuteListener { public void start(ExecuteContext ctx) { synchronized (STATISTICS) { Integer count = STATISTICS.get(ctx.type()); - + if (count == null) { count = 0; } - + STATISTICS.put(ctx.type(), count + 1); } } @@ -12510,7 +12510,7 @@ for (ExecuteType type : ExecuteType.values()) {

    Please read the for more details

    - +

    Example: Custom Logging ExecuteListener

    The following depicts an example of a custom ExecuteListener, which pretty-prints all queries being executed by jOOQ to stdout: @@ -12533,7 +12533,7 @@ public class PrettyPrinter extends DefaultExecuteListener { // Create a new DSLContext for logging rendering purposes // This DSLContext doesn't need a connection, only the SQLDialect... DSLContext create = DSL.using(ctx.dialect(), - + // ... and the flag for pretty-printing new Settings().withRenderFormatted(true)); @@ -12541,12 +12541,12 @@ public class PrettyPrinter extends DefaultExecuteListener { if (ctx.query() != null) { System.out.println(create.renderInlined(ctx.query())); } - + // If we're executing a routine else if (ctx.routine() != null) { System.out.println(create.renderInlined(ctx.routine())); } - + // If we're executing anything else (e.g. plain SQL) else if (!StringUtils.isBlank(ctx.sql())) { System.out.println(ctx.sql()); @@ -12556,12 +12556,12 @@ public class PrettyPrinter extends DefaultExecuteListener {

    See also the manual's sections about for more sample implementations of actual ExecuteListeners.

    - +

    Example: Bad query execution ExecuteListener

    You can also use ExecuteListeners to interact with your SQL statements, for instance when you want to check if executed or statements contain a WHERE clause. This can be achieved trivially with the following sample ExecuteListener:

    - + 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:

    - + @@ -12613,7 +12613,7 @@ public class DeleteOrUpdateWithoutWhereException extends RuntimeException {}

    With the above configuration, let's fetch some data with jOOQ

    - +

    @@ -12661,14 +12661,14 @@ Finishing : Total: 4.814ms, +3.375ms

  • 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
  • - +

    Optimise wisely

    Don't be put off by the above paragraphs. You should optimise wisely, i.e. only in places where you really need very high throughput to your database. jOOQ's overhead compared to plain JDBC is typically less than 1ms per query.

    - +
    Alternative execution models @@ -12678,7 +12678,7 @@ Finishing : Total: 4.814ms, +3.375ms

    - +
    Using jOOQ with JPA @@ -12687,11 +12687,11 @@ Finishing : Total: 4.814ms, +3.375ms

    These sections will show how to use jOOQ with JPA's native query API in order to fetch tuples or managed entities using the Java EE standards.

    - +

    In all of the following sections, let's assume we have the following JPA entities to model our database:

    - + - +
    Using jOOQ with JPA Native Query @@ -12794,7 +12794,7 @@ nativeQuery(em, DSL.using(configuration) books.forEach((Object[] book) -> System.out.println(book[0] + " " + book[1] + " wrote " + book[2]));]]>
    - +
    Using jOOQ with JPA entities @@ -12802,7 +12802,7 @@ books.forEach((Object[] book) -> System.out.println(book[0] + " " + book[1] + "

    The simplest way to fetch entities via the native query API is by passing the entity class along to the native query method. The following example maps jOOQ query results to JPA entities (). Just add the following utility method:

    - + List nativeQuery(EntityManager em, org.jooq.Query query, Class type) { // Extract the SQL statement from the jOOQ query: @@ -12843,7 +12843,7 @@ static Object convertToDatabaseType(Param param) {

    With the above simple API, we're ready to write complex jOOQ queries and map their results to JPA entities:

    - + authors = nativeQuery(em, DSL.using(configuration) @@ -12854,14 +12854,14 @@ nativeQuery(em, authors.forEach(author -> { System.out.println(author.firstName + " " + author.lastName + " wrote"); - + books.forEach(book -> { System.out.println(" " + book.title); }); });]]>
    - +
    Using jOOQ with JPA EntityResult @@ -12869,11 +12869,11 @@ authors.forEach(author -> {

    While JPA specifies how the mapping should be implemented (e.g. using ), there are no limitations regarding how you want to generate the SQL statement. The following, simple example shows how you can produce JPABook and JPAAuthor entities () from a jOOQ-generated SQL statement.

    - +

    In order to do so, we'll need to specify the . This can be done on any entity, and in this case, we're using :

    - + { } ) } -)]]> - +)]]> +

    Note how we need to map between:

    @@ -12903,11 +12903,11 @@ authors.forEach(author -> {
  • , which corresponds to the entity's attribute name
  • , which corresponds to the SQL result's column name
  • - +

    With the above boilerplate in place, we can now fetch entities using jOOQ and JPA:

    - + List nativeQuery(EntityManager em, org.jooq.Query query, String resultSetMapping) { // Extract the SQL statement from the jOOQ query: @@ -12925,7 +12925,7 @@ authors.forEach(author -> {

    Note, if you're using or , make sure to take those into account as well. E.g. as follows:

    - + List nativeQuery(EntityManager em, org.jooq.Query query, String resultSetMapping) { // Extract the SQL statement from the jOOQ query: @@ -12946,11 +12946,11 @@ static Object convertToDatabaseType(Param param) { }]]>

    Using the above API

    - +

    Now that we have everything setup, we can use the above API to run a jOOQ query to fetch JPA entities like this:

    - + result = nativeQuery(em, DSL.using(configuration @@ -12964,7 +12964,7 @@ nativeQuery(em, ) .from(AUTHOR) .join(BOOK).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) - .orderBy(BOOK.ID)), + .orderBy(BOOK.ID)), "bookmapping" // The name of the SqlResultSetMapping ); @@ -12973,11 +12973,11 @@ result.forEach((Object[] entities) -> { JPABook book = (JPABook) entities[0]; System.out.println(author.firstName + " " + author.lastName + " wrote " + book.title); -});]]> +});]]>

    The entities are now ready to be modified and persisted again.

    - +

    Caveats:

    @@ -12989,7 +12989,7 @@ result.forEach((Object[] entities) -> {
    -
    +
    @@ -13043,7 +13043,7 @@ result.forEach((Object[] entities) -> {

    You need to tell jOOQ some things about your database connection. Here's an example of how to do it for an Oracle database

    - + @@ -13052,7 +13052,7 @@ result.forEach((Object[] entities) -> { jdbc:oracle:thin:@[your jdbc connection parameters] [your database user] [your database password] - + user[db-user] @@ -13064,9 +13064,9 @@ result.forEach((Object[] entities) -> { org.jooq.util.oracle.OracleDatabase @@ -13100,9 +13100,9 @@ result.forEach((Object[] entities) -> { Use the pipe to separate several expressions) Watch out for case-sensitivity. Depending on your database, this might be important! - + You can create case-insensitive regular expressions using this syntax: (?i:expr) - + Whitespace is ignored and comments are possible. --> .* @@ -13133,7 +13133,7 @@ result.forEach((Object[] entities) -> { @@ -13154,13 +13154,13 @@ result.forEach((Object[] entities) -> {

    Code generation works by calling this class with the above property file as argument.

    - + org.jooq.util.GenerationTool /jooq-config.xml

    Be sure that these elements are located on the classpath:

    - +
    • The XML configuration file
    • jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar
    • @@ -13185,7 +13185,7 @@ result.forEach((Object[] entities) -> {
    • this example uses jOOQ's log4j support by adding log4j.xml and log4j.jar to the project classpath.
    • the actual jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar artefacts may contain version numbers in the file names.
    - +
    Eclipse configuration
    @@ -13227,11 +13227,11 @@ result.forEach((Object[] entities) -> { org.jooq jooq-codegen-maven @@ -13350,9 +13350,9 @@ result.forEach((Object[] entities) -> { false @@ -13365,7 +13365,7 @@ result.forEach((Object[] entities) -> { production schema. Use this to override your local development schema name for source code generation. If not specified, this will be the same as the input-schema. - + This will be ignored if outputSchemaToDefault is set to true --> [your database schema / owner / name] @@ -13475,33 +13475,33 @@ result.forEach((Object[] entities) -> { Defaults to false --> false - false - + true - + false ]]>
    @@ -13510,7 +13510,7 @@ result.forEach((Object[] entities) -> {

    Some of the above properties depend on other properties to work correctly. For instance, when generating immutable pojos, pojos must be generated. jOOQ will enforce such properties even if you tell it otherwise. Here is a list of property interdependencies:

    - +
    • When daos = true, then jOOQ will set relations = true
    • When daos = true, then jOOQ will set records = true
    • @@ -13519,7 +13519,7 @@ result.forEach((Object[] entities) -> {
    - +
    Programmatic generator configuration @@ -13527,7 +13527,7 @@ result.forEach((Object[] entities) -> {

    In the previous sections, we have covered how to set up jOOQ's code generator using XML, either by running a standalone Java application, or by using Maven. However, it is also possible to use jOOQ's GenerationTool programmatically. The XSD file used for the configuration (http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd) is processed using XJC to produce Java artefacts. The below example uses those artefacts to produce the equivalent configuration of the previous :

    - +

    For the above example, you will need all of jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, and jooq-codegen-{jooq-version}.jar, on your classpath.

    - +

    Manually loading the XML file

    - +

    Alternatively, you can also load parts of the configuration from an XML file using JAXB and programmatically modify other parts using the code generation API:

    - + org.h2.Driver ]]> - +

    Load the above using standard JAXB API:

    - +

    - +
    Custom generator strategies @@ -13600,7 +13600,7 @@ GeberationTool.generate(configuration);]]>

    jOOQ allows you to override default implementations of the code generator or the generator strategy. Specifically, the latter can be very useful if you want to inject custom behaviour into jOOQ's code generator with respect to naming classes, members, methods, and other Java objects.

    - + @@ -13825,58 +13825,58 @@ public class Book implements java.io.Serializable { - + MY_SCHEMA - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - +
    - + MY_TABLE - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomBaseClass com.example.MyOptionalCustomInterface
    - + - + MY_FIELD - + --> MatcherRule --> MatcherRule @@ -13884,30 +13884,30 @@ public class Book implements java.io.Serializable { --> MatcherRule - + - + MY_ROUTINE - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + - + MY_SEQUENCE - + --> MatcherRule @@ -13923,19 +13923,19 @@ public class Book implements java.io.Serializable { CAMEL - + PREFIX_$0_SUFFIX ]]> - +

    Some examples

    The following example shows a matcher strategy that adds a "T_" prefix to all table classes and to table identifiers: @@ -13946,7 +13946,7 @@ public class Book implements java.io.Serializable { - + UPPER @@ -13981,13 +13981,13 @@ public class Book implements java.io.Serializable { ]]> - +

    For more information about each XML tag, please refer to the http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd XSD file.

    - +
    Custom code sections @@ -14034,7 +14034,7 @@ public class Book implements java.io.Serializable {

    Any of the below methods can be overridden:

    - + Tables.java: This file contains all table objects in the form of static member references to the actual singleton object
  • UDTs.java: This file contains all UDT objects in the form of static member references to the actual singleton object
  • - +

    Referencing global artefacts

    When referencing global artefacts from your client application, you would typically static import them as such:

    - + @@ -14130,7 +14130,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate a implementation that looks like this:

    - + { // The singleton instance @@ -14146,7 +14146,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE) public Book as(java.lang.String alias) { return new Book(alias); } - + // [...] }]]> @@ -14165,7 +14165,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)
  • instanceFields: This flag controls the "static" keyword on table columns, as well as aliasing convenience
  • records: The generated record type is referenced from tables allowing for type-safe single-table record fetching
  • - +

    Flags controlling table generation

    Table generation cannot be deactivated @@ -14179,7 +14179,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate an implementation that looks like this:

    - + - +

    Flags influencing generated records

    These flags from the influence generated records: @@ -14237,7 +14237,7 @@ implements IBook {

  • interfaces: If interfaces are generated, records will implement them
  • jpaAnnotations: JPA annotations are used on generated records
  • - +

    Flags controlling record generation

    Record generation can be deactivated using the records flag @@ -14251,7 +14251,7 @@ implements IBook {

    Every table in your database will generate a POJO implementation that looks like this:

    - + - +

    Flags influencing generated POJOs

    These flags from the influence generated POJOs: @@ -14300,7 +14300,7 @@ public class Book implements java.io.Serializable

  • jpaAnnotations: JPA annotations are used on generated records
  • validationAnnotations: JSR-303 validation annotations are used on generated records
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the pojos flag @@ -14314,16 +14314,16 @@ public class Book implements java.io.Serializable

    Every table in your database will generate an interface that looks like this:

    - + - +

    Flags influencing generated interfaces

    These flags from the influence generated interfaces: @@ -14332,7 +14332,7 @@ public class Book implements java.io.Serializable

  • dateAsTimestamp: This influences all relevant getters and setters
  • unsignedTypes: This influences all relevant getters and setters
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the interfaces flag @@ -14347,7 +14347,7 @@ public class Book implements java.io.Serializable

    Every table in your database will generate a implementation that looks like this:

    - + { // Generated constructors @@ -14371,10 +14371,10 @@ public class Book implements java.io.Serializable public List fetchByAuthorId(Integer... values) { return fetch(BOOK.AUTHOR_ID, values); } - + // [...] }]]> - +

    Flags controlling DAO generation

    DAO generation can be activated using the daos flag @@ -14388,13 +14388,13 @@ public class Book implements java.io.Serializable

    Every sequence in your database will generate a implementation that looks like this:

    - + S_AUTHOR_ID = new SequenceImpl("S_AUTHOR_ID", TEST, SQLDataType.INTEGER); }]]> - +

    Flags controlling sequence generation

    Sequence generation cannot be deactivated @@ -14432,7 +14432,7 @@ public class Book implements java.io.Serializable public BigDecimal getResult() { return getValue(RESULT); } - + // [...] }]]> @@ -14454,7 +14454,7 @@ public class Book implements java.io.Serializable

    Every UDT in your database will generate a implementation that looks like this:

    - + { // The singleton UDT instance @@ -14467,10 +14467,10 @@ public class Book implements java.io.Serializable createField("CITY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); public static final UDTField COUNTRY = createField("COUNTRY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); - + // [...] }]]> - +

    Besides the implementation, a implementation is also generated

    @@ -14485,7 +14485,7 @@ public class Book implements java.io.Serializable public String getCity() {...} public void setCountry(String value) {...} public String getCountry() {...} - + // [...] }]]>
    @@ -14514,20 +14514,20 @@ public class Book implements java.io.Serializable BOOLEAN .*\.IS_VALID - + .* @@ -14558,7 +14558,7 @@ public class Book implements java.io.Serializable GregorianCalendar - + java.util.GregorianCalendar @@ -14574,21 +14574,21 @@ public class Book implements java.io.Serializable GregorianCalendar .*\.DATE_OF_.* - + .* @@ -14622,15 +14622,15 @@ create.selectFrom(AUTHOR)
    - - + +
    Custom data type binding

    The previous section discussed the case where your custom data type is mapped onto a standard JDBC type as contained in . In some cases, however, you want to map your own type onto a type that is not explicitly supported by JDBC, such as for instance, PostgreSQL's various advanced data types like JSON or HSTORE, or PostGIS types. For this, you can register an for relevant columns in your code generator. Consider the following trivial implementation of a binding for PostgreSQL's JSON data type, which binds the JSON string in PostgreSQL to a Google GSON object:

    - + {

    The above implementation intercepts all the interaction on a JDBC level, such that jOOQ will never need to know how to crrectly serialise / deserialise your custom data type. Similar to what we've seen in the previous section about , we can now register such a binding to the code generator. Note that you will reuse the same types of XML elements (<customType/> and <forcedType/>):

    - + JsonElement - + com.google.gson.JsonElement @@ -14740,26 +14740,26 @@ public class PostgresJSONGsonBinding implements Binding { JsonElement .*JSON.* - + .* -]]> +]]>

    See also the section about to learn about an alternative use of <forcedTypes/>. @@ -14779,7 +14779,7 @@ public class PostgresJSONGsonBinding implements Binding {

    - +
    Mapping generated schemata and tables @@ -14800,23 +14800,23 @@ public class PostgresJSONGsonBinding implements Binding {
    - +
    Code generation for large schemas

    Databases can become very large in real-world applications. This is not a problem for jOOQ's code generator, but it can be for the Java compiler. jOOQ generates some classes for . These classes can hit two sorts of limits of the compiler / JVM:

    - +
    • Methods (including static / instance initialisers) are allowed to contain only 64kb of bytecode.
    • Classes are allowed to contain at most 64k of constant literals
    - +

    While there exist workarounds for the above two limitations (delegating initialisations to nested classes, inheriting constant literals from implemented interfaces), the preferred approach is either one of these:

    - +
    • Distribute your database objects in several schemas. That is probably a good idea anyway for such large databases
    • to exclude excess database objects
    • @@ -14891,7 +14891,7 @@ public class PostgresJSONGsonBinding implements Binding {

      In such a setup, you might have a pre-existing schema implemented using JPA-annotated entities. Your real database schema might not be accessible while developing, or it is not a first-class citizen in your application (i.e. you follow a Java-first approach). This section explains how you can generate jOOQ classes from such a JPA model. Consider this model:

      - + org.jooq jooq-meta-extensions @@ -14949,7 +14949,7 @@ public class Book {

      With that dependency in place, you can now specify the JPADatabase in your code generator configuration:

      - + org.jooq.util.jpa.JPADatabase @@ -14968,7 +14968,7 @@ public class Book {

    - +
    Generating code from XML files @@ -14984,7 +14984,7 @@ public class Book {

    An example schema definition containing simple schema, table, column definitions can be seen below:

    - + @@ -15045,7 +15045,7 @@ public class Book { ... - + TEST @@ -15060,18 +15060,18 @@ public class Book {

    The above file can be made available to the code generator configuration by using the XMLDatabase as follows:

    - + org.jooq.util.xml.XMLDatabase - + dialect ORACLE - + xml-file @@ -15082,16 +15082,16 @@ public class Book { ]]>

    - If you already have a different XML format for your database, you can either XSL transform your own format into the one above via an additional Maven plugin, or pass the location of an XSL file to the XMLDatabase by providing an additional property: + If you already have a different XML format for your database, you can either XSL transform your own format into the one above via an additional Maven plugin, or pass the location of an XSL file to the XMLDatabase by providing an additional property:

    - + org.jooq.util.xml.XMLDatabase - + ... - + xsl-file @@ -15102,7 +15102,7 @@ public class Book { ]]>

    - This XML configuration can now be checked in and versioned, and modified independently from your live database schema. + This XML configuration can now be checked in and versioned, and modified independently from your live database schema.

    @@ -15117,14 +15117,14 @@ public class Book { - - + ]]> @@ -15143,7 +15143,7 @@ public class Book { generate-sources - @@ -15155,20 +15155,20 @@ public class Book { - + - org.jooq + org.jooq.trial jooq-codegen {jooq-version} @@ -15176,7 +15176,7 @@ public class Book { ]]> - +
    Running the code generator with Gradle @@ -15184,7 +15184,7 @@ public class Book {

    We recommend using the Gradle plugin by Etienne Studer (from Gradle Inc.). It provides a concise DSL that allows you to tune all configuration properties supported by each jOOQ version. Please direct any support questions or issues you may find directly to the third party plugin vendor.

    - +

    Alternatively, the XML MarkupBuilder can be used

    If you don't want to use the above third party plugin, there's also the possibility to use jOOQ's standalone code generator for simplicity. The following working example build.gradle script should work out of the box: @@ -15278,11 +15278,11 @@ org.jooq.util.GenerationTool.generate(

    When writing unit tests for your data access layer, you have probably used some generic mocking tool offered by popular providers like Mockito, jmock, mockrunner, or even DBUnit. With jOOQ, you can take advantage of the built-in JDBC mock API that allows you to emulate a simple database on the JDBC level for precisely those SQL/JDBC use cases supported by jOOQ.

    - +

    - Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider. + Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider.

    - +

    Mocking the JDBC API

    JDBC is a very complex API. It takes a lot of time to write a useful and correct mock implementation, implementing at least these interfaces: @@ -15295,16 +15295,16 @@ org.jooq.util.GenerationTool.generate(

  • - +

    Optionally, you may even want to implement interfaces, such as , , , and many others. In addition to the above, you might need to find a way to simultaneously support incompatible JDBC minor versions, such as 4.0, 4.1

    - +

    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 :

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    As you can see, the configuration setup is simple. Now, the MockDataProvider acts as your single point of contact with JDBC / jOOQ. It unifies any of these execution modes, transparently:

    - +
    • Statements without results
    • Statements without results but with generated keys
    • @@ -15327,16 +15327,16 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
    • Batch statements with single queries and multiple bind value sets
    • Batch statements with multiple queries and no bind values
    - +

    The above are the execution modes supported by jOOQ. Whether you're using any of jOOQ's various fetching modes (e.g. , , , ) is irrelevant, as those modes are all built on top of the standard JDBC API.

    - +

    Implementing MockDataProvider

    Now, here's how to implement MockDataProvider:

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc // 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 String sql = ctx.sql(); - + // Exceptions are propagated through the JDBC and jOOQ APIs if (sql.toUpperCase().startsWith("DROP")) { throw new SQLException("Statement not supported: " + sql); } - + // You decide, whether any given statement returns results, and how many else if (sql.toUpperCase().startsWith("SELECT")) { - + // Always return one author record Result result = create.newResult(AUTHOR); result.add(create.newRecord(AUTHOR)); @@ -15364,12 +15364,12 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc result.get(0).setValue(AUTHOR.LAST_NAME, "Orwell"); mock[0] = new MockResult(1, result); } - + // You can detect batch statements easily else if (ctx.batch()) { // [...] } - + return mock; } }]]> @@ -15381,17 +15381,17 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • : The number of affected rows
  • : The result set
  • - +

    You should return as many MockResult objects as there were query executions (in ) or results (in ). Instead of an awkward JDBC ResultSet, however, you can construct a "friendlier" with your own record types. The jOOQ mock API will use meta data provided with this Result in order to create the necessary JDBC

    - +

    See the for a list of rules that you should follow.

    - +
    SQL 2 jOOQ Parser @@ -15401,20 +15401,20 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    Gudu Software Ltd has been selling enterprise quality SQL software to hundreds of customers to help them migrate from one database to another using the General SQL Parser. Now you can take advantage of their knowledge to parse your SQL statements and transform them directly into jOOQ statements using a free trial version of SQL 2 jOOQ!

    - +

    It's as simple as this!

    - +
    • Create a JDBC connection
    • Create a new SQL2jOOQ converter object
    • Convert your SQL code
    • Get the result
    - +

    See it in action:

    - + If all goes well, the above program yields:

    - + > result = create.select( Actor.ACTOR.FIRST_NAME, Actor.ACTOR.LAST_NAME ) @@ -15478,21 +15478,21 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    Please take note of the fact that the sql2jooq library is Open Source, but it depends on the commercial gsp.jar parser, whose trial licensing terms can be seen here:

    - +

    https://github.com/sqlparser/sql2jooq/blob/master/sql2jooq/LICENSE-GSQLPARSER.txt

    - +

    For more information about the General SQL Parser, please refer to the product blog.

    - +

    Please report any issues, ideas, wishes to the jOOQ user group or the sql2jooq GitHub project.

    - +
    jOOQ Console @@ -15541,7 +15541,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • Sybase Adaptive Server Enterprise 15.5
  • Sybase SQL Anywhere 12
  • - +

    For an up-to-date list of currently supported RDBMS, please refer to http://www.jooq.org/legal/licensing/#databases.

    @@ -15562,7 +15562,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME, This chapter should document the most important notes about SQL, JDBC and jOOQ data types.

    - +
    BLOBs and CLOBs @@ -15572,7 +15572,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    Unsigned integer types @@ -15596,7 +15596,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
    - +
    INTERVAL data types @@ -15607,11 +15607,11 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • YEAR TO MONTH: This interval type models a number of months and years
  • DAY TO SECOND: This interval type models a number of days, hours, minutes, seconds and milliseconds
  • - +

    Both interval types ship with a variant of subtypes, such as DAY TO HOUR, HOUR TO SECOND, etc. jOOQ models these types as Java objects extending : (where Number.intValue() corresponds to the absolute number of months) and (where Number.intValue() corresponds to the absolute number of milliseconds)

    - +

    Interval arithmetic

    In addition to the documented previously, interval arithmetic is also supported by jOOQ. Essentially, the following operations are supported: @@ -15626,7 +15626,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    XML data types @@ -15635,7 +15635,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    Geospacial data types @@ -15645,7 +15645,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    CURSOR data types @@ -15654,22 +15654,22 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    > cursor;]]> - +

    In fact, such a cursor will be fetched immediately by jOOQ and wrapped in an object.

    - +
    ARRAY and TABLE data types

    The SQL standard specifies ARRAY data types, that can be mapped to Java arrays as such:

    - + intArray;]]> - +

    The above array type is supported by these SQL dialects:

    @@ -15678,33 +15678,33 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • HSQLDB
  • Postgres
  • - +

    Oracle typed arrays

    Oracle has strongly-typed arrays and table types (as opposed to the previously seen anonymously typed arrays). These arrays are wrapped by types.

    - +
    Oracle DATE data type

    - Oracle's DATE data type does not conform to the SQL standard. It is really a TIMESTAMP(0), i.e. a TIMESTAMP with a fractional second precision of zero. The most appropriate JDBC type for Oracle DATE types is . + Oracle's DATE data type does not conform to the SQL standard. It is really a TIMESTAMP(0), i.e. a TIMESTAMP with a fractional second precision of zero. The most appropriate JDBC type for Oracle DATE types is .

    - +

    Performance implications

    - +

    When binding TIMESTAMP variables to SQL statements, instead of truncating such variables to DATE, the cost based optimiser may choose to widen the database column from DATE to TIMESTAMP using an Oracle INTERNAL_FUNCTION(), which prevents index usage. Details about this behaviour can be seen in this Stack Overflow question.

    - +

    Use a data type binding to work around this issue

    - +

    The best way to work around this issue is to implement a , which generates the CAST expression for every bind variable:

    - + ctx) throws SQLException { render.keyword("cast").sql('(') @@ -15713,15 +15713,15 @@ public final void sql(BindingSQLContext ctx) throws SQLException { }]]>

    Deprecated functionality

    - +

    Historic versions of jOOQ used to support a <dateAsTimestamp/> flag, which can be used with the out-of-the-box as a :

    - + true - + @@ -15740,7 +15740,7 @@ public final void sql(BindingSQLContext ctx) throws SQLException {

    For more information, please refer to . -

    +

    @@ -15752,12 +15752,12 @@ public final void sql(BindingSQLContext ctx) throws SQLException {

    jOOQ takes SQL as an external domain-specific language and maps it onto Java, creating an internal domain-specific language. Internal DSLs cannot 100% implement their external language counter parts, as they have to adhere to the syntax rules of their host or target language (i.e. Java). This section explains the various problems and workarounds encountered and implemented in jOOQ.

    - +

    SQL allows for "keywordless" syntax

    SQL syntax does not always need keywords to form expressions. The clause takes various argument assignments:

    - + UPDATE t SET a = 1, b = 2 update(t).set(a, 1).set(b, 2) @@ -15775,12 +15775,12 @@ public final void sql(BindingSQLContext ctx) throws SQLException {

    In this case, ROW is an actual (optional) SQL keyword, implemented by at least PostgreSQL.

    - +

    SQL contains "composed" keywords

    As most languages, SQL does not attribute any meaning to whitespace. However, whitespace is important when forming "composed" keywords, i.e. SQL clauses composed of several keywords. jOOQ follows standard Java method naming conventions to map SQL keywords (case-insensitive) to Java methods (case-sensitive, camel-cased). Some examples:

    - + GROUP BY ORDER BY @@ -15793,7 +15793,7 @@ whenMatchedThenUpdate()

    Future versions of jOOQ may use all-uppercased method names in addition to the camel-cased ones (to prevent collisions with Java keywords):

    - + GROUP BY ORDER BY @@ -15824,7 +15824,7 @@ WHEN_MATCHED_THEN_UPDATE()

    The above example omits THEN and END keywords in Java. Future versions of jOOQ may comprise a more complete DSL, including such keywords again though, to provide a more 1:1 match for the SQL language.

    - +

    SQL contains "superfluous" syntactic elements

    Some SQL constructs are hard to map to Java, but they are also not really necessary. SQL often expects syntactic parentheses where they wouldn't really be needed, or where they feel slightly inconsistent with the rest of the SQL language. @@ -15861,7 +15861,7 @@ WHEN_MATCHED_THEN_UPDATE()

    jOOQ replaces those keywords by "synonyms":

    - + CASE .. ELSE PIVOT .. FOR .. IN .. @@ -15889,7 +15889,7 @@ pivot(..).on(..).in(..)

    Most SQL operators have to be mapped to descriptive method names in Java, as Java does not allow operator overloading:

    - + , != @@ -15918,7 +15918,7 @@ set(a, b)

    This is less of a syntactic SQL feature than a semantic one. In SQL, objects can be referenced before (i.e. "lexicographically before") they are declared. This is particularly true for

    - + @@ -15929,7 +15929,7 @@ select(t.a).from(t)]]>

    A more sophisticated example are common table expressions (CTE), which are currently not supported by jOOQ:

    - + WITH t(a, b) AS ( SELECT 1, 2 FROM DUAL ) @@ -15941,7 +15941,7 @@ FROM t

    - +
    jOOQ's BNF pseudo-notation @@ -15950,7 +15950,7 @@ FROM t

    - +
    Quality Assurance @@ -15962,16 +15962,16 @@ FROM t
  • To add lots of type-safety to your inline SQL
  • To increase productivity when writing inline SQL using your favourite IDE's autocompletion capabilities
  • - +

    With jOOQ being in the core of your application, you want to be sure that you can trust jOOQ. That is why jOOQ is heavily unit and integration tested with a strong focus on integration tests:

    - +

    Unit tests

    Unit tests are performed against dummy JDBC interfaces using http://jmock.org/. These tests verify that various implementations render correct SQL and bind variables correctly.

    - +

    Integration tests

    This is the most important part of the jOOQ test suites. Some 1500 queries are currently run against a standard integration test database. Both the test database and the queries are translated into every one of the 14 supported SQL dialects to ensure that regressions are unlikely to be introduced into the code base. @@ -15982,17 +15982,17 @@ FROM t

    jOOQ integration tests run the weirdest and most unrealistic queries. As a side-effect of these extensive integration test suites, many corner-case bugs for JDBC drivers and/or open source databases have been discovered, feature requests submitted through jOOQ and reported mainly to CUBRID, Derby, H2, HSQLDB.

    - +

    Code generation tests

    For every one of the 14 supported integration test databases, source code is generated and the tiniest differences in generated source code can be discovered. In case of compilation errors in generated source code, new test tables/views/columns are added to avoid regressions in this field.

    - +

    API Usability tests and proofs of concept

    jOOQ is used in jOOQ-meta as a proof of concept. This includes complex queries such as the following Postgres query

    - + These rather complex queries show that the jOOQ API is fit for advanced SQL use-cases, compared to the rather simple, often unrealistic queries in the integration test suite.

    - +

    Clean API and implementation. Code is kept DRY

    As a general rule of thumb throughout the jOOQ code, everything is kept DRY. Some examples: @@ -16057,19 +16057,19 @@ for (Record record : create.select(

    - +
    Migrating to jOOQ 3.0

    This section is for all users of jOOQ 2.x who wish to upgrade to the next major release. In the next sub-sections, the most important changes are explained. Some code hints are also added to help you fix compilation errors.

    - +

    Type-safe row value expressions

    Support for has been added in jOOQ 2.6. In jOOQ 3.0, many API parts were thoroughly (but often incompatibly) changed, in order to provide you with even more type-safety.

    - +

    Here are some affected API parts:

    @@ -16079,11 +16079,11 @@ for (Record record : create.select(
  • IN predicates and comparison predicates taking subselects changed incompatibly
  • INSERT and MERGE statements now take typesafe VALUES() clauses
  • - +

    Some hints related to row value expressions:

    - + record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result> result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch(); @@ -16091,31 +16091,31 @@ Result> result = create.select(BOOK.TITLE, BOOK.ID).fro // But Record2 extends Record. You don't have to use the additional typesafety: Record record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch();]]> - +

    SelectQuery and SelectXXXStep are now generic

    In order to support type-safe row value expressions and type-safe Record[N] types, SelectQuery is now generic: SelectQuery<R>

    - +

    SimpleSelectQuery and SimpleSelectXXXStep API were removed

    The duplication of the SELECT API is no longer useful, now that SelectQuery and SelectXXXStep are generic.

    - +

    Factory was split into DSL (query building) and DSLContext (query execution)

    The pre-existing Factory class has been split into two parts:

    - +
    1. 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
    2. 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 renamed to DSLContext. An example:

    - + - +

    Quantified comparison predicates

    Field.equalAny(...) and similar methods have been removed in favour of Field.equal(any(...)). This greatly simplified the Field API. An example:

    - + > subselect = any(select(BOOK.ID).from(BOOK)); Condition condition = BOOK.ID.equal(subselect);]]> - +

    FieldProvider

    The FieldProvider marker interface was removed. Its methods still exist on FieldProvider subtypes. Note, they have changed names from getField() to field() and from getIndex() to indexOf()

    - +

    GroupField

    GroupField has been introduced as a DSL marker interface to denote fields that can be passed to GROUP BY clauses. This includes all org.jooq.Field types. However, fields obtained from ROLLUP(), CUBE(), and GROUPING SETS() functions no longer implement Field. Instead, they only implement GroupField. An example:

    - + field1a = Factory.rollup(...); // OK Field field2a = Factory.one(); // OK @@ -16161,19 +16161,19 @@ GroupField field1b = DSL.rollup(...); // OK Field field1c = DSL.rollup(...); // Compilation error GroupField field2b = DSL.one(); // OK Field field2c = DSL.one(); // OK]]> - +

    NULL predicate

    Beware! Previously, Field.equal(null) was translated internally to an IS NULL predicate. This is no longer the case. Binding Java "null" to a comparison predicate will result in a regular comparison predicate (which never returns true). This was changed for several reasons:

    - +
    • To most users, this was a surprising "feature".
    • Other predicates didn't behave in such a way, e.g. the IN predicate, the BETWEEN predicate, or the LIKE predicate.
    • Variable binding behaved unpredictably, as IS NULL predicates don't bind any variables.
    • The generated SQL depended on the possible combinations of bind values, which creates unnecessary hard-parses every time a new unique SQL statement is rendered.
    - +

    Here is an example how to check if a field has a given value, without applying SQL's ternary NULL logic:

    @@ -16186,7 +16186,7 @@ Condition condition1 = BOOK.TITLE.equal(possiblyNull); // jOOQ 3.0 Condition condition2 = BOOK.TITLE.equal(possiblyNull).or(BOOK.TITLE.isNull().and(val(possiblyNull).isNull())); Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    Configuration

    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 @@ -16200,7 +16200,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> In order to resolve confusion that used to arise because of different lifecycle durations, these types are now no longer formally connected through inheritance.

    - +

    ConnectionProvider

    In order to allow for simpler connection / data source management, jOOQ externalised connection handling in a new ConnectionProvider type. The previous two connection modes are maintained backwards-compatibly (JDBC standalone connection mode, pooled DataSource mode). Other connection modes can be injected using: @@ -16210,24 +16210,24 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    These are some side-effects of the above change

    - +
    • 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. This resolves many class loader issues that were encountered before. It also helps listener implementations control their lifecycles themselves.

    - +

    Data type API

    The data type API has been changed drastically in order to enable some new DataType-related features. These changes include: @@ -16237,16 +16237,16 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]>[SQLDialect]DataType and SQLDataType no longer implement DataType. They're mere constant containers

  • Various minor API changes have been done.
  • - +

    Object renames

    These objects have been moved / renamed:

    - +
    • jOOU: a library used to represent unsigned integer types was moved from org.jooq.util.unsigned to org.jooq.util.types (which already contained INTERVAL data types)
    - +

    Feature removals

    Here are some minor features that have been removed in jOOQ 3.0 @@ -16340,7 +16340,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> --> diff --git a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.8.xml b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.8.xml index 1af4481ddc..da58bc0a7b 100644 --- a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.8.xml +++ b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.8.xml @@ -126,7 +126,7 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ's reason for being - compared to SQL / JDBC

    So why not just use SQL? @@ -149,14 +149,14 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ is different

    SQL was never meant to be abstracted. To be confined in the narrow boundaries of heavy mappers, hiding the beauty and simplicity of relational data. SQL was never meant to be object-oriented. SQL was never meant to be anything other than... SQL!

    - + - +
    Getting started with jOOQ @@ -346,12 +346,12 @@ limitations under the License.

    This section helps you correctly interpret this manual in the context of jOOQ.

    - +

    Code blocks

    The following are code blocks:

    - + @@ -367,7 +367,7 @@ org.jooq.property=value]]>

    These are useful to provide examples in code. Often, with jOOQ, it is even more useful to compare SQL code with its corresponding Java/jOOQ code. When this is done, the blocks are aligned side-by-side, with SQL usually being on the left, and an equivalent jOOQ DSL query in Java usually being on the right:

    - + @@ -379,17 +379,17 @@ create.selectOne().fetch()]]>

    The contents of code blocks follow conventions, too. If nothing else is mentioned next to any given code block, then the following can be assumed:

    - - + + - +

    Your naming may differ, of course. For instance, you could name the "create" instance "db", instead.

    - +

    Execution

    - +

    When you're coding PL/SQL, T-SQL or some other procedural SQL language, SQL statements are always executed immediately at the semi-colon. This is not the case in jOOQ, because as an internal DSL, jOOQ can never be sure that your statement is complete until you call fetch() or execute(). The manual tries to apply fetch() and execute() as thoroughly as possible. If not, it is implied:

    @@ -429,7 +429,7 @@ create.update(T).set(T.V, 1).execute();]]>

    jOOQ allows to override runtime behaviour using . If nothing is specified, the default runtime settings are assumed.

    - +

    Sample database

    jOOQ query examples run against the sample database. See the manual's section about to learn more about the sample database. @@ -464,7 +464,7 @@ CREATE TABLE book ( title VARCHAR2(400) NOT NULL, published_in NUMBER(7) NOT NULL, language_id NUMBER(7) NOT NULL, - + CONSTRAINT fk_book_author FOREIGN KEY (author_id) REFERENCES author(id), CONSTRAINT fk_book_language FOREIGN KEY (language_id) REFERENCES language(id) ); @@ -477,7 +477,7 @@ CREATE TABLE book_to_book_store ( name VARCHAR2(400) NOT NULL, book_id INTEGER NOT NULL, stock INTEGER, - + PRIMARY KEY(name, book_id), CONSTRAINT fk_b2bs_book_store FOREIGN KEY (name) REFERENCES book_store (name) ON DELETE CASCADE, CONSTRAINT fk_b2bs_book FOREIGN KEY (book_id) REFERENCES book (id) ON DELETE CASCADE @@ -488,7 +488,7 @@ CREATE TABLE book_to_book_store (

    In addition to the above, you may assume the following sample data:

    - + Effectively, jOOQ was originally designed to replace any other database abstraction framework short of the ones handling connection pooling (and more sophisticated )

    - +

    Use jOOQ the way you prefer

    ... but open source is community-driven. And the community has shown various ways of using jOOQ that diverge from its original intent. Some use cases encountered are: @@ -547,7 +547,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]>Using jOOQ for SQL building and Spring Data for SQL execution

  • Using jOOQ without the to build the basis of a framework for dynamic SQL execution.
  • - +

    The following sections explain about various use cases for using jOOQ in your application.

    @@ -560,7 +560,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]> This is the most simple of all use cases, allowing for construction of valid SQL for any database. In this use case, you will not use and probably not even . Instead, you'll use to wrap strings, literals and other user-defined objects into an object-oriented, type-safe AST modelling your SQL statements. An example is given here:

    - + - +

    The SQL string built with the jOOQ query DSL can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools (note that since jOOQ uses PreparedStatement by default, this will generate a bind variable for "1948". ).

    @@ -597,7 +597,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID)) .where(BOOK.PUBLISHED_IN.equal(1948)) .getSQL();]]> - +

    The SQL string that you can generate as such can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools.

    @@ -617,7 +617,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    Instead of any tool mentioned in the previous chapters, you can also use jOOQ directly to execute your jOOQ-generated SQL statements. This will add a lot of convenience on top of the previously discussed API for typesafe SQL construction, when you can re-use the information from generated classes to fetch records and custom data types. An example is given here:

    - + > result = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) @@ -671,10 +671,10 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { // Skip previously distinguished authors if ((int) author.getDistinguished() == 1) continue; - + // Check if the author has written more than 5 books if (author.fetchChildren(Keys.FK_BOOK_AUTHOR).size() > 5) { - + // Mark the author as a "distinguished" author author.setDistinguished(1); author.store(); @@ -691,7 +691,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {
    - +
    jOOQ for PROs @@ -729,7 +729,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { This manual section is intended for new users, to help them get a running application with jOOQ, quickly.

    - +
    Step 1: Preparation @@ -738,13 +738,13 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { If you haven't already downloaded it, download jOOQ:
    http://www.jooq.org/download

    - +

    Alternatively, you can create a Maven dependency to download jOOQ artefacts:

    - +

    Open Source Edition

    - + org.jooq jooq @@ -760,9 +760,9 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { jooq-codegen {jooq-version} ]]> - +

    Commercial Editions (Java 8+)

    - + org.jooq.pro @@ -779,9 +779,9 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { jooq-codegen {jooq-version} ]]> - +

    Commercial Editions (Java 6+)

    - + org.jooq.pro-java-6 @@ -798,22 +798,22 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { jooq-codegen {jooq-version} ]]> - +

    Commercial Editions (Free Trial)

    - + - org.jooq + org.jooq.trial jooq {jooq-version} - org.jooq + org.jooq.trial jooq-meta {jooq-version} - org.jooq + org.jooq.trial jooq-codegen {jooq-version} ]]> @@ -821,7 +821,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    Note that only the jOOQ Open Source Edition is available from Maven Central. If you're using the jOOQ Professional Edition or the jOOQ Enterprise Edition, you will have to manually install jOOQ in your local Nexus, or in your local Maven cache. For more information, please refer to the licensing pages.

    - +

    Please refer to the manual's section about to learn how to use jOOQ's code generator with Maven.

    @@ -836,14 +836,14 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    - +
    Step 2: Your database

    We're going to create a database called "library" and a corresponding "author" table. Connect to MySQL via your command line client and type the following:

    - + CREATE DATABASE `library`; USE `library`; @@ -857,7 +857,7 @@ CREATE TABLE `author` (
    - +
    Step 3: Code generation @@ -869,7 +869,7 @@ CREATE TABLE `author` (

    The easiest way to generate a schema is to copy the jOOQ jar files (there should be 3) and the MySQL Connector jar file to a temporary directory. Then, create a library.xml that looks like this:

    - + @@ -926,7 +926,7 @@ CREATE TABLE `author` (

    generator.target.directory - the directory to output to.

    - +

    Once you have the JAR files and library.xml in your temp directory, type this on a Windows machine:

    @@ -946,7 +946,7 @@ CREATE TABLE `author` (

    Note: jOOQ will try loading the library.xml from your classpath. This is also why there is a trailing period (.) on the classpath. If the file cannot be found on the classpath, jOOQ will look on the file system from the current working directory.

    - +

    Replace the filenames with your actual filenames. In this example, jOOQ {jooq-version} is being used. If everything has worked, you should see this in your console output:

    @@ -1008,17 +1008,17 @@ INFO: Packages fetched : 0 (0 included, 0 excluded) Nov 1, 2011 7:25:08 PM org.jooq.impl.JooqLogger info INFO: GENERATION FINISHED! : Total: 791.688ms, +9.143ms - +
    - +
    Step 4: Connect to your database

    Let's just write a vanilla main class in the project containing the generated classes:

    - +
    - +
    Step 5: Querying

    Let's add a simple query constructed with jOOQ's query DSL:

    - + result = create.select().from(AUTHOR).fetch();]]> @@ -1068,7 +1068,7 @@ Result result = create.select().from(AUTHOR).fetch();]]>

    - +
    Step 6: Iterating @@ -1087,7 +1087,7 @@ Result result = create.select().from(AUTHOR).fetch();]]>

    The full program should now look like this:

    - +
    - +
    Step 7: Explore! @@ -1183,7 +1183,7 @@ public class Main {
  • Another example using Spring and Guice for transaction management can be downloaded from GitHub.
  • Another, excellent tutorial by Petri Kainulainen can be found here.
  • - +

    Add the required Maven dependencies

    For this example, we'll create the following Maven dependencies @@ -1199,11 +1199,11 @@ public class Main { org.jooq jooq @@ -1269,7 +1269,7 @@ public class Main {

    The above dependencies are configured together using a Spring Beans configuration:

    - + - + - + @@ -1327,7 +1327,7 @@ public class Main { - + ]]> @@ -1378,7 +1378,7 @@ public class QueryTest {

    The following example shows how you can use Spring's TransactionManager to explicitly handle transactions:

    - +
    - +
    Using jOOQ with Flyway

    Flyway - Database Migrations Made EasyWhen performing database migrations, we at Data Geekery recommend using jOOQ with Flyway - Database Migrations Made Easy. In this chapter, we're going to look into a simple way to get started with the two frameworks.

    - +

    Philosophy

    - +

    There are a variety of ways how jOOQ and Flyway could interact with each other in various development setups. In this tutorial we're going to show just one variant of such framework team play - a variant that we find particularly compelling for most use cases.

    - +

    The general philosophy behind the following approach can be summarised as this:

    - +
    • 1. Database increment
    • 2. Database migration
    • 3. Code re-generation
    • 4. Development
    - +

    The four steps above can be repeated time and again, every time you need to modify something in your database. More concretely, let's consider:

    - +
    • 1. Database increment - You need a new column in your database, so you write the necessary DDL in a Flyway script
    • 2. Database migration - This Flyway script is now part of your deliverable, which you can share with all developers who can migrate their databases with it, the next time they check out your change
    • @@ -1524,23 +1524,23 @@ public class TransactionTest { ]]>

      0. Maven Project Configuration - Dependencies

      - +

      While jOOQ and Flyway could be used in standalone migration scripts, in this tutorial, we'll be using Maven for the standard project setup. You will also find the source code of this tutorial on GitHub at https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-flyway-example, and the full pom.xml file here.

      - +

      These are the dependencies that we're using in our Maven configuration:

      - + org.jooq jooq @@ -1618,11 +1618,11 @@ public class TransactionTest { org.jooq jooq-codegen-maven @@ -1879,14 +1879,14 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre;

    - +
    Using jOOQ with JAX-RS

    In some use-cases, having a lean, single-tier server-side architecture is desirable. Typically, such architectures expose a RESTful API implementing client code and the UI using something like AngularJS.

    - +

    In Java, the standard API for RESTful applications is JAX-RS, which is part of JEE 7, along with a standard JSON implementation. But you can use JAX-RS also outside of a JEE container. The following example shows how to set up a simple license server using these technologies:

    @@ -1899,9 +1899,9 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre;

    For the example, we'll use a PostgreSQL database.

    - +

    Creating the license server database

    - +

    We'll keep the example simple and use a LICENSE table to store all license keys and associated information, whereas a LOG_VERIFY table is used to log access to the license server. Here's the DDL:

    @@ -1913,7 +1913,7 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre; LICENSEE TEXT NOT NULL, -- The e-mail address of the licensee LICENSE TEXT NOT NULL, -- The license key VERSION VARCHAR(50) NOT NULL DEFAULT '.*', -- The licensed version(s), a regular expression - + CONSTRAINT PK_LICENSE PRIMARY KEY (ID), CONSTRAINT UK_LICENSE UNIQUE (LICENSE) ); @@ -1926,7 +1926,7 @@ CREATE TABLE LICENSE_SERVER.LOG_VERIFY ( REQUEST_IP VARCHAR(50) NOT NULL, -- The request IP verifying the license VERSION VARCHAR(50) NOT NULL, -- The version that is being verified MATCH BOOLEAN NOT NULL, -- Whether the verification was successful - + CONSTRAINT PK_LOG_VERIFY PRIMARY KEY (ID) );]]> @@ -1948,13 +1948,13 @@ $$ LANGUAGE PLPGSQL;

    The actual algorithm might be using a secret salt to hash the function arguments. For the sake of a tutorial, a constant string will suffice.

    - +

    Setting up the project

    - +

    We're going to be setting up the

    - + 9966 - + org.jooq jooq-codegen-maven @@ -2027,14 +2027,14 @@ $$ LANGUAGE PLPGSQL; servlet-api 2.5 - + org.jooq jooq @@ -2056,13 +2056,13 @@ $$ LANGUAGE PLPGSQL;

    With the above setup, we're now pretty ready to start developing our license service as a JAX-RS service.

    - +

    The license service class

    - +

    Once we've run the , we can write the following service class:

    - + /license/verify checks if a given licensee has access to version using a license. * @@ -2122,7 +2122,7 @@ public class LicenseService { @Override public String run(DSLContext ctx) { String v = (version == null || version.equals("")) ? "" : version; - + // Use the jOOQ query DSL API to generate a log entry return ctx.insertInto(LOG_VERIFY) @@ -2143,10 +2143,10 @@ public class LicenseService { } }); } - + // [...] }]]> - +

    The INSERT INTO LOG_VERIFY query is actually rather interesting. In plain SQL, it would look like this:

    @@ -2175,7 +2175,7 @@ RETURNING MATCH;]]> .set(new DefaultConnectionProvider(c)) .set(SQLDialect.POSTGRES) .set(new Settings().withExecuteLogging(false))); - + return runnable.run(ctx); } catch (Exception e) { @@ -2184,13 +2184,13 @@ RETURNING MATCH;]]> return "Service Unavailable - Please contact support@datageekery.com for help"; } } - + private interface CtxRunnable { String run(DSLContext ctx); }]]>

    Configuring Spring and Jetty

    - +

    All we need now is to configure Spring...

    @@ -2248,7 +2248,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/sch

    Using the license server

    - +

    You can now use the license server at the following URLs

    @@ -2265,7 +2265,7 @@ http://localhost:8088/jooq-jax-rs-example/license/verify?mail=test@example.com&l

    Let's verify what happened, in the database:

    - + - +

    Downloading the complete example

    - +

    The complete example can be downloaded for free and under the terms of the Apache Software License 2.0 from here:
    https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-jax-rs-example @@ -2295,21 +2295,21 @@ select * from license_server.log_verify

    - +
    jOOQ and Java 8

    Java 8 has introduced a great set of enhancements, among which lambda expressions and the new Streams API. These new constructs align very well with jOOQ's fluent API as can be seen in the following examples:

    - +

    jOOQ and lambda expressions

    jOOQ's API is fully Java-8-ready, which basically means that it is a SAM (Single Abstract Method) type, which can be instanciated using a lambda expression. Consider this example:

    - + - +

    The above example shows how jOOQ's method can receive a lambda expression that implements to map from jOOQ to your custom types.

    - +

    jOOQ and the Streams API

    @@ -2370,7 +2370,7 @@ select * from license_server.log_verify // Just emit a CREATE TABLE statement System.out.println( "CREATE TABLE " + table + " ("); - + // Map each "Column" type into a String // containing the column specification, // and join them using comma and @@ -2381,15 +2381,15 @@ select * from license_server.log_verify " " + col.type) .collect(Collectors.joining(",\n")) ); - + System.out.println(");"); } );]]> - +

    The above example is explained more in depth in this blog post: http://blog.jooq.org/2014/04/11/java-8-friday-no-more-need-for-orms/. For more information about Java 8, consider these resources:

    - +
    - +
    jOOQ and Nashorn

    With Java 8 and the new built-in JavaScript engine Nashorn, a whole new ecosystem of software can finally make easy use of jOOQ in server-side JavaScript. A very simple example can be seen here:

    - +

    - More details about how to use jOOQ, JDBC, and SQL with Nashorn can be seen here. + More details about how to use jOOQ, JDBC, and SQL with Nashorn can be seen here.

    - +
    jOOQ and Scala @@ -2622,7 +2622,7 @@ print(
  • Type inference using "var" and "val" keywords
  • Lambda expressions and for-comprehension syntax for record iteration and data type conversion
  • - +

    But jOOQ also leverages other useful Scala features, such as

    @@ -2630,15 +2630,15 @@ print(
  • implicit defs for operator overloading
  • Scala Macros (soon to come)
  • - +

    All of the above heavily improve jOOQ's querying DSL API experience for Scala developers.

    - +

    A short example jOOQ application in Scala might look like this:

    - +
    - - + +
    jOOQ and Groovy @@ -2701,7 +2701,7 @@ object Test { //

    A short example jOOQ application in Groovy might look like this:

    - +
    - - + +
    jOOQ and Kotlin @@ -2752,7 +2752,7 @@ DSL.using(sql.connection)

    A short example jOOQ application in Kotlin might look like this:

    - + ) { properties.getProperty("db.url"), properties.getProperty("db.username"), properties.getProperty("db.password") - + // The below "use" method is an adapted version of the one in kotlin.io // See also: https://github.com/JetBrains/kotlin/pull/807 ).use { @@ -2793,11 +2793,11 @@ fun main(args: Array) {

    Note that Kotlin supports some means of operator overloading. For instance, a + b in Kotlin maps to a formal a.plus(b) method invocation, and jOOQ provides the required synonyms in its API to help you write such expressions.

    - +

    One particularly nice language feature is the fact that [square brackets] allow for accessing any object's contents via get() and set() methods. Instead of using the above value1(), value2(), and value3() methods, we could also iterate as such:

    - + ) { println("${it[BOOK.TITLE]} by ${it[AUTHOR.FIRST_NAME]} ${it[AUTHOR.LAST_NAME]}") // Notice: ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ }]]> - +

    A caveat of Kotlin operator overloading is the fact that operators such as == or >= map to a.equals(b), a.compareTo(b) == 0, a.compareTo(b) >= 0 respectively. This behaviour does not make sense in a fluent API such as jOOQ.

    - +
    jOOQ and NoSQL @@ -2830,7 +2830,7 @@ fun main(args: Array) {

    - +
    Dependencies @@ -2848,7 +2848,7 @@ fun main(args: Array) {
    - +
    Build your own @@ -2877,7 +2877,7 @@ fun main(args: Array) {
    - +
    jOOQ and backwards-compatibility @@ -2889,7 +2889,7 @@ fun main(args: Array) {
  • If a minor release includes backwards-compatible, API-relevant new features, [Y] is incremented by one and [Z] is reset to zero.
  • If a major release includes backwards-incompatible, API-relevant new features, [X] is incremented by one and [Y], [Z] are reset to zero.
  • - +

    jOOQ's understanding of backwards-compatibility

    Backwards-compatibility is important to jOOQ. You've chosen jOOQ as a strategic SQL engine and you don't want your SQL to break. That is why there is at most one major release per year, which changes only those parts of jOOQ's API and functionality, which were agreed upon on the user group. During the year, only minor releases are shipped, adding new features in a backwards-compatible way @@ -2902,15 +2902,15 @@ fun main(args: Array) {

  • Overloading methods for convenience
  • Changing the type hierarchy of interfaces
  • - +

    It becomes obvious that it would be impossible to add new language elements (e.g. new , new ) to the API without breaking any client code that actually implements those interfaces. Hence, the following rule should be observed:

    - +

    jOOQ's DSL interfaces should not be implemented by client code! Extend only those extension points that are explicitly documented as "extendable" (e.g. )

    - +

    jOOQ-codegen and jOOQ-meta

    While a reasonable amount of care is spent to maintain these two modules under the rules of semantic versioning, it may well be that minor releases introduce backwards-incompatible changes. This will be announced in the respective release notes and should be the exception. @@ -2938,7 +2938,7 @@ fun main(args: Array) { - +

    The query DSL type @@ -2969,7 +2969,7 @@ fun main(args: Array) { // ... which is in fact the same as: DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    DSL subclasses @@ -2988,7 +2988,7 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME));
    - + @@ -2997,14 +2997,14 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    The DSLContext class

    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.

    - +

    Fluent creation of a DSLContext object

    The DSLContext object can be created fluently from the : @@ -3019,7 +3019,7 @@ DSLContext create = DSL.using(connection, dialect);]]>

    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

    A Configuration can be supplied with these objects: @@ -3038,7 +3038,7 @@ DSLContext create = DSL.using(connection, dialect);]]> - +

    Wrapping a Configuration object, a DSLContext can construct , for later . An example is given here:

    @@ -3080,7 +3080,7 @@ DSL.using(connection, dialect) CONNECT BY clause to the query */ -@Support({ SQLDialect.CUBRID, SQLDialect.}) +@Support({ SQLDialect.CUBRID, SQLDialect.ORACLE }) SelectConnectByConditionStep connectBy(Condition condition);]]>

    @@ -3102,7 +3102,7 @@ SelectSelectStep select(Field... fields);]]>

    Nevertheless, the IS DISTINCT FROM predicate is supported by jOOQ in all dialects, as its semantics can be expressed with an equivalent . For more details, see the manual's section about the .

    - +

    jOOQ and the Oracle SQL dialect

    Oracle SQL is much more expressive than many other SQL dialects. It features many unique keywords, clauses and functions that are out of scope for the SQL standard. Some examples for this are @@ -3126,13 +3126,13 @@ SelectSelectStep select(Field... fields);]]>

    In jOOQ 3.1, the notion of a SQLDialect.family() was introduced, in order to group several similar into a common family. An example for this is SQL Server, which is supported by jOOQ in various versions:

    - +
    • : The "version-less" SQL Server version. This always maps to the latest supported version of SQL Server
    • : The SQL Server version 2012
    • : The SQL Server version 2008
    - +

    In the above list, SQLSERVER is both a dialect and a family of three dialects. This distinction is used internally by jOOQ to distinguish whether to use the clause (SQL Server 2012), or whether to emulate it using ROW_NUMBER() OVER() (SQL Server 2008).

    @@ -3149,7 +3149,7 @@ SelectSelectStep select(Field... fields);]]>

    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.

    - +

    Interact with JDBC DataSources

    If you're in a J2EE or Spring context, however, you may wish to use a instead. Connections obtained from such a DataSource will be closed after query execution by jOOQ. The semantics of such a close operation should be the returning of the connection into a connection pool, not the actual closing of the underlying connection. Typically, this makes sense in an environment using distributed JTA transactions. An example of using DataSources with jOOQ can be seen in the tutorial section about . @@ -3157,17 +3157,17 @@ SelectSelectStep select(Field... fields);]]>

    Note, in this case, jOOQ will internally use a , which you can reference directly if you prefer that.

    - +

    Inject custom behaviour

    If your specific environment works differently from any of the above approaches, you can inject your own custom implementation of a ConnectionProvider into jOOQ. This is the API contract you have to fulfil:

    - + @@ -3177,19 +3177,19 @@ 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...

    - +
    - +

    Here is an example of how to use the custom data API. Let's assume that you have written an , that prevents INSERT statements, when a given flag is set to true:

    @@ -3199,10 +3199,10 @@ public class NoInsertListener extends DefaultExecuteListener { @Override public void start(ExecuteContext ctx) { - + // This listener is active only, when your custom flag is set to true 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) { throw new DataAccessException("No INSERT statements allowed"); @@ -3213,11 +3213,11 @@ public class NoInsertListener extends DefaultExecuteListener {

    See the manual's section about to learn more about how to implement an ExecuteListener.

    - +

    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:

    - + ExecuteListeners are a useful tool to...

    - +
    • implement custom logging
    • apply triggers written in Java
    • collect query execution statistics
    - +

    ExecuteListeners are hooked into your by returning them from an :

    @@ -3275,7 +3275,7 @@ configuration.set( new DefaultExecuteListenerProvider(new PerformanceLoggingListener()), new DefaultExecuteListenerProvider(new NoInsertListener()) );]]>
    - +

    See the manual's section about to see examples of such listener implementations.

    @@ -3319,22 +3319,22 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - +

    All Settings

    - +

    This section of the manual explains all the available Settings flags as available from the XSD specification.

    - + false - + ... @@ -3345,17 +3345,17 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - UPPER_CASED : UPPER - lower_cased : LOWER - CasedAsReportedByTheDatabase : AS_IS - + Defaults to "QUOTED" --> LOWER UPPER - + false @@ -3363,54 +3363,54 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - question marks : INDEXED - named parameters : NAMED - inlined values : INLINED - + Defaults to "INDEXED". - + This value is overridden by statementType == STATIC_STATEMENT, in case of which, this defaults to INLINED --> INDEXED - + PREPARED_STATEMENT - + true false true false ]]> - +

    More details

    - +

    Please refer to the jOOQ runtime configuration XSD for more details:
    http://www.jooq.org/xsd/jooq-runtime-{runtime-xsd-version}.xsd

    - +
    Runtime schema and table mapping @@ -3418,7 +3418,7 @@ DSLContext create = DSL.using(connection, dialect, settings);]]>

    You may wish to design your database in a way that you have several instances of your schema. This is useful when you want to cleanly separate data belonging to several customers / organisation units / branches / users and put each of those entities' data in a separate database or schema.

    - +

    In our AUTHOR example this would mean that you provide a book reference database to several companies, such as My Book World and Books R Us. In that case, you'll probably have a schema setup like this:

    @@ -3448,7 +3448,7 @@ create.selectFrom(AUTHOR).fetch();

    The query executed with a Configuration equipped with the above mapping will in fact produce this SQL statement:

    - + SELECT * FROM MY_BOOK_WORLD.AUTHOR

    Even if AUTHOR was generated from DEV. @@ -3523,13 +3523,13 @@ create.selectFrom(AUTHOR).fetch();

    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

    Table mapping and schema mapping can be applied independently, by specifying several MappedSchema entries in the above configuration. jOOQ will process them in order of appearance and map at first match. Note that you can always omit a MappedSchema's output value, in case of which, only the table mapping is applied. If you omit a MappedSchema's input value, the table mapping is applied to all schemata!

    - +

    Using regular expressions

    All of the above examples were using 1:1 constant name mappings where the input and output schema or table names are fixed by the configuration. With jOOQ 3.8, regular expression can be used as well for mapping, for example: @@ -3582,7 +3582,7 @@ create.selectFrom(AUTHOR).fetch();

    Here is an example to illustrate what that means:

    - + 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) @@ -3654,7 +3654,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); @@ -3681,7 +3681,7 @@ query.addJoin(BOOK, BOOK.AUTHOR_ID.equal(AUTHOR.ID));]]>

    Note, that for historic reasons, the DSL API mixes mutable and immutable behaviour with respect to the internal representation of the being constructed. While creating , (such as functions) assumes immutable behaviour, creating does not. In other words, the following can be said:

    - + select2 = create.selectOne().fetch();]]>

    jOOQ does not explicitly support the asterisk operator in projections. However, you can omit the projection as in these examples:

    - +

    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:

    - + select(Collection> fields); public static SelectSelectStep select(Field... fields); @@ -3963,14 +3963,14 @@ public static SelectSelectStep> select(Field SelectSelectStep> select(Field field1, Field field2); public static SelectSelectStep> select(Field field1, Field field2, Field field3); // [...]]]> - +

    Since the generic R type is bound to some , the associated T type information can be used in various other contexts, e.g. the . Such a SELECT statement can be assigned typesafely:

    > s1 = create.select(BOOK.ID, BOOK.TITLE); Select> s2 = create.select(BOOK.ID, trim(BOOK.TITLE));]]> - +

    For more information about typesafe record types with degree up to {max-row-degree}, see the manual's section about .

    @@ -3996,7 +3996,7 @@ create.selectOne().from(BOOK.as("b"), AUTHOR.as("a")).fetch();]]>

    Read more about aliasing in the manual's section about .

    - +

    More advanced table expressions

    Apart from simple tables, you can pass any arbitrary to the jOOQ FROM clause. This may include in Oracle: @@ -4054,11 +4054,11 @@ DSL.using(SQLDialect.POSTGRES).selectOne().fetch();]]>

  • NATURAL LEFT [ OUTER ] JOIN
  • NATURAL RIGHT [ OUTER ] JOIN
  • - +

    Besides, jOOQ also supports

    - +
    • CROSS APPLY (T-SQL and Oracle 12c specific)
    • OUTER APPLY (T-SQL and Oracle 12c specific)
    • @@ -4188,7 +4188,7 @@ ON BOOK.AUTHOR_ID = AUTHOR.ID

      SEMI JOIN and ANTI JOIN

      - Very few databases (e.g. Apache Impala) ship with a built-in syntax for { LEFT | RIGHT } SEMI JOIN and { LEFT | RIGHT } ANTI JOIN, which are much more concise versions of the SQL standard IN / EXISTS and NOT IN / NOT EXISTS predicates. The idea is that the JOIN syntax is expressed where it belongs, in the FROM clause, not in the WHERE clause. + Very few databases (e.g. Apache Impala) ship with a built-in syntax for { LEFT | RIGHT } SEMI JOIN and { LEFT | RIGHT } ANTI JOIN, which are much more concise versions of the SQL standard IN / EXISTS and NOT IN / NOT EXISTS predicates. The idea is that the JOIN syntax is expressed where it belongs, in the FROM clause, not in the WHERE clause.

      Since jOOQ 3.7, these types of JOIN are also supported and they're emulated using EXISTS and NOT EXISTS respectively. @@ -4196,7 +4196,7 @@ ON BOOK.AUTHOR_ID = AUTHOR.ID

      Here's how SEMI JOIN translates to EXISTS.

      - + - +

      T-SQL's CROSS APPLY and OUTER APPLY

      T-SQL has long known what the SQL standard calls lateral derived tables, lateral joins using the APPLY keyword. To every row resulting from the table expression on the left, we apply the table expression on the right. This is extremely useful for table-valued functions, which are also supported by jOOQ. Some examples:

      - + - +

      The above example shows standard usage of the LATERAL keyword to connect a derived table to the previous table in the . A similar statement can be written in T-SQL:

      - + - +

      While not all forms of LATERAL JOIN have an equivalent APPLY syntax, the inverse is true, and jOOQ can thus emulate OUTER APPLY and CROSS APPLY using LATERAL JOIN.

      - +

      LATERAL JOIN or CROSS APPLY are particularly useful together with , which are also supported by jOOQ.

      @@ -4384,12 +4384,12 @@ ORDER BY 1

      Note that this syntax is also supported in the CUBRID database and might be emulated in other dialects supporting common table expressions in the future.

      - +

      ORDER SIBLINGS

      The Oracle database allows for specifying a SIBLINGS keyword in the . Instead of ordering the overall result, this will only order siblings among each other, keeping the hierarchy intact. An example is given here:

      - + - +
    @@ -4433,7 +4433,7 @@ GROUP BY AUTHOR_ID

    Note, as defined in the SQL standard, when grouping, you may no longer project any columns that are not a formal part of the GROUP BY clause, or .

    - +

    MySQL's deviation from the SQL standard

    MySQL has a peculiar way of not adhering to this standard behaviour. This is documented in the MySQL manual. In short, with MySQL, you can also project any other field that is not part of the GROUP BY clause. The projected values will just be arbitrary values from within the group. You cannot rely on any ordering. For example: @@ -4468,7 +4468,7 @@ GROUP BY () .groupBy() .fetch();]]> - +

    ROLLUP(), CUBE() and GROUPING SETS()

    Some databases support the SQL standard grouping functions and some extensions thereof. See the manual's section about for more details. @@ -4489,7 +4489,7 @@ FROM BOOK GROUP BY AUTHOR_ID HAVING COUNT(*) >= 2 ]]>  -= 4

    - +
    The WINDOW clause

    The SQL:2003 standard as well as PostgreSQL and Sybase SQL Anywhere support a WINDOW clause that allows for specifying WINDOW frames for reuse in and .

    - +   - +

    Note that in order to create such a window definition, we need to first create a using .

    Even if only PostgreSQL and Sybase SQL Anywhere natively support this great feature, jOOQ can emulate it by expanding any and types that you pass to the window() method - if the database supports window functions at all.

    - +

    Some more information about and the WINDOW clause can be found on our blog: http://blog.jooq.org/2013/11/03/probably-the-coolest-sql-feature-window-functions/

    @@ -4687,8 +4687,8 @@ ORDER BY CASE TITLE

    The SQL standard defines that a "query expression" can be ordered, and that query expressions can contain , whose subqueries cannot be ordered. While this is defined as such in the SQL standard, many databases allowing for the in one way or another, do not adhere to this part of the SQL standard. Hence, jOOQ allows for ordering all SELECT statements, regardless whether they are constructed as a part of a UNION or not. Corner-cases are handled internally by jOOQ, by introducing synthetic subselects to adhere to the correct syntax, where this is needed.

    - - + +

    Oracle's ORDER SIBLINGS BY clause

    jOOQ also supports Oracle's SIBLINGS keyword to be used with ORDER BY clauses for @@ -4740,7 +4740,7 @@ SELECT TOP 1 * FROM BOOK

    Things get a little more tricky in those databases that have no native idiom for OFFSET pagination (actual queries may vary):

    - + 1]]>

    As you can see, jOOQ will take care of the incredibly painful ROW_NUMBER() OVER() (or ROWNUM for Oracle) filtering in subselects for you, you'll just have to write limit(1).offset(2) in any dialect.

    - +

    Side-note: If you're interested in understanding why we chose ROWNUM for Oracle, please refer to this very interesting benchmark, comparing the different approaches of doing pagination in Oracle: http://www.inf.unideb.hu/~gabora/pagination/results.html.

    @@ -4787,7 +4787,7 @@ WHERE RN > 1]]>

    - +
    The SEEK clause @@ -4797,7 +4797,7 @@ WHERE RN > 1]]>

    A much faster and more stable way to perform paging is the so-called keyset paging method also called seek method. jOOQ supports a synthetic seek() clause, that can be used to perform keyset paging. Imagine we have these data:

    - + 1]]>

    Now, if we want to display page 6 to the user, instead of going to page 6 by using a record OFFSET, we could just fetch the record strictly after the last record on page 5, which yields the values (533, 2). This is how you would do it with SQL or with jOOQ:

    - + As you can see, the jOOQ SEEK clause is a synthetic clause that does not really exist in SQL. However, the jOOQ syntax is far more intuitive for a variety of reasons:

    - +
    • It replaces OFFSET where you would expect
    • It doesn't force you to mix regular predicates with "seek" predicates
    • It is typesafe
    • It emulates for you, in those databases that do not support them
    - +

    This query now yields:

    - + Note that you cannot combine the SEEK clause with the OFFSET clause.

    - +

    More information about this great feature can be found in the jOOQ blog:

    @@ -4868,11 +4868,11 @@ LIMIT 5
  • http://blog.jooq.org/2013/10/26/faster-sql-paging-with-jooq-using-the-seek-method/
  • http://blog.jooq.org/2013/11/18/faster-sql-pagination-with-keysets-continued/
  • - +

    Further information about offset pagination vs. keyset pagination performance can be found on our partner page:

    - +
    No more offset @@ -4984,7 +4984,7 @@ SELECT * FROM author ORDER BY id DESC;]]>

    SQL allows to perform set operations as understood in standard set theory on result sets. These operations include unions, intersections, subtractions. For two subselects to be combinable by such a set operator, each subselect must return a of the same degree and type.

    - +

    UNION and UNION ALL

    These operators combine two results into one. While UNION removes all duplicate records resulting from this combination, UNION ALL leaves subselect results as they are. Typically, you should prefer UNION ALL over UNION, if you don't really need to remove duplicates. The following example shows how to use such a UNION operation in jOOQ. @@ -4999,16 +4999,16 @@ SELECT * FROM BOOK WHERE ID = 5 .unionAll( create.selectFrom(BOOK).where(BOOK.ID.equal(5))) .fetch();]]> - +

    INTERSECT [ ALL ] and EXCEPT [ ALL ]

    INTERSECT is the operation that produces only those values that are returned by both subselects. EXCEPT (or MINUS in Oracle) is the operation that returns only those values that are returned exclusively in the first subselect. Both operators will remove duplicates from their results.

    - +

    Just like with UNION ALL, these operators have an optional ALL keyword that allows for keeping duplicate rows after intersection or subtraction, which is supported in jOOQ 3.7+.

    - +

    jOOQ's set operators and how they're different from standard SQL

    As previously mentioned in the manual's section about the , jOOQ has slightly changed the semantics of these set operators. While in SQL, a subselect may not contain any or (unless you wrap the subselect into a ), jOOQ allows you to do so. In order to select both the youngest and the oldest author from the database, you can issue the following statement with jOOQ (rendered to the MySQL dialect): @@ -5029,7 +5029,7 @@ ORDER BY 1 .orderBy(AUTHOR.DATE_OF_BIRTH.desc()).limit(1)) .orderBy(1) .fetch();]]> - +

    In case your database doesn't support ordered UNION subselects, the subselects are nested in derived tables:

    @@ -5047,12 +5047,12 @@ SELECT * FROM ( ORDER BY 1]]> - +

    Projection typesafety for degrees between 1 and {max-row-degree}

    Two subselects that are combined by a set operator are required to be of the same degree and, in most databases, also of the same type. jOOQ 3.0's introduction of helps compile-checking these constraints:

    - + > s1 = select(BOOK.ID, BOOK.TITLE).from(BOOK); Select> s2 = selectOne(); @@ -5088,7 +5088,7 @@ s1.union(s4); // OK. The two Record[N] types match]]>

    Note that you can pass any string in the .hint() clause. If you use that clause, the passed string will always be put in between the SELECT [DISTINCT] keywords and the actual projection list. This can be useful in other databases too, such as MySQL, for instance:

    - +
    - +
    Lexical and logical SELECT clause order

    SQL has a lexical and a logical order of SELECT clauses. The lexical order of SELECT clauses is inspired by the English language. As SQL statements are commands for the database, it is natural to express a statement in an imperative tense, such as "SELECT this and that!".

    - +

    Logical SELECT clause order

    The logical order of SELECT clauses, however, does not correspond to the syntax. In fact, the logical order is this:

    - +
    • : First, all data sources are defined and joined
    • : Then, data is filtered as early as possible
    • @@ -5126,11 +5126,11 @@ FROM table1
    • : Then, a paging view is created for the ordered tuples
    • : Finally, pessimistic locking is applied
    - +

    The SQL Server documentation also explains this, with slightly different clauses:

    - +
    • FROM
    • ON
    • @@ -5144,16 +5144,16 @@ FROM table1
    • ORDER BY
    • TOP
    - +

    As can be seen, databases have to logically reorder a SQL statement in order to determine the best execution plan.

    - +

    Alternative syntaxes: LINQ, SLICK

    Some "higher-level" abstractions, such as C#'s LINQ or Scala's SLICK try to inverse the lexical order of SELECT clauses to what appears to be closer to the logical order. The obvious advantage of moving the SELECT clause to the end is the fact that the projection type, which is the record type returned by the SELECT statement can be re-used more easily in the target environment of the internal domain specific language.

    - +

    A LINQ example:

    @@ -5166,11 +5166,11 @@ Where p.UnitsInStock <= p.ReorderLevel AndAlso Not p.Discontinued // SELECT clause Select p]]> - +

    A SLICK example:

    - + INSERT statement is used to insert new records into a database table. The following sections describe the various operation modes of the jOOQ INSERT statement.

    - +
    INSERT .. VALUES - +

    INSERT .. VALUES with a single row

    Records can either be supplied using a VALUES() constructor, or a SELECT statement. jOOQ supports both types of INSERT statements. An example of an INSERT statement using a VALUES() constructor is given here: @@ -5228,7 +5228,7 @@ VALUES (100, 'Hermann', 'Hesse'); create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME); step.values("A", "B", "C"); // ^^^ Doesn't compile, the expected type is Integer]]> - +

    INSERT .. VALUES with multiple rows

    The SQL standard specifies that multiple rows can be supplied to the VALUES() constructor in an INSERT statement. Here's an example of a multi-record INSERT @@ -5266,14 +5266,14 @@ SELECT 101, 'Alfred', 'Döblin' FROM DUAL;

    - +
    INSERT .. DEFAULT VALUES

    A lesser-known syntactic feature of SQL is the INSERT .. DEFAULT VALUES statement, where a single record is inserted, containing only DEFAULT values for every row. It is written as such:

    - + create.insertInto(AUTHOR) .defaultValues() .execute(); - +

    This can make a lot of sense in situations where you want to "reserve" a row in the database for an subsequent within the same transaction. Or if you just want to send an event containing trigger-generated default values, such as IDs or timestamps.

    @@ -5291,18 +5291,18 @@ DEFAULT VALUES;

    -  create.insertInto( AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, ...) .values( - defaultValue(AUTHOR.ID), - defaultValue(AUTHOR.FIRST_NAME), + defaultValue(AUTHOR.ID), + defaultValue(AUTHOR.FIRST_NAME), defaultValue(AUTHOR.LAST_NAME), ...) .execute(); @@ -5311,7 +5311,7 @@ VALUES (

    - +
    INSERT .. SET @@ -5328,13 +5328,13 @@ VALUES ( .set(AUTHOR.FIRST_NAME, "Alfred") .set(AUTHOR.LAST_NAME, "Döblin") .execute(); - +

    As you can see, this syntax is a bit more verbose, but also more readable, as every field can be matched with its value. Internally, the two syntaxes are strictly equivalent. -

    +

    - +
    INSERT .. SELECT @@ -5342,22 +5342,22 @@ VALUES (

    In some occasions, you may prefer the INSERT SELECT syntax, for instance, when you copy records from one table to another:

    - + create.insertInto(AUTHOR_ARCHIVE) .select(selectFrom(AUTHOR).where(AUTHOR.DECEASED.isTrue())) .execute();
    - +
    INSERT .. ON DUPLICATE KEY

    The synthetic ON DUPLICATE KEY UPDATE clause

    - +

    The MySQL database supports a very convenient way to INSERT or UPDATE a record. This is a non-standard extension to the SQL syntax, which is supported by jOOQ and emulated in other RDBMS, where this is possible (i.e. if they support the SQL standard ). Here is an example how to use the ON DUPLICATE KEY UPDATE clause:

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, update the author's name create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -5367,11 +5367,11 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .execute();

    The synthetic ON DUPLICATE KEY IGNORE clause

    - +

    The MySQL database also supports an INSERT IGNORE INTO clause. This is supported by jOOQ using the more convenient SQL syntax variant of ON DUPLICATE KEY IGNORE:

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, ignore the INSERT statement create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -5381,11 +5381,11 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME)

    If the underlying database doesn't have any way to "ignore" failing INSERT statements, (e.g. MySQL via INSERT IGNORE), jOOQ can emulate the statement using a , or using INSERT .. SELECT WHERE NOT EXISTS:

    - +

    Emulating IGNORE with MERGE

    - +

    - The above jOOQ statement can be emulated with the following, equivalent SQL statement: + The above jOOQ statement can be emulated with the following, equivalent SQL statement:

    MERGE INTO AUTHOR @@ -5393,11 +5393,11 @@ USING (SELECT 1 FROM DUAL) ON (AUTHOR.ID = 3) WHEN NOT MATCHED THEN INSERT (ID, LAST_NAME) VALUES (3, 'Koontz') - +

    Emulating IGNORE with INSERT .. SELECT WHERE NOT EXISTS

    - +

    - The above jOOQ statement can be emulated with the following, equivalent SQL statement: + The above jOOQ statement can be emulated with the following, equivalent SQL statement:

    INSERT INTO AUTHOR (ID, LAST_NAME) @@ -5409,11 +5409,11 @@ WHERE NOT EXISTS ( )
    - +
    INSERT .. RETURNING - +

    The Postgres database has native support for an INSERT .. RETURNING clause. This is a very powerful concept that is emulated for all other dialects using JDBC's method. Take this example:

    @@ -5493,7 +5493,7 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    jOOQ supports formal in various contexts, among which the UPDATE statement. Only one row value expression can be updated at a time. Here's an example:

    - + The above row value expressions usages are completely typesafe.

    - +

    UPDATE .. RETURNING

    The Firebird and Postgres databases support a RETURNING clause on their UPDATE statements, similar as the RETURNING clause in . This is useful to fetch trigger-generated values in one go. An example is given here:

    - +

    - The UPDATE .. RETURNING clause is emulated for DB2 using the SQL standard SELECT .. FROM FINAL TABLE(UPDATE ..) construct, and in Oracle, using the PL/SQL UPDATE .. RETURNING statement. + The UPDATE .. RETURNING clause is emulated for DB2 using the SQL standard SELECT .. FROM FINAL TABLE(UPDATE ..) construct, and in Oracle, using the PL/SQL UPDATE .. RETURNING statement.

    @@ -5610,7 +5610,7 @@ WHEN NOT MATCHED THEN INSERT (LAST_NAME) VALUES ('Hitchcock');

    The H2 database ships with a somewhat less powerful but a little more intuitive syntax for its own version of the MERGE statement. An example more or less equivalent to the previous one can be seen here:

    - + -- Check if there is already an author called 'Hitchcock' -- If there is, rename him to John. If there isn't add him. @@ -5630,7 +5630,7 @@ VALUES ('John', 'Hitchcock') This syntax can be fully emulated by jOOQ for all other databases that support the SQL standard MERGE statement. For more information about the H2 MERGE syntax, see the documentation here:
    http://www.h2database.com/html/grammar.html#merge

    - +

    Typesafety of VALUES() for degrees up to {max-row-degree}

    Much like the , the MERGE statement's VALUES() clause provides typesafety for degrees up to {max-row-degree}, in both the standard syntax variant as well as the H2 variant. @@ -5731,7 +5731,7 @@ create.alterView("old_view").renameTo("new_view").execute();]]>

    - +
    The CREATE statement @@ -5798,7 +5798,7 @@ create.createTable("TOP_AUTHORS").as( ))).execute();]]>
    - +
    The DROP statement @@ -5847,24 +5847,24 @@ create.createTable("TOP_AUTHORS").as(

    - - + +
    Generating DDL from objects

    When using jOOQ's , a whole set of meta data is generated with the generated artefacts, such as schemas, tables, columns, data types, constraints, default values, etc.

    - +

    This meta data can be used to generate DDL CREATE statements in any SQL dialect, in order to partially restore the original schema again on a new database instance. This is particularly useful, for instance, when working with an Oracle production database, and an H2 in-memory test database. The following code produces the DDL for a schema:

    - + @@ -5873,7 +5873,7 @@ for (Query query : ddl.queries()) { When executing the above, you should see something like the following:

    - - +

    Do note that these features only restore parts of the original schema. For instance, vendor-specific storage clauses that are not available to jOOQ's generated meta data cannot be reproduced this way.

    @@ -5910,13 +5910,13 @@ alter table "PUBLIC"."T_BOOK"

    Most databases know some sort of namespace to group objects like , , and others into a common catalog or schema. jOOQ uses the types and to model these groupings, following SQL standard naming.

    - +

    The catalog

    - +

    A catalog is a collection of schemas. In many databases, the catalog corresponds to the database, or the database instance. Most often, catalogs are completely independent and their tables cannot be joined or combined in any way in a single query. The exception here is SQL Server, which allows for fully referencing tables from multiple catalogs:

    - + @@ -5928,17 +5928,17 @@ JOIN [Catalog2].[Schema2].[Table2] AS [t2] ON [t1].[ID] = [t2].[ID]]]> jOOQ's generates subpackages for each catalog.

    - +

    The schema

    - +

    A schema is a collection of objects, such as tables. Most databases support some sort of schema (except for some embedded databases like Access, Firebird, SQLite). In most databases, the schema is an independent structural entity. In Oracle, the schema and the user / owner is mostly treated as the same thing. An example of a query that uses fully qualified tables including schema names is:

    - + - +

    By default, the Settings.renderSettings flag is turned on. jOOQ will thus generate fully qualified object names, including the setting name. For more information about this setting, see

    @@ -5960,7 +5960,7 @@ JOIN "Schema2"."Table2" AS "t2" ON "t1"."ID" = "t2"."ID"]]>

    Most of the times, when thinking about a you're probably thinking about an actual table in your database schema. If you're using jOOQ's , you will have all tables from your database schema available to you as type safe Java objects. You can then use these tables in SQL , or in other , just like any other table expression. An example is given here:

    - +
    - +

    The above example shows how AUTHOR and BOOK tables are joined in a . It also shows how you can access by dereferencing the relevant Java attributes of their tables.

    @@ -6013,11 +6013,11 @@ create.select() .and(a.FIRST_NAME.equal("Paulo"))) .orderBy(b.TITLE) .fetch();]]> - +

    As you can see in the above example, calling as() on generated tables returns an object of the same type as the table. This means that the resulting object can be used to dereference fields from the aliased table. This is quite powerful in terms of having your Java compiler check the syntax of your SQL statements. If you remove a column from a table, dereferencing that column from that table alias will cause compilation errors.

    - +

    Dereferencing columns from other table expressions

    Only few table expressions provide the SQL syntax typesafety as shown above, where generated tables are used. Most tables, however, expose their fields through field() methods: @@ -6029,12 +6029,12 @@ Table a = AUTHOR.as("a"); // Get fields from a: Field id = a.field("ID"); Field firstName = a.field("FIRST_NAME");]]> - +

    Derived column lists

    The SQL standard specifies how a table can be renamed / aliased in one go along with its columns. It references the term "derived column list" for the following syntax (as supported by Postgres, for instance):

    - + In jOOQ, you would simply specify a varargs list of column aliases as such:

    - + The that can be used in are the most powerful and best supported means of creating new in SQL. Informally, the following can be said:

    - + A(colA1, ..., colAn) "join" B(colB1, ..., colBm) "produces" C(colA1, ..., colAn, colB1, ..., colBm)

    @@ -6109,7 +6109,7 @@ create.select().from(values(

    jOOQ supports all of these JOIN types (including semi-join and anti-join) directly on any :

    - + table) @@ -6168,7 +6168,7 @@ TableOnStep join(Name)]]>

    Some databases allow for expressing in-memory temporary tables using a VALUES() constructor. This constructor usually works the same way as the VALUES() clause known from the or from the . With jOOQ, you can also use the VALUES() table constructor, to create tables that can be used in a :

    - + Note, that it is usually quite useful to provide column aliases ("derived column lists") along with the table alias for the VALUES() constructor.

    - +

    The above statement is emulated by jOOQ for those databases that do not support the VALUES() constructor, natively (actual emulations may vary):

    - + A can appear almost anywhere a can. Such a "nested SELECT" is often called a "derived table". Apart from many convenience methods accepting objects directly, a SELECT statement can always be transformed into a object using the asTable() method.

    - +

    Example: Scalar subquery

    - + If you are closely coupling your application to an Oracle database, you can take advantage of some Oracle-specific features, such as the PIVOT clause, used for statistical analyses. The formal syntax definition is as follows:

    - + -- SELECT .. FROM table PIVOT (aggregateFunction [, aggregateFunction] FOR column IN (expression [, expression])) -- WHERE .. - +

    The PIVOT clause is available from the type, as pivoting is done directly on a table. Currently, only Oracle's PIVOT clause is supported. Support for SQL Server's slightly different PIVOT clause will be added later. Also, jOOQ may emulate PIVOT for other dialects in the future.

    @@ -6360,7 +6360,7 @@ WHERE NOT EXISTS (

    The SQL standard specifies how SQL databases should implement ARRAY and TABLE types, as well as CURSOR types. Put simply, a CURSOR is a pointer to any materialised . Depending on the cursor's features, this table expression can be scrolled through in both directions, records can be locked, updated, removed, inserted, etc. Often, CURSOR types contain s, whereas ARRAY and TABLE types contain simple scalar values, although that is not a requirement

    - +

    ARRAY types in SQL are similar to Java's array types. They contain a "component type" or "element type" and a "dimension". This sort of ARRAY type is implemented in H2, HSQLDB and Postgres and supported by jOOQ as such. Oracle uses strongly-typed arrays, which means that an ARRAY type (VARRAY or TABLE type) has a name and possibly a maximum capacity associated with it.

    @@ -6383,7 +6383,7 @@ FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(null, null, 'ALLSTATS'));

    - +
    Table-valued functions @@ -6406,11 +6406,11 @@ BEGIN ORDER BY id RETURN END]]> - +

    The jOOQ code generator will now produce a from the above, which can be used as a SQL function:

    - + r1 = create.selectFrom(fBooks(null)).fetch(); @@ -6418,7 +6418,7 @@ Result r1 = create.selectFrom(fBooks(null)).fetch(); create.select(BOOK.ID, F_BOOKS.TITLE) .from(BOOK.crossApply(fBooks(BOOK.ID))) .fetch();]]> - +
    ¨ @@ -6492,12 +6492,12 @@ DSL.using(SQLDialect.SYBASE ).selectOne().getSQL();]]>

    Column expressions can be used in various SQL clauses in order to refer to one or several columns. This chapter explains how to form various types of column expressions with jOOQ. A particular type of column expression is given in the section about , where an expression may have a degree of more than one.

    - +

    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:

    - + field1 = BOOK.TITLE; @@ -6553,7 +6553,7 @@ ORDER BY BOOK.TITLE

    Just like , columns can be renamed using aliases. Here is an example:

    - + SELECT FIRST_NAME || ' ' || LAST_NAME author, COUNT(*) books FROM AUTHOR JOIN BOOK ON AUTHOR.ID = AUTHOR_ID @@ -6562,7 +6562,7 @@ GROUP BY FIRST_NAME, LAST_NAME;

    Here is how it's done with jOOQ:

    - + Record record = create.select( concat(AUTHOR.FIRST_NAME, val(" "), AUTHOR.LAST_NAME).as("author"), count().as("books")) @@ -6570,14 +6570,14 @@ GROUP BY FIRST_NAME, LAST_NAME; .join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID)) .groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .fetchAny(); - +

    When you alias Fields like above, you can access those Fields' values using the alias name:

    - + System.out.println("Author : " + record.getValue("author")); System.out.println("Books : " + record.getValue("books")); - + @@ -6590,7 +6590,7 @@ System.out.println("Books : " + record.getValue("books"));

    Sometimes, this automatic mapping might not be what you needed, or jOOQ cannot know the type of a field. In those cases you would write SQL type CAST like this:

    - + -- Let's say, your Postgres column LAST_NAME was VARCHAR(30) -- Then you could do this: SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL @@ -6598,27 +6598,27 @@ SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL

    in jOOQ, you can write something like that:

    - + create.select(TAuthor.LAST_NAME.cast(PostgresDataType.TEXT)).fetch();

    The same thing can be achieved by casting a Field directly to String.class, as TEXT is the default data type in Postgres to map to Java's String

    - + create.select(TAuthor.LAST_NAME.cast(String.class)).fetch(); - +

    The complete CAST API in consists of these three methods:

    - + { // Cast this field to the type of another field Field cast(Field field); - + // Cast this field to a given DataType Field cast(DataType type); - + // Cast this field to the default DataType for a given Class Field cast(Class type); } @@ -6641,14 +6641,14 @@ public class DSL {

    A slightly different use case than are data type coercions, which are not rendered through to generated SQL. Sometimes, you may want to pretend that a numeric value is really treated as a string value, for instance when binding a numeric :

    - + field1 = val(1).coerce(String.class); Field field2 = val("1").coerce(Integer.class);]]>

    In the above example, field1 will be treated by jOOQ as a Field<String>, binding the numeric literal 1 as a VARCHAR value. The same applies to field2, whose string literal "1" will be bound as an INTEGER value.

    - +

    This technique is better than performing unsafe or rawtype casting in Java, if you cannot access the "right" field type from any given expression.

    @@ -6668,15 +6668,15 @@ Field field2 = val("1").coerce(Integer.class);]]>

    In order to express a SQL query like this one:

    - + SELECT ((1 + 2) * (5 - 3) / 2) % 10 FROM DUAL - +

    You can write something like this in jOOQ:

    - + create.select(val(1).add(2).mul(val(5).sub(3)).div(2).mod(10)).fetch(); - +

    Operator precedence

    jOOQ does not know any operator precedence (see also ). All operations are evaluated from left to right, as with any object-oriented API. The two following expressions are the same: @@ -6704,14 +6704,14 @@ Field field2 = val("1").coerce(Integer.class);]]> - +

    String concatenation

    The SQL standard defines the concatenation operator to be an infix operator, similar to the ones we've seen in the chapter about . This operator looks like this: ||. Some other dialects do not support this operator, but expect a concat() function, instead. jOOQ renders the right operator / function, depending on your :

    - + SELECT 'A' || 'B' || 'C' FROM DUAL -- Or in MySQL: @@ -6739,13 +6739,13 @@ create.select(concat("A", "B", "C")).fetch();
  • NVL: Get the first non-null value among two arguments.
  • NVL2: Get the second argument if the first is null, or the third argument, otherwise.
  • - +

    Please refer to the for more details.

    - +
    Numeric functions @@ -6755,7 +6755,7 @@ create.select(concat("A", "B", "C")).fetch();

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ABS: Get the absolute value of a value.
    • ACOS: Get the arc cosine of a value.
    • @@ -6786,7 +6786,7 @@ create.select(concat("A", "B", "C")).fetch();
    • TANH: Get the hyperbolic tangent of a value.
    • TRUNC: Truncate the decimals off a given value.
    - +

    Please refer to the for more details.

    @@ -6811,13 +6811,13 @@ create.select(concat("A", "B", "C")).fetch();
  • SHL: Shift bits to the left
  • SHR: Shift bits to the right
  • - +

    Some background about bitwise operation emulation

    As stated before, not all databases support all of these bitwise operations. jOOQ emulates them wherever this is possible. More details can be seen in this blog post:
    http://blog.jooq.org/2011/10/30/the-comprehensive-sql-bitwise-operations-compatibility-list/

    - +
    @@ -6830,7 +6830,7 @@ create.select(concat("A", "B", "C")).fetch();

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ASCII: Get the ASCII code of a character.
    • BIT_LENGTH: Get the length of a string in bits.
    • @@ -6851,16 +6851,16 @@ create.select(concat("A", "B", "C")).fetch();
    • TRIM: Trim a string on both sides.
    • UPPER: Get a string in upper case letters.
    - +

    Please refer to the for more details.

    - +

    Regular expressions, REGEXP, REGEXP_LIKE, etc.

    Various databases have some means of searching through columns using regular expressions if the does not provide sufficient pattern matching power. While there are many different functions and operators in the various databases, jOOQ settled for the SQL:2008 standard REGEX_LIKE operator. Being an operator (and not a function), you should use the corresponding method on :

    - +

    @@ -6869,7 +6869,7 @@ create.select(concat("A", "B", "C")).fetch(); - +

    Case sensitivity with strings @@ -6882,20 +6882,20 @@ create.select(concat("A", "B", "C")).fetch();

    For these ad-hoc ordering use-cases, most people resort to using LOWER() or UPPER() as follows:

    - + -- Case-insensitive filtering: -SELECT * FROM BOOK +SELECT * FROM BOOK WHERE upper(TITLE) = 'ANIMAL FARM' -- Case-insensitive ordering: -SELECT * +SELECT * FROM AUTHOR ORDER BY upper(FIRST_NAME), upper(LAST_NAME) // Case-insensitive filtering: create.selectFrom(BOOK) .where(upper(BOOK.TITLE).eq("ANIMAL FARM")).fetch(); - + // Case-insensitive ordering: create.selectFrom(AUTHOR) .orderBy(upper(AUTHOR.FIRST_NAME), upper(AUTHOR.LAST_NAME)) @@ -6912,7 +6912,7 @@ create.selectFrom(AUTHOR)

    This is a list of date and time functions supported by jOOQ's :

    - +
    • CURRENT_DATE: Get current date as a DATE object.
    • CURRENT_TIME: Get current time as a TIME object.
    • @@ -6922,7 +6922,7 @@ create.selectFrom(AUTHOR)
    • TIMESTAMP_ADD: Add a number of days or an interval to a timestamp.
    • TIMESTAMP_DIFF: Get the difference as an INTERVAL DAY TO SECOND between two dates.
    - +

    Intervals in jOOQ

    jOOQ fills a gap opened by JDBC, which neglects an important SQL data type as defined by the SQL standards: INTERVAL types. See the manual's section about for more details. @@ -7074,7 +7074,7 @@ GROUP BY AUTHOR_ID WindowOverStep rank(); WindowOverStep denseRank(); WindowOverStep percentRank(); - + // Windowing functions WindowIgnoreNullsStep firstValue(Field field); WindowIgnoreNullsStep lastValue(Field field); @@ -7092,13 +7092,13 @@ GROUP BY AUTHOR_ID // Statistical functions WindowOverStep cumeDist(); WindowOverStep ntile(int number); - + // Inverse distribution functions OrderedAggregateFunction precentileCont(Number number); OrderedAggregateFunction precentileCont(Field number); OrderedAggregateFunction precentileDisc(Number number); OrderedAggregateFunction precentileDisc(Field number);]]> - +

    SQL distinguishes between various window function types (e.g. "ranking functions"). Depending on the function, SQL expects mandatory PARTITION BY or ORDER BY clauses within the OVER() clause. jOOQ does not enforce those rules for two reasons:

    @@ -7113,14 +7113,14 @@ GROUP BY AUTHOR_ID

    Here are some simple examples of window functions with jOOQ:

    - + -- Sample uses of ROW_NUMBER() ROW_NUMBER() OVER() ROW_NUMBER() OVER(PARTITION BY 1) ROW_NUMBER() OVER(ORDER BY BOOK.ID) ROW_NUMBER() OVER(PARTITION BY BOOK.AUTHOR_ID ORDER BY BOOK.ID) - + -- Sample uses of FIRST_VALUE FIRST_VALUE(BOOK.ID) OVER() FIRST_VALUE(BOOK.ID IGNORE NULLS) OVER() @@ -7131,14 +7131,14 @@ rowNumber().over() rowNumber().over().partitionByOne() rowNumber().over().partitionBy(BOOK.AUTHOR_ID) rowNumber().over().partitionBy(BOOK.AUTHOR_ID).orderBy(BOOK.ID) - + // Sample uses of firstValue() firstValue(BOOK.ID).over() firstValue(BOOK.ID).ignoreNulls().over() firstValue(BOOK.ID).respectNulls().over()
    - +

    An advanced window function example

    Window functions can be used for things like calculating a "running total". The following example fetches transactions and the running total for every transaction going back to the beginning of the transaction table (ordered by booked_at). Window functions are accessible from the previously seen type using the over() method: @@ -7166,7 +7166,7 @@ firstValue(BOOK.ID).respectNulls().over()

    In the previous chapter about , we have seen the concept of "ordered-set aggregate functions", such as Oracle's LISTAGG(). These functions have a window function / analytical function variant, as well. For example:

    - + SELECT LISTAGG(TITLE, ', ') WITHIN GROUP (ORDER BY TITLE) @@ -7251,7 +7251,7 @@ ORDER BY 1 NULLS LAST, 2 NULLS LAST

    In English, the ROLLUP() grouping function provides N+1 groupings, when N is the number of arguments to the ROLLUP() function. Each grouping has an additional group field from the ROLLUP() argument field list. The results of the second query might look something like this:

    - + GROUPING SETS() and other grouping functions:
    http://msdn.microsoft.com/en-us/library/bb510427(v=sql.105)

    - +

    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:

    - + ... fields); GroupField cube(Field... fields); @@ -7354,7 +7354,7 @@ Field groupingId(Field...);]]>

    MySQL and CUBRID don't know any grouping functions, but they support a WITH ROLLUP clause, that is equivalent to simple ROLLUP() grouping functions. jOOQ emulates ROLLUP() in MySQL and CUBRID, by rendering this WITH ROLLUP clause. The following two statements mean the same:

    - + Some databases support user-defined functions, which can be embedded in any SQL statement, if you're using jOOQ's . Let's say you have the following simple function in Oracle SQL:

    - + The above function will be made available from a generated class. You can use it like any other :

    - + - +

    Note that user-defined functions returning or data types can also be used wherever can be used, if they are

    @@ -7406,7 +7406,7 @@ END echo;

    Some databases support user-defined aggregate functions, which can then be used along with or as . An example for such a database is Oracle. With Oracle, you can define the following OBJECT type (the example was taken from the Oracle 11g documentation):

    - +

    jOOQ's will detect such aggregate functions and generate them differently from regular . They implement the type, as mentioned in the manual's section about . Here's how you can use the SECOND_MAX() aggregate function with jOOQ:

    - +
    - +
    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:

    - + Row1 row(T1 t1) { ... } public static Row2 row(T1 t1, T2 t2) { ... } @@ -7636,12 +7636,12 @@ public static RowN row(Object... values) { ... }]]>

    See the relevant sections for more details about how to use row value expressions in predicates.

    - +

    Using row value expressions in UPDATE statements

    The also supports a variant where row value expressions are updated, rather than single columns. See the relevant section for more details

    - +

    Higher-degree row value expressions

    jOOQ chose to explicitly support degrees up to {max-row-degree} to match Scala's typesafe tuple, function and product support. Unlike Scala, however, jOOQ also supports higher degrees without the additional typesafety. @@ -7665,7 +7665,7 @@ public static RowN row(Object... values) { ... }]]>

  • The of a
  • The 's ON clause
  • - +

    Boolean types in SQL

    Before SQL:1999, boolean types did not really exist in SQL. They were modelled by 0 and 1 numeric/char values. With SQL:1999, true booleans were introduced and are now supported by most databases. In short, these are possible boolean values: @@ -7761,7 +7761,7 @@ Condition combined2 = combined1.andNot(c); // The left-hand side of the AND NOT

    Here are all boolean operators on the interface:

    - + < to test for being strictly less
  • <= to test for being less or equal
  • - +

    Unfortunately, Java does not support operator overloading, hence these operators are also implemented as methods in jOOQ, like any other SQL syntax elements. The relevant parts of the interface are these:

    - + ); // = (some column expression) eq or equal(Select>); // = (some scalar SELECT statement) @@ -7823,12 +7823,12 @@ ge or greaterOrEqual(Select>); // >= (some scalar SELECT st

    Note that every operator is represented by two methods. A verbose one (such as equal()) and a two-character one (such as eq()). Both methods are the same. You may choose either one, depending on your taste. The manual will always use the more verbose one.

    - +

    jOOQ's convenience methods using comparison operators

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using comparison predicates:

    - +
    - +
    Boolean operator precedence @@ -7855,7 +7855,7 @@ BOOK.TITLE.notEqualIgnoreCase("animal farm")]]>

    In SQL, the two expressions wouldn't be the same, as SQL natively knows operator precedence.

    - + A AND B OR C AND D OR E -- Precedence is applied (((A AND B) OR C) AND D) OR E -- Precedence is overridden @@ -7869,7 +7869,7 @@ BOOK.TITLE.notEqualIgnoreCase("animal farm")]]>

    All variants of the that we've seen in the previous chapter also work for . If your database does not support row value expression comparison predicates, jOOQ emulates them the way they are defined in the SQL standard:

    - + (X, Y))]]>

    jOOQ supports all of the above row value expression comparison predicates, both with and at the right-hand side:

    - +
    - +
    Quantified comparison predicate @@ -7966,7 +7966,7 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    It is interesting to note that the SQL standard defines the in terms of the ANY-quantified predicate. The following two expressions are equivalent:

    - + @@ -7977,14 +7977,14 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    - +
    NULL predicate

    In SQL, you cannot compare NULL with any value using , as the result would yield NULL again, which is neither TRUE nor FALSE (see also the manual's section about ). In order to test a for NULL, use the NULL predicate as such:

    - + @@ -8022,7 +8022,7 @@ NOT((A, B) IS NOT NULL)]]>

    The SQL standard contains a nice truth table for the above rules:

    - + +-----------------------+-----------+---------------+---------------+-------------------+ | Expression | R IS NULL | R IS NOT NULL | NOT R IS NULL | NOT R IS NOT NULL | +-----------------------+-----------+---------------+---------------+-------------------+ @@ -8036,13 +8036,13 @@ NOT((A, B) IS NOT NULL)]]>

    In jOOQ, you would simply use the isNull() and isNotNull() methods on row value expressions. Again, as with the , the row value expression NULL predicate is emulated by jOOQ, if your database does not natively support it:

    - +
    - +
    DISTINCT predicate @@ -8069,7 +8069,7 @@ BOOK.TITLE.isNotDistinctFrom(BOOK.SUB_TITLE)]]>

    If your database does not natively support the DISTINCT predicate, jOOQ emulates it with an equivalent , modelling the above truth table:

    - + ... or better, if the INTERSECT set operation is supported:

    - + - +
    @@ -8110,7 +8110,7 @@ EXISTS(SELECT a INTERSECT SELECT b)

    The BETWEEN predicate can be seen as syntactic sugar for a pair of . According to the SQL standard, the following two predicates are equivalent:

    - + = [B] AND [A] <= [C]]]> @@ -8131,7 +8131,7 @@ BOOK.PUBLISHED_IN.notBetween(1920).and(1940)]]>

    The SQL standard defines the SYMMETRIC keyword to be used along with BETWEEN to indicate that you do not care which bound of the range is larger than the other. A database system should simply swap range bounds, in case the first bound is greater than the second one. jOOQ supports this keyword as well, emulating it if necessary.

    - + @@ -8142,7 +8142,7 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The emulation is done trivially:

    - + @@ -8157,27 +8157,27 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The SQL BETWEEN predicate also works well for . Much like the , it is defined in terms of a pair of regular :

    - + = [B] AND [A] <= [C] ([A] >= [B] AND [A] <= [C]) OR ([A] >= [C] AND [A] <= [B])]]> - +

    The above can be factored out according to the rules listed in the manual's section about .

    - +

    jOOQ supports the BETWEEN [SYMMETRIC] predicate and emulates it in all SQL dialects where necessary. An example is given here:

    - + - + - +
    LIKE predicate @@ -8198,7 +8198,7 @@ TITLE NOT LIKE '%abc%']]> - +

    Escaping operands with the LIKE predicate

    Often, your pattern may contain any of the wildcard characters "_" and "%", in case of which you may want to escape them. jOOQ does not automatically escape patterns in like() and notLike() methods. Instead, you can explicitly define an escape character as such: @@ -8217,12 +8217,12 @@ BOOK.TITLE.notLike("%The !%-Sign Book%", '!')]]>

    Please refer to your database manual for more details about escaping patterns with the LIKE predicate.

    - +

    jOOQ's convenience methods using the LIKE predicate

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using the LIKE predicate. Typical operations are "contains predicates", "starts with predicates", "ends with predicates", etc. Here is the full convenience API wrapping LIKE predicates:

    - + >) // Construct a NOT IN predicate from a subse

    A sample IN predicate might look like this:

    - + @@ -8275,12 +8275,12 @@ TITLE NOT IN ('Animal Farm', '1984')]]>
    BOOK.TITLE.notIn("Animal Farm", "1984")]]>
    - +

    NOT IN and NULL values

    Beware that you should probably not have any NULL values in the right hand side of a NOT IN predicate, as the whole expression would evaluate to NULL, which is rarely desired. This can be shown informally using the following reasoning:

    - + -- The following conditional expressions are formally or informally equivalent A NOT IN (B, C) A != ANY(B, C) @@ -8321,7 +8321,7 @@ NULL -- [ANY] AND NULL yields NULL -- Using a subselect (BOOK.ID, BOOK.TITLE) IN ( SELECT T.ID, T.TITLE - FROM T + FROM T )]]> - +

    In both cases, i.e. when using an IN list or when using a subselect, the type of the predicate is checked. Both sides of the predicate must be of equal degree and row type.

    - +

    - Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value. + Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value.

    - +
    EXISTS predicate @@ -8355,7 +8355,7 @@ row(BOOK.ID, BOOK.TITLE).in(
  • From a using
  • From a using , and from other clauses
  • - +

    An example of an EXISTS predicate can be seen here:

    @@ -8374,7 +8374,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

    - +

    Performance of IN vs. EXISTS

    In theory, the two types of predicates can perform equally well. If your database system ships with a sophisticated cost-based optimiser, it will be able to transform one predicate into the other, if you have all necessary constraints set (e.g. referential constraints, not null constraints). However, in reality, performance between the two might differ substantially. An interesting blog post investigating this topic on the MySQL database can be seen here:
    @@ -8382,7 +8382,7 @@ notExists(create.selectOne().from(BOOK)

    - +
    OVERLAPS predicate @@ -8420,7 +8420,7 @@ row(Date.valueOf('2010-01-01'), new DayToSecond(2)).overlaps(Date.valueOf('2010-

    Unlike the standard (or any database implementing the standard), jOOQ also supports the OVERLAPS predicate for comparing arbitrary . For instance, (1, 3) OVERLAPS (2, 4) will yield true in jOOQ. This is emulated as such

    - +
    - +
    Dynamic SQL

    In most cases, , , and as introduced in the previous chapters will be embedded into different SQL statement clauses as if the statement were a static SQL statement (e.g. in a view or stored procedure):

    - + - +

    It is, however, interesting to think of all of the above expressions as what they are: expressions. And as such, nothing keeps users from extracting expressions and referencing them from outside the statement. The following statement is exactly equivalent:

    @@ -8464,26 +8464,26 @@ create.select(select) .groupBy(groupBy) .orderBy() .fetch();]]> - +

    Each individual expression, and collection of expressions can be seen as an independent entity that can be

    - +
    1. Constructed dynamically
    2. Reused across queries
    - +

    Dynamic construction is particularly useful in the case of the , for dynamic predicate building. For instance:

    - +

    The dynamic SQL building power may be one of the biggest advantages of using a runtime query model like the one offered by jOOQ. Queries can be created dynamically, of arbitrary complexity. In the above example, we've just constructed a dynamic . The same can be done for any other clauses, including dynamic , or adding additional as needed.

    @@ -8519,7 +8519,7 @@ create.select()
  • - +

    You'll probably find other examples. If verbosity scares you off, don't worry. The verbose use-cases for jOOQ are rather rare, and when they come up, you do have an option. Just write SQL the way you're used to!

    @@ -8549,7 +8549,7 @@ Condition condition(String sql, Object... bindings); // Construct a condition taking other jOOQ object arguments // Example: condition("a = {0}", val(1)); 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 DSL:

    @@ -8607,7 +8607,7 @@ Result fetch(String sql, QueryPart... parts);]]>

    Apart from the general factory methods, plain SQL is also available in various other contexts. For instance, when adding a .where("a = b") clause to a query. Hence, there exist several convenience methods where plain SQL can be inserted usefully. This is an example displaying all various use-cases in one single query:

    - + LAST_NAME = create.field("a.LAST_NAME"); @@ -8728,7 +8728,7 @@ Name name = name("AUTHOR", "TITLE");]]> On a JDBC level, you can also reuse the SQL string and prepared statement object instead of constructing it again, as you can bind new values to the prepared statement. jOOQ currently does not cache prepared statements, internally. - +

    The following sections explain how you can introduce bind values in jOOQ, and how you can control the way they are rendered and bound to SQL.

    @@ -8741,7 +8741,7 @@ Name name = name("AUTHOR", "TITLE");]]>

    JDBC only knows indexed bind values. A typical example for using bind values with JDBC is this:

    - + With dynamic SQL, keeping track of the number of question marks and their corresponding index may turn out to be hard. jOOQ abstracts this and lets you provide the bind value right where it is needed. A trivial example is this:

    - + 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

    Should you decide to run the above query outside of jOOQ, using your own , you can do so as follows:

    - + select = create.select().from(BOOK).where(BOOK.ID.equal(5)).and(BOOK.TITLE.equal("Animal Farm")); // Render the SQL statement: @@ -8894,25 +8894,25 @@ create.select()
    SQL injection - +

    SQL injection is serious

    SQL injection is a serious problem that needs to be taken care of thoroughly. A single vulnerability can be enough for an attacker to dump your whole database, and potentially seize your database server. We've blogged about the severity of this threat on the jOOQ blog.

    - +

    SQL injection happens because a programming language (SQL) is used to dynamically create arbitrary server-side statements based on user input. Programmers must take lots of care not to mix the language parts (SQL) with the user input ()

    - +

    SQL injection in jOOQ

    With jOOQ, SQL is usually created via a type safe, non-dynamic Java abstract syntax tree, where bind variables are a part of that abstract syntax tree. It is not possible to expose SQL injection vulnerabilities this way.

    - +

    However, jOOQ offers convenient ways of introducing in various places of the jOOQ API (which are annotated using since jOOQ 3.6). While jOOQ's API allows you to specify bind values for use with plain SQL, you're not forced to do that. For instance, both of the following queries will lead to the same, valid result:

    - +

    A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] FROM AUTHOR JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID @@ -9055,15 +9055,15 @@ public final void accept(Context context) {

    As mentioned in the previous chapter about , there are some elements in the that are used for formatting / pretty-printing rendered SQL. In order to obtain pretty-printed SQL, just use the following :

    - - + +

    And then, use the above DSLContext to render pretty-printed SQL:

    - + A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] WHERE AUTHOR.ID = ? -- [...] @@ -9156,11 +9156,11 @@ public final void bind(BindContext context) throws DataAccessException {

    Converters

    - +

    The simplest use-case of injecting custom data types is by using . A Converter can convert from a database type <T> to a user-defined type <U> and vice versa. You'll be implementing this SPI:

    - + { // Your conversion logic goes into these two methods, that can convert @@ -9171,8 +9171,8 @@ public final void bind(BindContext context) throws DataAccessException { // You need to provide Class instances for each type, too: Class fromType(); Class toType(); -}]]> - +}]]> +

    If, for instance, you want to use Java 8's for SQL DATE and for SQL TIMESTAMP, you write a converter like this:

    @@ -9203,14 +9203,14 @@ public class LocalDateConverter implements Converter { public Class toType() { return LocalDate.class; } -}]]> +}]]>

    This converter can now be used in a variety of jOOQ API, most importanly to create a new data type:

    - + type = SQLDataType.DATE.asConvertedDataType(new LocalDateConverter());]]> - +

    And data types, in turn, can be used with any , i.e. with any , including or based ones:

    @@ -9223,15 +9223,15 @@ Field date1 = DSL.field("my_table.my_column", type); // Name based Field date2 = DSL.field(name("my_table", "my_column"), type);]]> - +

    Bindings

    - +

    While converters are very useful for simple use-cases, is useful when you need to customise data type interactions at a JDBC level, e.g. when you want to bind a PostgreSQL JSON data type. Custom bindings implement the following SPI:

    - + extends Serializable { // A converter that does the conversion between the database type T @@ -9251,11 +9251,11 @@ Field date2 = DSL.field(name("my_table", "my_column"), type);]]> ctx) throws SQLException; void get(BindingGetSQLInputContext ctx) throws SQLException; }]]> - +

    Below is full fledged example implementation that uses Google Gson to model JSON documents in Java

    - + { public void get(BindingGetSQLInputContext ctx) throws SQLException { throw new SQLFeatureNotSupportedException(); } -}]]> - +}]]> +

    Code generation

    There is a special section in the manual explaining how to automatically tie your Converters and Bindings to your generated code. The relevant sections are:

    - +
    - +
    Custom syntax elements

    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:

    - + extends AbstractField {} public abstract class CustomCondition extends AbstractCondition {} public abstract class CustomTable> extends TableImpl {} @@ -9366,7 +9366,7 @@ public abstract class CustomRecord> extends TableRecord

    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 method, as discussed before:

    - + 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 showing how to create a field multiplying another field by 2

    - + IDx2 = new CustomField(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(" * ?"); @@ -9406,10 +9406,10 @@ final Field IDx2 = new CustomField(BOOK.ID.getName(), BOOK.ID. @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(DSL.val(2)); } @@ -9428,7 +9428,7 @@ create.select(IDx2).from(BOOK);]]>

    Many vendor-specific functions are not officially supported by jOOQ, but you can implement such support yourself using CustomField, for instance. Here's an example showing how to implement Oracle's TO_CHAR() function, emulating it in SQL Server using CONVERT():

    - + { @@ -9465,7 +9465,7 @@ class ToChar extends CustomField {

    The above CustomField implementation can be exposed from your own custom DSL class:

    - + toChar(Field field, String format) { return new ToChar(field, DSL.inline(format)); @@ -9473,7 +9473,7 @@ class ToChar extends CustomField { }]]>
    - +
    Plain SQL QueryParts @@ -9487,10 +9487,10 @@ class ToChar extends CustomField {

    The above distinction is best explained using an example:

    - + Note that for historic reasons the two API usages can also be mixed, although this is not recommended and the exact behaviour is unspecified.

    - +

    Plain SQL templating specification

    - +

    Templating with QueryPart placeholders (or bind value placeholders) requires a simple parsing logic to be applied to SQL strings. The jOOQ template parser behaves according to the following rules:

    @@ -9525,13 +9525,13 @@ create.selectFrom(BOOK).where(
  • QueryPart placeholders ({number}) are replaced by the matching QueryPart.
  • Keywords ({identifier}) are treated like keywords and rendered in the correct case according to .
  • - +

    Tools for templating

    - +

    A variety of API is provided to create template elements that are intended for use with the above templating mechanism. These tools can be found in

    - +

    - +
    Custom SQL transformation @@ -9577,7 +9577,7 @@ create.attach(select);]]> With jOOQ 3.2's SPI, it is possible to perform custom SQL transformation to implement things like shared-schema multi-tenancy, or a security layer centrally preventing access to certain data. This SPI is extremely powerful, as you can make ad-hoc decisions at runtime regarding local or global transformation of your SQL statement. The following sections show a couple of simple, yet real-world use-cases.

    - +
    Logging abbreviated bind values @@ -9585,7 +9585,7 @@ create.attach(select);]]>

    When implementing a logger, one needs to carefully assess how much information should really be disclosed on what logger level. In log4j and similar frameworks, we distinguish between FATAL, ERROR, WARN, INFO, DEBUG, and TRACE. In DEBUG level, jOOQ's logs all executed statements including inlined bind values as such:

    - + with bind values : select * from "BOOK" where "BOOK"."TITLE" like 'How I stopped worrying%']]> @@ -9601,7 +9601,7 @@ public class BindValueAbbreviator extends DefaultVisitListener { @Override public void visitStart(VisitContext context) { - + // Transform only when rendering values if (context.renderContext() != null) { QueryPart part = context.queryPart(); @@ -9615,16 +9615,16 @@ public class BindValueAbbreviator extends DefaultVisitListener { // e.g. using commons-lang's StringUtils.abbreviate() if (value instanceof String && ((String) value).length() > maxLength) { anyAbbreviations = true; - + // ... and replace it in the current rendering context (not in the Query) context.queryPart(val(abbreviate((String) value, maxLength))); } - + // If the bind value is a byte[] (or Blob) of a given length, abbreviate it // e.g. by removing bytes from the array else if (value instanceof byte[] && ((byte[]) value).length > maxLength) { anyAbbreviations = true; - + // ... and replace it in the current rendering context (not in the Query) context.queryPart(val(Arrays.copyOf((byte[]) value, maxLength))); } @@ -9634,10 +9634,10 @@ public class BindValueAbbreviator extends DefaultVisitListener { @Override public void visitEnd(VisitContext context) { - + // If any abbreviations were performed before... if (anyAbbreviations) { - + // ... and if this is the top-level QueryPart, then append a SQL comment to indicate the abbreviation if (context.queryPartsLength() == 1) { context.renderContext().sql(" -- Bind values may have been abbreviated"); @@ -9662,14 +9662,14 @@ public class BindValueAbbreviator extends DefaultVisitListener {
    - +
    SQL building in Scala

    jOOQ-Scala is a maven module used for leveraging some advanced Scala features for those users that wish to use jOOQ with Scala.

    - +

    Using Scala's implicit defs to allow for operator overloading

    The most obvious Scala feature to use in jOOQ are implicit defs for implicit conversions in order to enhance the type with SQL-esque operators. @@ -9677,7 +9677,7 @@ public class BindValueAbbreviator extends DefaultVisitListener {

    The following depicts a trait which wraps all fields:

    - + The following depicts a trait which wraps numeric fields:

    - + An example query using such overloaded operators would then look like this:

    - +

    In a previous section of the manual, we've seen how jOOQ can be used to that can be executed with any API including JDBC or ... jOOQ. This section of the manual deals with various means of actually executing SQL with jOOQ.

    - +

    SQL execution with JDBC

    JDBC calls executable objects "". It distinguishes between three types of statements: @@ -9817,7 +9817,7 @@ fetch]]>

    Today, the JDBC API may look weird to users being used to object-oriented design. While statements hide a lot of SQL dialect-specific implementation details quite well, they assume a lot of knowledge about the internal state of a statement. For instance, you can use the method, to add a the prepared statement being created to an "internal list" of batch statements. Instead of returning a new type, this method forces user to reflect on the prepared statement's internal state or "mode".

    - +

    jOOQ is wrapping JDBC

    These things are abstracted away by jOOQ, which exposes such concepts in a more object-oriented way. For more details about jOOQ's batch query execution, see the manual's section about . @@ -9825,7 +9825,7 @@ fetch]]>

    The following sections of this manual will show how jOOQ is wrapping JDBC for SQL execution

    - +

    Alternative execution modes

    Just because you can, doesn't mean you must. At the end of this chapter, we'll show how you can use jOOQ to generate SQL statements that are then executed with other APIs, such as Spring's JdbcTemplate, or Hibernate. For more information see the . @@ -9844,7 +9844,7 @@ fetch]]>

  • Both APIs return the number of affected records in non-result queries. JDBC: , jOOQ:
  • Both APIs return a scrollable result set type from result queries. JDBC: , jOOQ:
  • - +

    Differences to JDBC

    Some of the most important differences between JDBC and jOOQ are listed here: @@ -9860,14 +9860,14 @@ fetch]]>

    - +
    Query vs. ResultQuery

    Unlike JDBC, jOOQ has a lot of knowledge about a SQL query's structure and internals (see the manual's section about ). Hence, jOOQ distinguishes between these two fundamental types of queries. While every can be executed, only can return results (see the manual's section about to learn more about fetching results). With plain SQL, the distinction can be made clear most easily:

    - + result = resultQuery.fetch();]]>
  • : Some databases allow for returning many result sets from a single query. JDBC can handle this but it's very verbose. A list of results should be returned instead.
  • : Some queries take too long to execute to wait for their results. You should be able to spawn query execution in a separate process.
  • - +

    Convenience and how ResultQuery, Result, and Record share API

    The term "fetch" is always reused in jOOQ when you can fetch data from the database. An provides many overloaded means of fetching data:

    - +

    Various modes of fetching

    These modes of fetching are also documented in subsequent sections of the manual

    - + fetch(); @@ -9933,7 +9933,7 @@ List> fetchMany(); // Execute a ResultQuery with jOOQ, but return a JDBC ResultSet, not a jOOQ object ResultSet fetchResultSet();]]> - +

    Fetch convenience

    These means of fetching are also available from and APIs @@ -9979,11 +9979,11 @@ ResultSet fetchResultSet();]]>

    These means of fetching are also available from and APIs

    - + Map fetchMap(Field key); Map fetchMap(Field key, Field value); @@ -10023,7 +10023,7 @@ ResultSet fetchResultSet();]]>

    Yet, still, sometimes you wish to use strongly typed records, when you know that you're selecting only from a single table:

    - +

    Fetching strongly or weakly typed records

    When fetching data only from a single table, the type is known to jOOQ if you use jOOQ's to generate for your database tables. In order to fetch such strongly typed records, you will have to use the : @@ -10035,7 +10035,7 @@ BookRecord book = create.selectFrom(BOOK).where(BOOK.ID.equal(1)).fetchOne(); // Typesafe field access is now possible: 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:

    @@ -10043,11 +10043,11 @@ System.out.println("Published in: " + book.getPublishedIn());]]>
  • - +

    Mapping custom row types to strongly typed records

    - +

    Sometimes, you may want to explicitly select only a subset of your columns, but still use strongly typed records. Alternatively, you may want to join a one-to-one relationship and receive the two individual strongly typed records after the join.

    @@ -10108,7 +10108,7 @@ System.out.println("Author : " + author.getFirstName() + " " + author.getLa

    By default, jOOQ returns an object, which is essentially a of . Often, you will find yourself wanting to transform this result object into a type that corresponds more to your specific needs. Or you just want to list all values of one specific column. Here are some examples to illustrate those use cases:

    - + titles1 = create.select().from(BOOK).fetch().getValues(BOOK.TITLE); List titles2 = create.select().from(BOOK).fetch(BOOK.TITLE); @@ -10143,7 +10143,7 @@ Map> group4 = create.selectFrom(BOOK).fetchGroups(BO

    In a more functional operating mode, you might want to write callbacks that receive records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + () {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -10178,7 +10178,7 @@ create.selectFrom(BOOK)

    In a more functional operating mode, you might want to write callbacks that map records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + ids = create.selectFrom(BOOK) @@ -10190,12 +10190,12 @@ create.selectFrom(BOOK) return book.getId(); } }); - + // Or more concisely create.selectFrom(BOOK) .orderBy(BOOK.ID) .fetch(new RecordMapper() {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -10221,7 +10221,7 @@ create.selectFrom(BOOK)

    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. See the manual's section about to see how to modify jOOQ's standard POJO mapping behaviour.

    - +

    Using JPA-annotated POJOs

    jOOQ tries to find JPA annotations on your POJO types. If it finds any, they are used as the primary source for mapping meta-information. Only the annotation is used and understood by jOOQ. An example: @@ -10231,7 +10231,7 @@ create.selectFrom(BOOK) public class MyBook { @Column(name = "ID") public int myId; - + @Column(name = "TITLE") public String myTitle; } @@ -10240,16 +10240,16 @@ public class MyBook { MyBook myBook = create.select().from(BOOK).fetchAny().into(MyBook.class); List myBooks = create.select().from(BOOK).fetch().into(MyBook.class); List myBooks = create.select().from(BOOK).fetchInto(MyBook.class);]]> - +

    Just as with any other JPA implementation, you can put the annotation on any class member, including attributes, setters and getters. Please refer to the Javadoc for more details.

    - +

    Using simple POJOs

    If jOOQ does not find any JPA-annotations, columns are mapped to the "best-matching" constructor, attribute or setter. An example illustrates this:

    - + myBooks = create.select().from(BOOK).fetchInto(MyBook1.class);]]><

    Please refer to the Javadoc for more details.

    - +

    Using "immutable" POJOs

    If jOOQ does not find any default constructor, columns are mapped to the "best-matching" constructor. This allows for using "immutable" POJOs with jOOQ. An example illustrates this:

    - + myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchInto( public class MyBook3 { public final String title; public final int id; - + @ConstructorProperties({ "title", "id"}) public MyBook2(String title, int id) { this.title = title; @@ -10304,7 +10304,7 @@ MyBook3 myBook = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchA List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetch().into(MyBook3.class); List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchInto(MyBook3.class); ]]> - +

    Please refer to the Javadoc for more details.

    @@ -10313,12 +10313,12 @@ List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchI

    jOOQ also allows for fetching data into abstract classes or interfaces, or in other words, "proxyable" types. This means that jOOQ will return a wrapped in a implementing your custom type. An example of this is given here:

    - + - +

    Note: Because of your manual setting of ID = 10, jOOQ's store() method will asume that you want to insert a new record. See the manual's section about for more details on this.

    - +

    Interaction with DAOs

    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: @@ -10385,21 +10385,21 @@ bookDao.update(book); // Delete it again bookDao.delete(book);]]> - +

    More complex data structures

    jOOQ currently doesn't support more complex data structures, the way Hibernate/JPA attempt to map relational data onto POJOs. While future developments in this direction are not excluded, jOOQ claims that generic mapping strategies lead to an enormous additional complexity that only serves very few use cases. You are likely to find a solution using any of jOOQ's various , with only little boiler-plate code on the client side.

    - +
    POJOs with RecordMappers

    In the previous sections we have seen how to create types to map jOOQ records onto arbitrary objects. We have also seen how jOOQ provides default algorithms to map jOOQ records onto . Your own custom domain model might be much more complex, but you want to avoid looking up the most appropriate RecordMapper every time you need one. For this, you can provide jOOQ's with your own implementation of the interface. An example is given here:

    - + } } } - + // Books might be joined with their authors, create a 1:1 mapping if (type == Book.class) { return new BookMapper(); @@ -10436,12 +10436,12 @@ bookDao.delete(book);]]>

    The above is a very simple example showing that you will have complete flexibility in how to override jOOQ's record to POJO mapping mechanisms.

    - +

    Using third party libraries

    A couple of useful libraries exist out there, which implement custom, more generic mapping algorithms. Some of them have been specifically made to work with jOOQ. Among them are:

    - +
    • ModelMapper (with an explicit jOOQ integration)
    • SimpleFlatMapper (with an explicit jOOQ integration)
    • @@ -10456,14 +10456,14 @@ bookDao.delete(book);]]>

      Unlike JDBC's , jOOQ's does not represent an open database cursor with various fetch modes and scroll modes, that needs to be closed after usage. jOOQ's results are simple in-memory Java objects, containing all of the result values. If your result sets are large, or if you have a lot of network latency, you may wish to fetch records one-by-one, or in small chunks. jOOQ supports a type for that purpose. In order to obtain such a reference, use the method. An example is given here:

      - + cursor = create.selectFrom(BOOK).fetchLazy()) { // Cursor has similar methods as Iterator while (cursor.hasNext()) { BookRecord book = cursor.fetchOne(); - + Util.doThingsWithBook(book); } }]]> @@ -10471,7 +10471,7 @@ try (Cursor cursor = create.selectFrom(BOOK).fetchLazy()) {

      As a holds an internal reference to an open , it may need to be closed at the end of iteration. If a cursor is completely scrolled through, it will conveniently close the underlying ResultSet. However, you should not rely on that.

      - +

      Cursors ship with all the other fetch features

      Like or , gives access to all of the other fetch features that we've seen so far, i.e. @@ -10491,7 +10491,7 @@ try (Cursor cursor = create.selectFrom(BOOK).fetchLazy()) {

      jOOQ 3.7+ supports Java 8, and with Java 8, it supports . This opens up a range of possibilities of combining the declarative aspects of SQL with the functional aspects of the new Stream API. Much like , such a Stream keeps an internal reference to a JDBC , which means that the Stream has to be treated like a resource. Here's an example of using such a stream:

      - + stream = create.selectFrom(BOOK).stream()) { stream.forEach(Util::doThingsWithBook); @@ -10536,7 +10536,7 @@ try (Stream stream = create.selectFrom(BOOK).stream()) { " " + col.getValue()) .collect(Collectors.joining(",\n")) ); - + System.out.println(");"); });]]> @@ -10577,7 +10577,7 @@ CREATE TABLE COLUMNS( REMARKS VARCHAR, SOURCE_DATA_TYPE SMALLINT );]]> - +
    @@ -10609,7 +10609,7 @@ CREATE TABLE COLUMNS(

    The correct (and verbose) way to do this with JDBC is as follows:

    - +

    As previously discussed in the chapter about , jOOQ does not rely on an internal state of any JDBC object, which is "externalised" by Javadoc. Instead, it has a straight-forward API allowing you to do the above in a one-liner:

    - + @@ -10650,22 +10650,22 @@ Results results = create.fetchMany("sp_help 'author'");]]>
    Later fetching

    Using Java 8 CompletableFutures

    - +

    Java 8 has introduced the new type, which allows for functional composition of asynchronous execution units. When applying this to SQL and jOOQ, you might be writing code as follows:

    - + + .supplyAsync(() -> DSL.using(configuration) .insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .values(3, "Hitchcock") .execute() ) - + // This will supply an AuthorRecord value for the newly inserted author .handleAsync((rows, throwable) -> DSL.using(configuration) @@ -10678,30 +10678,30 @@ CompletableFuture record.changed(true); return record.insert(); }) - + // This will supply an int value indicating the number of deleted rows - .handleAsync((rows, throwable) -> + .handleAsync((rows, throwable) -> DSL.using(configuration) .delete(AUTHOR) .where(AUTHOR.ID.eq(3)) .execute() ) .join();]]> - +

    The above example will execute four actions one after the other, but asynchronously in the JDK's default or common . -

    - +

    +

    For more information, please refer to the Javadoc and official documentation. -

    - +

    +

    Using deprecated API

    - +

    Some queries take very long to execute, yet they are not crucial for the continuation of the main program. For instance, you could be generating a complicated report in a Swing application, and while this report is being calculated in your database, you want to display a background progress bar, allowing the user to pursue some other work. This can be achived simply with jOOQ, by creating a , a type that extends . An example is given here:

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(); @@ -10717,7 +10717,7 @@ Result result = future.get();]]>

    Note, that instead of letting jOOQ spawn a new thread, you can also provide jOOQ with your own :

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(service);]]> @@ -10731,7 +10731,7 @@ FutureResult future = create.selectFrom(BOOK).where(... complex pred

    When interacting with legacy applications, you may prefer to have jOOQ return a , rather than jOOQ's own types. This can be done simply, in two ways:

    - + cursor = create.fetchLazy(rs);]]>

    You can also tighten the interaction with jOOQ's data type system and features, by passing the record type to the above fetch methods:

    - + result = create.fetch (rs, Integer.class, String.class); Cursor result = create.fetchLazy(rs, Integer.class, String.class); @@ -10795,7 +10795,7 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Apart from a few extra features (), jOOQ only supports basic types as supported by the JDBC API. In your application, you may choose to transform these data types into your own ones, without writing too much boiler-plate code. This can be done using jOOQ's types. A converter essentially allows for two-way conversion between two Java data types <T> and <U>. By convention, the <T> type corresponds to the type in your database whereas the <U> type corresponds to your own user type. The Converter API is given here:

    - + extends Serializable { /** @@ -10822,12 +10822,12 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Such a converter can be used in many parts of the jOOQ API. Some examples have been illustrated in the manual's section about .

    - +

    A Converter for GregorianCalendar

    Here is a some more elaborate example involving a Converter for :

    - + { @@ -10858,12 +10858,12 @@ public class CalendarConverter implements Converter dates1 = create.selectFrom(BOOK).fetch().getValues(BOOK.PUBLISHING_DATE, new CalendarConverter()); List dates2 = create.selectFrom(BOOK).fetch(BOOK.PUBLISHING_DATE, new CalendarConverter()); ]]> - +

    Enum Converters

    jOOQ ships with a built-in default , that you can use to map VARCHAR values to enum literals or NUMBER values to enum ordinals (both modes are supported). Let's say, you want to map a YES / NO / MAYBE column to a custom Enum:

    - + - +

    Using Converters in generated source code

    jOOQ also allows for generated source code to reference your own custom converters, in order to permanently replace a <T> type by your own, custom <U> type. See the manual's section about for details. @@ -10925,20 +10925,20 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE) .join(AUTHOR).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) .intern(BOOK.AUTHOR_ID) .fetch();]]> - +

    You can specify as many fields as you want for interning. The above has the following effect:

    - +
    • If the interned Field is of type , then is called upon each string
    • If the interned Field is of any other type, then the call is ignored
    - +

    Future versions of jOOQ will implement interning of data for non-String data types by collecting values in , removing duplicate instances.

    - +

    Note, that jOOQ will not use interned data for identity comparisons: string1 == string2. Interning is used only to reduce the memory footprint of objects.

    @@ -10946,7 +10946,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)
    - +
    Static statements vs. Prepared Statements @@ -10956,7 +10956,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)

    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:

    - + @@ -10986,7 +10986,7 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    Whichever aproach is more optimal for you cannot be decided by jOOQ. In most cases, prepared statements are probably better. But you always have the option of forcing jOOQ to render inlined bind values.

    - +

    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 @@ -11000,15 +11000,15 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    As previously discussed in the chapter about , reusing PreparedStatements is handled a bit differently in jOOQ from how it is handled in JDBC

    - +

    Keeping open PreparedStatements with JDBC

    With JDBC, you can easily reuse a by not closing it between subsequent executions. An example is given here:

    - + The above technique can be quite useful when you want to reuse expensive database resources. This can be the case when your statement is executed very frequently and your database would take non-negligible time to soft-parse the prepared statement and generate a new statement / cursor resource.

    - +

    Keeping open PreparedStatements with jOOQ

    This is also modeled in jOOQ. However, the difference to JDBC is that closing a statement is the default action, whereas keeping it open has to be configured explicitly. This is better than JDBC, because the default action should be the one that is used most often. Keeping open statements is rarely done in average applications. Here's an example of how to keep open PreparedStatements with jOOQ:

    - + query = create.selectOne().keepStatement(true)) { Result result1 = query.fetch(); // This will lazily create a new PreparedStatement @@ -11043,7 +11043,7 @@ try (ResultQuery query = create.selectOne().keepStatement(true)) {

    JDBC knows a couple of execution flags and modes, which can be set through the jOOQ API as well. jOOQ essentially supports these flags and execution modes:

    - + query = create.selectOne().keepStatement(true)) { // The query execution timeout. // ----------------------------------------------------------- Query queryTimeout(int timeout); - + }]]> - + extends Query { // [...] @@ -11076,25 +11076,25 @@ try (ResultQuery query = create.selectOne().keepStatement(true)) { // The maximum number of rows to be fetched by JDBC // ----------------------------------------------------------- ResultQuery maxRows(int rows); - + }]]>

    Using ResultSet concurrency with ExecuteListeners

    An example of why you might want to manually set a ResultSet's concurrency flag to something non-default is given here:

    - + - +

    In the above example, your custom is triggered before jOOQ loads a new Record from the JDBC ResultSet. With the concurrency being set to ResultSet.CONCUR_UPDATABLE, you can now modify the database cursor through the standard JDBC ResultSet API.

    @@ -11152,22 +11152,22 @@ try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO author(id stmt.setString(2, "Erich"); stmt.setString(3, "Gamma"); stmt.addBatch(); - + stmt.setInt(1, 2); stmt.setString(2, "Richard"); stmt.setString(3, "Helm"); stmt.addBatch(); - + stmt.setInt(1, 3); stmt.setString(2, "Ralph"); stmt.setString(3, "Johnson"); stmt.addBatch(); - + stmt.setInt(1, 4); stmt.setString(2, "John"); stmt.setString(3, "Vlissides"); stmt.addBatch(); - + int[] result = stmt.executeBatch(); }]]>
    @@ -11176,7 +11176,7 @@ try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO author(id

    jOOQ supports executing queries in batch mode as follows:

    - + - +

    When creating a batch execution with a single query and multiple bind values, you will still have to provide jOOQ with dummy bind values for the original query. In the above example, these are set to null. For subsequent calls to bind(), there will be no type safety provided by jOOQ.

    @@ -11212,18 +11212,18 @@ create.batch(create.insertInto(AUTHOR, ID, FIRST_NAME, LAST_NAME ).values((Inte

    Instead of actually phrasing a select statement, you can also use the convenience methods:

    - + - +

    Inlining sequence references in SQL

    You can inline sequence references in jOOQ SQL statements. The following are examples of how to do that:

    - + The general distinction between (stored) procedures and (stored) functions can be summarised like this:

    - +

    Procedures

    • Are called using JDBC CallableStatement
    • Have no return value
    • Usually support OUT parameters
    - +

    Functions

    • Can be used in SQL statements
    • Have a return value
    • Usually don't support OUT parameters
    - +

    Exceptions to these rules

    • DB2, H2, and HSQLDB don't allow for JDBC escape syntax when calling functions. Functions must be used in a SELECT statement
    • @@ -11284,19 +11284,19 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

      To simplify things a little bit, jOOQ handles both procedures and functions the same way, using a more general type.

      - +

      Using jOOQ for standalone calls to stored procedures and functions

      If you're using jOOQ's , it will generate objects for you. Let's consider the following example:

      - +

      The generated artefacts can then be used as follows:

      - + - +

      But you can also call the procedure using a generated convenience method in a global Routines class:

      @@ -11323,7 +11323,7 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]>

      For more details about for procedures, see the manual's section about .

      - +

      Inlining stored function references in SQL

      Unlike procedures, functions can be inlined in SQL statements to generate or , if you're using . Assume you have a function like this: @@ -11331,11 +11331,11 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]> - +

      The generated artefacts can then be used as follows:

      - + boolean exists = create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]> - +

      For more info about inlining stored function references in SQL statements, please refer to the manual's section about .

      @@ -11376,7 +11376,7 @@ create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]>

      Oracle UDTs can have object-oriented structures including member functions and procedures. With Oracle, you can do things like this:

      - + {"schema":"schema-n","table":"table-n","name":"field-n","type":"type-n"}], "records":[[value-1-1,value-1-2,...,value-1-n], [value-2-1,value-2-2,...,value-2-n]]} - +

      Note: This format has been modified in jOOQ 2.6.0 and 3.7.0

      @@ -11691,7 +11691,7 @@ Query query = error.query();]]>
    - +
    Importing JSON @@ -11725,7 +11725,7 @@ create.loadInto(BOOK)

    - +
    Importing Records @@ -11755,7 +11755,7 @@ DSL.using(configuration1)

    - +
    Importing Arrays @@ -11801,12 +11801,12 @@ DSL.using(configuration1)

    CRUD always uses the same patterns, regardless of the nature of underlying tables. This again, leads to a lot of boilerplate code, if you have to issue your statements yourself. Like Hibernate / JPA and other ORMs, jOOQ facilitates CRUD using a specific API involving types.

    - +

    Primary keys and updatability

    In normalised databases, every table has a primary key by which a tuple/record within that table can be uniquely identified. In simple cases, this is a (possibly auto-generated) number called ID. But in many cases, primary keys include several non-numeric columns. An important feature of such keys is the fact that in most databases, they are enforced using an index that allows for very fast random access to the table. A typical way to access / modify / delete a book is this:

    - + - +

    Normalised databases assume that a primary key is unique "forever", i.e. that a key, once inserted into a table, will never be changed or re-inserted after deletion. In order to use jOOQ's operations correctly, you should design your database accordingly.

    @@ -11827,7 +11827,7 @@ DELETE FROM BOOK WHERE ID = 5;]]>

    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:

    - + - +

    See the manual's section about for some more insight on "attached" objects.

    - +

    Storing

    Storing a record will perform an or an . In general, new records are always inserted, whereas records loaded from the database are always updated. This is best visualised in code: @@ -11866,7 +11866,7 @@ BookRecord book2 = create.fetchOne(BOOK, BOOK.ID.equal(id)); // Update the record: UPDATE BOOK SET TITLE = 'Animal Farm' WHERE ID = [id] book2.setTitle("Animal Farm"); book2.store();]]> - +

    Some remarks about storing:

    @@ -11876,18 +11876,18 @@ book2.store();]]>
  • When loading records from , jOOQ will assume the record is a new record. It will hence attempt to INSERT it.
  • When you activate , storing a record may fail, if the underlying database record has been changed in the mean time.
  • - +

    Deleting

    Deleting a record will remove it from the database. Here's how you delete records:

    - + - +

    Refreshing

    Refreshing a record from the database means that jOOQ will issue a to refresh all record values that are not the primary key. This is particularly useful when you use jOOQ's feature, in case a modified record is "stale" and cannot be stored to the database, because the underlying database record has changed in the mean time. @@ -11906,7 +11906,7 @@ book.refresh();]]>

    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 :

    - + The "original" value, i.e. the value as it was originally fetched from the database or null, if the record was never in the database
  • The "changed" flag, indicating if the value was ever changed through the Record API.
  • - +

    The purpose of the above information is for jOOQ's to know, which values need to be stored to the database, and which values have been left untouched.

    @@ -11942,19 +11942,19 @@ for (BookRecord book : create.fetch(BOOK, BOOK.PUBLISHED_IN.equal(1948))) {

    Many databases support the concept of IDENTITY values, or key values. This is reflected by JDBC's method. jOOQ abstracts using this method as many databases and JDBC drivers behave differently with respect to generated keys. Let's assume the following SQL Server BOOK table:

    - +

    If you're using jOOQ's , the above table will generate a with an IDENTITY column. This information is used by jOOQ internally, to update IDs after calling :

    - +

    and contain foreign key navigation methods. These navigation methods allow for "navigating" inbound or outbound foreign key references by executing an appropriate query. An example is given here:

    - + books = author.fetchChildren(FK_BOOK_AUTHOR);]]>

    Tables without a PRIMARY KEY are considered non-updatable by jOOQ, as jOOQ has no way of uniquely identifying such a record within the database. If you're using jOOQ's , such tables will generate classes, instead of classes. When you fetch from such a table, the returned records will not allow for calling any of the methods.

    - +

    Note, that some databases use internal rowid or object-id values to identify such records. jOOQ does not support these vendor-specific record meta-data.

    @@ -12085,7 +12085,7 @@ Result books = author.fetchChildren(FK_BOOK_AUTHOR);]]>
    - +

    Optimised optimistic locking using TIMESTAMP fields

    If you're using jOOQ's , you can take indicate TIMESTAMP or UPDATE COUNTER fields for every generated table in the . Let's say we have this table:

    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:

    - +

    As before, without the added TIMESTAMP column, optimistic locking is transparent to the API.

    - +

    Optimised optimistic locking using VERSION fields

    Instead of using TIMESTAMPs, you may also use numeric VERSION fields, containing version numbers that are incremented by jOOQ upon store() calls. @@ -12154,7 +12154,7 @@ book2.store();]]>

    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:

    - + books = create.fetch(BOOK); @@ -12170,7 +12170,7 @@ create.batchStore(books);]]>

    - +
    CRUD SPI: RecordListener @@ -12181,11 +12181,11 @@ create.batchStore(books);]]>
  • Adding a central ID generation algorithm, generating UUIDs for all of your records.
  • Adding a central record initialisation mechanism, preparing the database prior to inserting a new record.
  • - +

    An example of such a RecordListener is given here:

    - + - +

    Now, configure jOOQ's runtime to load your listener

    @@ -12225,7 +12225,7 @@ DSLContext create = DSL.using(configuration);]]>

    If you're using jOOQ's , you can configure it to generate and DAOs for you. jOOQ then generates one DAO per , i.e. per table with a single-column primary key. Generated DAOs implement a common jOOQ type called . This type contains the following methods:

    - + corresponds to the DAO's related table //

    corresponds to the DAO's related generated POJO type // corresponds to the DAO's related table's primary key type. @@ -12236,23 +12236,23 @@ public interface DAO, P, T> { void insert(P object) throws DataAccessException; void insert(P... objects) throws DataAccessException; void insert(Collection

    objects) throws DataAccessException; - + // These methods allow for updating POJOs based on their primary key void update(P object) throws DataAccessException; void update(P... objects) throws DataAccessException; void update(Collection

    objects) throws DataAccessException; - + // These methods allow for deleting POJOs based on their primary key void delete(P... objects) throws DataAccessException; void delete(Collection

    objects) throws DataAccessException; void deleteById(T... ids) throws DataAccessException; void deleteById(Collection ids) throws DataAccessException; - + // These methods allow for checking record existence boolean exists(P object) throws DataAccessException; boolean existsById(T id) throws DataAccessException; long count() throws DataAccessException; - + // These methods allow for retrieving POJOs by primary key or by some other field List

    findAll() throws DataAccessException; P findById(T id) throws DataAccessException; @@ -12281,7 +12281,7 @@ public class BookDao extends DAOImpl {

    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:

    - +

    Note how the lambda expression receives a new, derived configuration that should be used within the local scope:

    - + { // Wrap configuration in a new DSLContext: DSL.using(configuration).insertInto(...); DSL.using(configuration).insertInto(...); - + // Or, reuse the new DSLContext within the transaction scope: DSLContext ctx = DSL.using(configuration); ctx.insertInto(...); ctx.insertInto(...); - + // ... but avoid using the scope from outside the transaction: create.insertInto(...); create.insertInto(...); }); ]]> - +

    - While some implementations (e.g. ones based on ThreadLocals, e.g. Spring or JTA) may allow you to reuse the globally scoped reference, the jOOQ transaction API design allows for TransactionProvider implementations that require your transactional code to use the new, locally scoped Configuration, instead. + While some implementations (e.g. ones based on ThreadLocals, e.g. Spring or JTA) may allow you to reuse the globally scoped reference, the jOOQ transaction API design allows for TransactionProvider implementations that require your transactional code to use the new, locally scoped Configuration, instead.

    @@ -12502,7 +12502,7 @@ class SpringTransaction implements Transaction {

    With jOOQ, it's simple. All of jOOQ's exceptions are "system exceptions", hence they are all unchecked.

    - +

    jOOQ's DataAccessException

    jOOQ uses its own to wrap any underlying that might have occurred. Note that all methods in jOOQ that may cause such a DataAccessException document this both in the Javadoc as well as in their method signature. @@ -12518,7 +12518,7 @@ class SpringTransaction implements Transaction {

  • InvalidResultException: An operation was performed expecting only one result, but several results were returned.
  • MappingException: Something went wrong when loading a record from a or when mapping a record into a POJO
  • - +

    Override jOOQ's exception handling

    The following section about documents means of overriding jOOQ's exception handling, if you wish to deal separately with some types of constraint violations, or if you raise business errors from your database, etc. @@ -12535,7 +12535,7 @@ class SpringTransaction implements Transaction {

    For convenience and better backwards-compatibility, consider extending instead of implementing this interface.

    - +

    Example: Query statistics ExecuteListener

    Here is a sample implementation of an ExecuteListener, that is simply counting the number of queries per type that are being executed using jOOQ: @@ -12552,11 +12552,11 @@ public class StatisticsListener extends DefaultExecuteListener { public void start(ExecuteContext ctx) { synchronized (STATISTICS) { Integer count = STATISTICS.get(ctx.type()); - + if (count == null) { count = 0; } - + STATISTICS.put(ctx.type(), count + 1); } } @@ -12599,7 +12599,7 @@ for (ExecuteType type : ExecuteType.values()) {

    Please read the for more details

    - +

    Example: Custom Logging ExecuteListener

    The following depicts an example of a custom ExecuteListener, which pretty-prints all queries being executed by jOOQ to stdout: @@ -12622,7 +12622,7 @@ public class PrettyPrinter extends DefaultExecuteListener { // Create a new DSLContext for logging rendering purposes // This DSLContext doesn't need a connection, only the SQLDialect... DSLContext create = DSL.using(ctx.dialect(), - + // ... and the flag for pretty-printing new Settings().withRenderFormatted(true)); @@ -12630,12 +12630,12 @@ public class PrettyPrinter extends DefaultExecuteListener { if (ctx.query() != null) { System.out.println(create.renderInlined(ctx.query())); } - + // If we're executing a routine else if (ctx.routine() != null) { System.out.println(create.renderInlined(ctx.routine())); } - + // If we're executing anything else (e.g. plain SQL) else if (!StringUtils.isBlank(ctx.sql())) { System.out.println(ctx.sql()); @@ -12645,12 +12645,12 @@ public class PrettyPrinter extends DefaultExecuteListener {

    See also the manual's sections about for more sample implementations of actual ExecuteListeners.

    - +

    Example: Bad query execution ExecuteListener

    You can also use ExecuteListeners to interact with your SQL statements, for instance when you want to check if executed or statements contain a WHERE clause. This can be achieved trivially with the following sample ExecuteListener:

    - + 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:

    - + @@ -12702,7 +12702,7 @@ public class DeleteOrUpdateWithoutWhereException extends RuntimeException {}

    With the above configuration, let's fetch some data with jOOQ

    - +

    @@ -12750,14 +12750,14 @@ Finishing : Total: 4.814ms, +3.375ms

  • 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
  • - +

    Optimise wisely

    Don't be put off by the above paragraphs. You should optimise wisely, i.e. only in places where you really need very high throughput to your database. jOOQ's overhead compared to plain JDBC is typically less than 1ms per query.

    - +
    Alternative execution models @@ -12767,7 +12767,7 @@ Finishing : Total: 4.814ms, +3.375ms

    - +
    Using jOOQ with JPA @@ -12776,11 +12776,11 @@ Finishing : Total: 4.814ms, +3.375ms

    These sections will show how to use jOOQ with JPA's native query API in order to fetch tuples or managed entities using the Java EE standards.

    - +

    In all of the following sections, let's assume we have the following JPA entities to model our database:

    - + - +
    Using jOOQ with JPA Native Query @@ -12884,7 +12884,7 @@ nativeQuery(em, DSL.using(configuration) books.forEach((Object[] book) -> System.out.println(book[0] + " " + book[1] + " wrote " + book[2]));]]>
    - +
    Using jOOQ with JPA entities @@ -12892,7 +12892,7 @@ books.forEach((Object[] book) -> System.out.println(book[0] + " " + book[1] + "

    The simplest way to fetch entities via the native query API is by passing the entity class along to the native query method. The following example maps jOOQ query results to JPA entities (). Just add the following utility method:

    - + List nativeQuery(EntityManager em, org.jooq.Query query, Class type) { // Extract the SQL statement from the jOOQ query: @@ -12934,7 +12934,7 @@ static Object convertToDatabaseType(Param param) {

    With the above simple API, we're ready to write complex jOOQ queries and map their results to JPA entities:

    - + authors = nativeQuery(em, DSL.using(configuration) @@ -12945,14 +12945,14 @@ nativeQuery(em, authors.forEach(author -> { System.out.println(author.firstName + " " + author.lastName + " wrote"); - + books.forEach(book -> { System.out.println(" " + book.title); }); });]]>
    - +
    Using jOOQ with JPA EntityResult @@ -12960,11 +12960,11 @@ authors.forEach(author -> {

    While JPA specifies how the mapping should be implemented (e.g. using ), there are no limitations regarding how you want to generate the SQL statement. The following, simple example shows how you can produce JPABook and JPAAuthor entities () from a jOOQ-generated SQL statement.

    - +

    In order to do so, we'll need to specify the . This can be done on any entity, and in this case, we're using :

    - + { } ) } -)]]> - +)]]> +

    Note how we need to map between:

    @@ -12994,11 +12994,11 @@ authors.forEach(author -> {
  • , which corresponds to the entity's attribute name
  • , which corresponds to the SQL result's column name
  • - +

    With the above boilerplate in place, we can now fetch entities using jOOQ and JPA:

    - + List nativeQuery(EntityManager em, org.jooq.Query query, String resultSetMapping) { // Extract the SQL statement from the jOOQ query: @@ -13016,7 +13016,7 @@ authors.forEach(author -> {

    Note, if you're using or , make sure to take those into account as well. E.g. as follows:

    - + List nativeQuery(EntityManager em, org.jooq.Query query, String resultSetMapping) { // Extract the SQL statement from the jOOQ query: @@ -13037,11 +13037,11 @@ static Object convertToDatabaseType(Param param) { }]]>

    Using the above API

    - +

    Now that we have everything setup, we can use the above API to run a jOOQ query to fetch JPA entities like this:

    - + result = nativeQuery(em, DSL.using(configuration @@ -13055,7 +13055,7 @@ nativeQuery(em, ) .from(AUTHOR) .join(BOOK).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) - .orderBy(BOOK.ID)), + .orderBy(BOOK.ID)), "bookmapping" // The name of the SqlResultSetMapping ); @@ -13064,11 +13064,11 @@ result.forEach((Object[] entities) -> { JPABook book = (JPABook) entities[0]; System.out.println(author.firstName + " " + author.lastName + " wrote " + book.title); -});]]> +});]]>

    The entities are now ready to be modified and persisted again.

    - +

    Caveats:

    @@ -13080,7 +13080,7 @@ result.forEach((Object[] entities) -> {
    -
    +
    @@ -13134,7 +13134,7 @@ result.forEach((Object[] entities) -> {

    You need to tell jOOQ some things about your database connection. Here's an example of how to do it for an Oracle database

    - + @@ -13143,7 +13143,7 @@ result.forEach((Object[] entities) -> { jdbc:oracle:thin:@[your jdbc connection parameters] [your database user] [your database password] - + user[db-user] @@ -13155,9 +13155,9 @@ result.forEach((Object[] entities) -> { org.jooq.util.oracle.OracleDatabase @@ -13191,9 +13191,9 @@ result.forEach((Object[] entities) -> { Use the pipe to separate several expressions) Watch out for case-sensitivity. Depending on your database, this might be important! - + You can create case-insensitive regular expressions using this syntax: (?i:expr) - + Whitespace is ignored and comments are possible. --> .* @@ -13224,7 +13224,7 @@ result.forEach((Object[] entities) -> { @@ -13245,13 +13245,13 @@ result.forEach((Object[] entities) -> {

    Code generation works by calling this class with the above property file as argument.

    - + org.jooq.util.GenerationTool /jooq-config.xml

    Be sure that these elements are located on the classpath:

    - +
    • The XML configuration file
    • jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar
    • @@ -13276,7 +13276,7 @@ result.forEach((Object[] entities) -> {
    • this example uses jOOQ's log4j support by adding log4j.xml and log4j.jar to the project classpath.
    • the actual jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar artefacts may contain version numbers in the file names.
    - +
    Eclipse configuration
    @@ -13318,11 +13318,11 @@ result.forEach((Object[] entities) -> { org.jooq jooq-codegen-maven @@ -13441,9 +13441,9 @@ result.forEach((Object[] entities) -> { false @@ -13456,7 +13456,7 @@ result.forEach((Object[] entities) -> { production schema. Use this to override your local development schema name for source code generation. If not specified, this will be the same as the input-schema. - + This will be ignored if outputSchemaToDefault is set to true --> [your database schema / owner / name] @@ -13568,33 +13568,33 @@ result.forEach((Object[] entities) -> { Defaults to false --> false - false - + true - + false ]]>
    @@ -13603,7 +13603,7 @@ result.forEach((Object[] entities) -> {

    Some of the above properties depend on other properties to work correctly. For instance, when generating immutable pojos, pojos must be generated. jOOQ will enforce such properties even if you tell it otherwise. Here is a list of property interdependencies:

    - +
    • When daos = true, then jOOQ will set relations = true
    • When daos = true, then jOOQ will set records = true
    • @@ -13612,7 +13612,7 @@ result.forEach((Object[] entities) -> {
    - +
    Programmatic generator configuration @@ -13620,7 +13620,7 @@ result.forEach((Object[] entities) -> {

    In the previous sections, we have covered how to set up jOOQ's code generator using XML, either by running a standalone Java application, or by using Maven. However, it is also possible to use jOOQ's GenerationTool programmatically. The XSD file used for the configuration (http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd) is processed using XJC to produce Java artefacts. The below example uses those artefacts to produce the equivalent configuration of the previous :

    - +

    For the above example, you will need all of jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, and jooq-codegen-{jooq-version}.jar, on your classpath.

    - +

    Manually loading the XML file

    - +

    Alternatively, you can also load parts of the configuration from an XML file using JAXB and programmatically modify other parts using the code generation API:

    - + org.h2.Driver ]]> - +

    Load the above using standard JAXB API:

    - +

    - +
    Custom generator strategies @@ -13693,7 +13693,7 @@ GeberationTool.generate(configuration);]]>

    jOOQ allows you to override default implementations of the code generator or the generator strategy. Specifically, the latter can be very useful if you want to inject custom behaviour into jOOQ's code generator with respect to naming classes, members, methods, and other Java objects.

    - + @@ -13923,58 +13923,58 @@ public class Book implements java.io.Serializable { - + MY_SCHEMA - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - +
    - + MY_TABLE - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomBaseClass com.example.MyOptionalCustomInterface
    - + - + MY_FIELD - + --> MatcherRule --> MatcherRule @@ -13982,30 +13982,30 @@ public class Book implements java.io.Serializable { --> MatcherRule - + - + MY_ROUTINE - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + - + MY_SEQUENCE - + --> MatcherRule @@ -14021,19 +14021,19 @@ public class Book implements java.io.Serializable { CAMEL - + PREFIX_$0_SUFFIX ]]> - +

    Some examples

    The following example shows a matcher strategy that adds a "T_" prefix to all table classes and to table identifiers: @@ -14044,7 +14044,7 @@ public class Book implements java.io.Serializable { - + UPPER @@ -14079,13 +14079,13 @@ public class Book implements java.io.Serializable { ]]> - +

    For more information about each XML tag, please refer to the http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd XSD file.

    - +
    Custom code sections @@ -14132,7 +14132,7 @@ public class Book implements java.io.Serializable {

    Any of the below methods can be overridden:

    - + Tables.java: This file contains all table objects in the form of static member references to the actual singleton object
  • UDTs.java: This file contains all UDT objects in the form of static member references to the actual singleton object
  • - +

    Referencing global artefacts

    When referencing global artefacts from your client application, you would typically static import them as such:

    - + @@ -14228,7 +14228,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate a implementation that looks like this:

    - + { // The singleton instance @@ -14244,7 +14244,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE) public Book as(java.lang.String alias) { return new Book(alias); } - + // [...] }]]> @@ -14263,7 +14263,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)
  • instanceFields: This flag controls the "static" keyword on table columns, as well as aliasing convenience
  • records: The generated record type is referenced from tables allowing for type-safe single-table record fetching
  • - +

    Flags controlling table generation

    Table generation cannot be deactivated @@ -14277,7 +14277,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate an implementation that looks like this:

    - + - +

    Flags influencing generated records

    These flags from the influence generated records: @@ -14335,7 +14335,7 @@ implements IBook {

  • interfaces: If interfaces are generated, records will implement them
  • jpaAnnotations: JPA annotations are used on generated records
  • - +

    Flags controlling record generation

    Record generation can be deactivated using the records flag @@ -14349,7 +14349,7 @@ implements IBook {

    Every table in your database will generate a POJO implementation that looks like this:

    - + - +

    Flags influencing generated POJOs

    These flags from the influence generated POJOs: @@ -14398,7 +14398,7 @@ public class Book implements java.io.Serializable

  • jpaAnnotations: JPA annotations are used on generated records
  • validationAnnotations: JSR-303 validation annotations are used on generated records
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the pojos flag @@ -14412,16 +14412,16 @@ public class Book implements java.io.Serializable

    Every table in your database will generate an interface that looks like this:

    - + - +

    Flags influencing generated interfaces

    These flags from the influence generated interfaces: @@ -14430,7 +14430,7 @@ public class Book implements java.io.Serializable

  • dateAsTimestamp: This influences all relevant getters and setters
  • unsignedTypes: This influences all relevant getters and setters
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the interfaces flag @@ -14445,7 +14445,7 @@ public class Book implements java.io.Serializable

    Every table in your database will generate a implementation that looks like this:

    - + { // Generated constructors @@ -14469,10 +14469,10 @@ public class Book implements java.io.Serializable public List fetchByAuthorId(Integer... values) { return fetch(BOOK.AUTHOR_ID, values); } - + // [...] }]]> - +

    Flags controlling DAO generation

    DAO generation can be activated using the daos flag @@ -14486,13 +14486,13 @@ public class Book implements java.io.Serializable

    Every sequence in your database will generate a implementation that looks like this:

    - + S_AUTHOR_ID = new SequenceImpl("S_AUTHOR_ID", TEST, SQLDataType.INTEGER); }]]> - +

    Flags controlling sequence generation

    Sequence generation cannot be deactivated @@ -14530,7 +14530,7 @@ public class Book implements java.io.Serializable public BigDecimal getResult() { return getValue(RESULT); } - + // [...] }]]> @@ -14552,7 +14552,7 @@ public class Book implements java.io.Serializable

    Every UDT in your database will generate a implementation that looks like this:

    - + { // The singleton UDT instance @@ -14565,10 +14565,10 @@ public class Book implements java.io.Serializable createField("CITY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); public static final UDTField COUNTRY = createField("COUNTRY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); - + // [...] }]]> - +

    Besides the implementation, a implementation is also generated

    @@ -14583,7 +14583,7 @@ public class Book implements java.io.Serializable public String getCity() {...} public void setCountry(String value) {...} public String getCountry() {...} - + // [...] }]]>
    @@ -14612,20 +14612,20 @@ public class Book implements java.io.Serializable BOOLEAN .*\.IS_VALID - + .* @@ -14649,7 +14649,7 @@ public class Book implements java.io.Serializable

    When using a custom type in jOOQ, you need to let jOOQ know about its associated . Ad-hoc usages of such converters has been discussed in the chapter about . However, when mapping a custom type onto a standard JDBC type, a more common use-case is to let jOOQ know about custom types at code generation time (if you're using non-standard JDBC types, like for example JSON or HSTORE, see the ). Use the following configuration elements to specify, that you'd like to use GregorianCalendar for all database fields that start with DATE_OF_

    - +

    There's a simple configuration using only <forcedTypes/> configuration elements, and an advanced configuration using both <forcedTypes/> and <customTypes/> elements, which allow for greater reuse.

    @@ -14665,29 +14665,29 @@ public class Book implements java.io.Serializable - + java.util.GregorianCalendar com.example.CalendarConverter - + .*\.DATE_OF_.* - + .* @@ -14697,7 +14697,7 @@ public class Book implements java.io.Serializable

    Advanced configuration

    - The advanced configuration allows for specifying <customTypes/>, which can be used to reuse configuration elements for user type / converter / binding combinations by giving them a name: + The advanced configuration allows for specifying <customTypes/>, which can be used to reuse configuration elements for user type / converter / binding combinations by giving them a name:

    @@ -14706,7 +14706,7 @@ public class Book implements java.io.Serializable GregorianCalendar - + java.util.GregorianCalendar @@ -14722,21 +14722,21 @@ public class Book implements java.io.Serializable GregorianCalendar .*\.DATE_OF_.* - + .* @@ -14770,15 +14770,15 @@ create.selectFrom(AUTHOR)
    - - + +
    Custom data type binding

    The previous section discussed the case where your custom data type is mapped onto a standard JDBC type as contained in . In some cases, however, you want to map your own type onto a type that is not explicitly supported by JDBC, such as for instance, PostgreSQL's various advanced data types like JSON or HSTORE, or PostGIS types. For this, you can register an for relevant columns in your code generator. Consider the following trivial implementation of a binding for PostgreSQL's JSON data type, which binds the JSON string in PostgreSQL to a Google GSON object:

    - + {

    The above implementation intercepts all the interaction on a JDBC level, such that jOOQ will never need to know how to crrectly serialise / deserialise your custom data type. Similar to what we've seen in the previous section about , we can now register such a binding to the code generator. Note that you will reuse the same types of XML elements (<customType/> and <forcedType/>):

    - + @@ -14878,26 +14878,26 @@ public class PostgresJSONGsonBinding implements Binding { com.example.PostgresJSONGsonBinding .*JSON.* - + .* -]]> +]]>

    See also the section about to learn about an alternative use of <forcedTypes/>. @@ -14917,7 +14917,7 @@ public class PostgresJSONGsonBinding implements Binding {

    - +
    Mapping generated schemata and tables @@ -14938,23 +14938,23 @@ public class PostgresJSONGsonBinding implements Binding {
    - +
    Code generation for large schemas

    Databases can become very large in real-world applications. This is not a problem for jOOQ's code generator, but it can be for the Java compiler. jOOQ generates some classes for . These classes can hit two sorts of limits of the compiler / JVM:

    - +
    • Methods (including static / instance initialisers) are allowed to contain only 64kb of bytecode.
    • Classes are allowed to contain at most 64k of constant literals
    - +

    While there exist workarounds for the above two limitations (delegating initialisations to nested classes, inheriting constant literals from implemented interfaces), the preferred approach is either one of these:

    - +
    • Distribute your database objects in several schemas. That is probably a good idea anyway for such large databases
    • to exclude excess database objects
    • @@ -15029,7 +15029,7 @@ public class PostgresJSONGsonBinding implements Binding {

      In such a setup, you might have a pre-existing schema implemented using JPA-annotated entities. Your real database schema might not be accessible while developing, or it is not a first-class citizen in your application (i.e. you follow a Java-first approach). This section explains how you can generate jOOQ classes from such a JPA model. Consider this model:

      - + org.jooq jooq-meta-extensions @@ -15087,7 +15087,7 @@ public class Book {

      With that dependency in place, you can now specify the JPADatabase in your code generator configuration:

      - + org.jooq.util.jpa.JPADatabase @@ -15106,7 +15106,7 @@ public class Book {

    - +
    Generating code from XML files @@ -15122,7 +15122,7 @@ public class Book {

    An example schema definition containing simple schema, table, column definitions can be seen below:

    - + @@ -15183,7 +15183,7 @@ public class Book { ... - + TEST @@ -15198,18 +15198,18 @@ public class Book {

    The above file can be made available to the code generator configuration by using the XMLDatabase as follows:

    - + org.jooq.util.xml.XMLDatabase - + dialect ORACLE - + xml-file @@ -15220,16 +15220,16 @@ public class Book { ]]>

    - If you already have a different XML format for your database, you can either XSL transform your own format into the one above via an additional Maven plugin, or pass the location of an XSL file to the XMLDatabase by providing an additional property: + If you already have a different XML format for your database, you can either XSL transform your own format into the one above via an additional Maven plugin, or pass the location of an XSL file to the XMLDatabase by providing an additional property:

    - + org.jooq.util.xml.XMLDatabase - + ... - + xsl-file @@ -15240,7 +15240,7 @@ public class Book { ]]>

    - This XML configuration can now be checked in and versioned, and modified independently from your live database schema. + This XML configuration can now be checked in and versioned, and modified independently from your live database schema.

    @@ -15255,14 +15255,14 @@ public class Book { - - + ]]> @@ -15281,7 +15281,7 @@ public class Book { generate-sources - @@ -15293,20 +15293,20 @@ public class Book { - + - org.jooq + org.jooq.trial jooq-codegen {jooq-version} @@ -15314,7 +15314,7 @@ public class Book { ]]> - +
    Running the code generator with Gradle @@ -15322,7 +15322,7 @@ public class Book {

    We recommend using the Gradle plugin by Etienne Studer (from Gradle Inc.). It provides a concise DSL that allows you to tune all configuration properties supported by each jOOQ version. Please direct any support questions or issues you may find directly to the third party plugin vendor.

    - +

    Alternatively, the XML MarkupBuilder can be used

    If you don't want to use the above third party plugin, there's also the possibility to use jOOQ's standalone code generator for simplicity. The following working example build.gradle script should work out of the box: @@ -15416,11 +15416,11 @@ org.jooq.util.GenerationTool.generate(

    When writing unit tests for your data access layer, you have probably used some generic mocking tool offered by popular providers like Mockito, jmock, mockrunner, or even DBUnit. With jOOQ, you can take advantage of the built-in JDBC mock API that allows you to emulate a simple database on the JDBC level for precisely those SQL/JDBC use cases supported by jOOQ.

    - +

    - Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider. + Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider.

    - +

    Mocking the JDBC API

    JDBC is a very complex API. It takes a lot of time to write a useful and correct mock implementation, implementing at least these interfaces: @@ -15433,16 +15433,16 @@ org.jooq.util.GenerationTool.generate(

  • - +

    Optionally, you may even want to implement interfaces, such as , , , and many others. In addition to the above, you might need to find a way to simultaneously support incompatible JDBC minor versions, such as 4.0, 4.1

    - +

    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 :

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    As you can see, the configuration setup is simple. Now, the MockDataProvider acts as your single point of contact with JDBC / jOOQ. It unifies any of these execution modes, transparently:

    - +
    • Statements without results
    • Statements without results but with generated keys
    • @@ -15465,16 +15465,16 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
    • Batch statements with single queries and multiple bind value sets
    • Batch statements with multiple queries and no bind values
    - +

    The above are the execution modes supported by jOOQ. Whether you're using any of jOOQ's various fetching modes (e.g. , , , ) is irrelevant, as those modes are all built on top of the standard JDBC API.

    - +

    Implementing MockDataProvider

    Now, here's how to implement MockDataProvider:

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc // 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 String sql = ctx.sql(); - + // Exceptions are propagated through the JDBC and jOOQ APIs if (sql.toUpperCase().startsWith("DROP")) { throw new SQLException("Statement not supported: " + sql); } - + // You decide, whether any given statement returns results, and how many else if (sql.toUpperCase().startsWith("SELECT")) { - + // Always return one author record Result result = create.newResult(AUTHOR); result.add(create.newRecord(AUTHOR)); @@ -15502,12 +15502,12 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc result.get(0).setValue(AUTHOR.LAST_NAME, "Orwell"); mock[0] = new MockResult(1, result); } - + // You can detect batch statements easily else if (ctx.batch()) { // [...] } - + return mock; } }]]> @@ -15519,17 +15519,17 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • : The number of affected rows
  • : The result set
  • - +

    You should return as many MockResult objects as there were query executions (in ) or results (in ). Instead of an awkward JDBC ResultSet, however, you can construct a "friendlier" with your own record types. The jOOQ mock API will use meta data provided with this Result in order to create the necessary JDBC

    - +

    See the for a list of rules that you should follow.

    - +
    SQL 2 jOOQ Parser @@ -15539,20 +15539,20 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    Gudu Software Ltd has been selling enterprise quality SQL software to hundreds of customers to help them migrate from one database to another using the General SQL Parser. Now you can take advantage of their knowledge to parse your SQL statements and transform them directly into jOOQ statements using a free trial version of SQL 2 jOOQ!

    - +

    It's as simple as this!

    - +
    • Create a JDBC connection
    • Create a new SQL2jOOQ converter object
    • Convert your SQL code
    • Get the result
    - +

    See it in action:

    - + If all goes well, the above program yields:

    - + > result = create.select( Actor.ACTOR.FIRST_NAME, Actor.ACTOR.LAST_NAME ) @@ -15616,21 +15616,21 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    Please take note of the fact that the sql2jooq library is Open Source, but it depends on the commercial gsp.jar parser, whose trial licensing terms can be seen here:

    - +

    https://github.com/sqlparser/sql2jooq/blob/master/sql2jooq/LICENSE-GSQLPARSER.txt

    - +

    For more information about the General SQL Parser, please refer to the product blog.

    - +

    Please report any issues, ideas, wishes to the jOOQ user group or the sql2jooq GitHub project.

    - +
    jOOQ Console @@ -15679,7 +15679,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • Sybase Adaptive Server Enterprise 15.5
  • Sybase SQL Anywhere 12
  • - +

    For an up-to-date list of currently supported RDBMS, please refer to http://www.jooq.org/legal/licensing/#databases.

    @@ -15700,7 +15700,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME, This chapter should document the most important notes about SQL, JDBC and jOOQ data types.

    - +
    BLOBs and CLOBs @@ -15710,7 +15710,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    Unsigned integer types @@ -15734,7 +15734,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
    - +
    INTERVAL data types @@ -15745,11 +15745,11 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • YEAR TO MONTH: This interval type models a number of months and years
  • DAY TO SECOND: This interval type models a number of days, hours, minutes, seconds and milliseconds
  • - +

    Both interval types ship with a variant of subtypes, such as DAY TO HOUR, HOUR TO SECOND, etc. jOOQ models these types as Java objects extending : (where Number.intValue() corresponds to the absolute number of months) and (where Number.intValue() corresponds to the absolute number of milliseconds)

    - +

    Interval arithmetic

    In addition to the documented previously, interval arithmetic is also supported by jOOQ. Essentially, the following operations are supported: @@ -15764,7 +15764,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    XML data types @@ -15773,7 +15773,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    Geospacial data types @@ -15783,7 +15783,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    CURSOR data types @@ -15792,22 +15792,22 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    > cursor;]]> - +

    In fact, such a cursor will be fetched immediately by jOOQ and wrapped in an object.

    - +
    ARRAY and TABLE data types

    The SQL standard specifies ARRAY data types, that can be mapped to Java arrays as such:

    - + intArray;]]> - +

    The above array type is supported by these SQL dialects:

    @@ -15816,33 +15816,33 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • HSQLDB
  • Postgres
  • - +

    Oracle typed arrays

    Oracle has strongly-typed arrays and table types (as opposed to the previously seen anonymously typed arrays). These arrays are wrapped by types.

    - +
    Oracle DATE data type

    - Oracle's DATE data type does not conform to the SQL standard. It is really a TIMESTAMP(0), i.e. a TIMESTAMP with a fractional second precision of zero. The most appropriate JDBC type for Oracle DATE types is . + Oracle's DATE data type does not conform to the SQL standard. It is really a TIMESTAMP(0), i.e. a TIMESTAMP with a fractional second precision of zero. The most appropriate JDBC type for Oracle DATE types is .

    - +

    Performance implications

    - +

    When binding TIMESTAMP variables to SQL statements, instead of truncating such variables to DATE, the cost based optimiser may choose to widen the database column from DATE to TIMESTAMP using an Oracle INTERNAL_FUNCTION(), which prevents index usage. Details about this behaviour can be seen in this Stack Overflow question.

    - +

    Use a data type binding to work around this issue

    - +

    The best way to work around this issue is to implement a , which generates the CAST expression for every bind variable:

    - + ctx) throws SQLException { render.keyword("cast").sql('(') @@ -15851,15 +15851,15 @@ public final void sql(BindingSQLContext ctx) throws SQLException { }]]>

    Deprecated functionality

    - +

    Historic versions of jOOQ used to support a <dateAsTimestamp/> flag, which can be used with the out-of-the-box as a :

    - + true - + @@ -15872,7 +15872,7 @@ public final void sql(BindingSQLContext ctx) throws SQLException {

    For more information, please refer to . -

    +

    @@ -15884,12 +15884,12 @@ public final void sql(BindingSQLContext ctx) throws SQLException {

    jOOQ takes SQL as an external domain-specific language and maps it onto Java, creating an internal domain-specific language. Internal DSLs cannot 100% implement their external language counter parts, as they have to adhere to the syntax rules of their host or target language (i.e. Java). This section explains the various problems and workarounds encountered and implemented in jOOQ.

    - +

    SQL allows for "keywordless" syntax

    SQL syntax does not always need keywords to form expressions. The clause takes various argument assignments:

    - + UPDATE t SET a = 1, b = 2 update(t).set(a, 1).set(b, 2) @@ -15907,12 +15907,12 @@ public final void sql(BindingSQLContext ctx) throws SQLException {

    In this case, ROW is an actual (optional) SQL keyword, implemented by at least PostgreSQL.

    - +

    SQL contains "composed" keywords

    As most languages, SQL does not attribute any meaning to whitespace. However, whitespace is important when forming "composed" keywords, i.e. SQL clauses composed of several keywords. jOOQ follows standard Java method naming conventions to map SQL keywords (case-insensitive) to Java methods (case-sensitive, camel-cased). Some examples:

    - + GROUP BY ORDER BY @@ -15925,7 +15925,7 @@ whenMatchedThenUpdate()

    Future versions of jOOQ may use all-uppercased method names in addition to the camel-cased ones (to prevent collisions with Java keywords):

    - + GROUP BY ORDER BY @@ -15956,7 +15956,7 @@ WHEN_MATCHED_THEN_UPDATE()

    The above example omits THEN and END keywords in Java. Future versions of jOOQ may comprise a more complete DSL, including such keywords again though, to provide a more 1:1 match for the SQL language.

    - +

    SQL contains "superfluous" syntactic elements

    Some SQL constructs are hard to map to Java, but they are also not really necessary. SQL often expects syntactic parentheses where they wouldn't really be needed, or where they feel slightly inconsistent with the rest of the SQL language. @@ -15993,7 +15993,7 @@ WHEN_MATCHED_THEN_UPDATE()

    jOOQ replaces those keywords by "synonyms":

    - + CASE .. ELSE PIVOT .. FOR .. IN .. @@ -16021,7 +16021,7 @@ pivot(..).on(..).in(..)

    Most SQL operators have to be mapped to descriptive method names in Java, as Java does not allow operator overloading:

    - + , != @@ -16050,7 +16050,7 @@ set(a, b)

    This is less of a syntactic SQL feature than a semantic one. In SQL, objects can be referenced before (i.e. "lexicographically before") they are declared. This is particularly true for

    - + @@ -16061,7 +16061,7 @@ select(t.a).from(t)]]>

    A more sophisticated example are common table expressions (CTE), which are currently not supported by jOOQ:

    - + WITH t(a, b) AS ( SELECT 1, 2 FROM DUAL ) @@ -16073,7 +16073,7 @@ FROM t

    - +
    jOOQ's BNF pseudo-notation @@ -16082,7 +16082,7 @@ FROM t

    - +
    Quality Assurance @@ -16094,16 +16094,16 @@ FROM t
  • To add lots of type-safety to your inline SQL
  • To increase productivity when writing inline SQL using your favourite IDE's autocompletion capabilities
  • - +

    With jOOQ being in the core of your application, you want to be sure that you can trust jOOQ. That is why jOOQ is heavily unit and integration tested with a strong focus on integration tests:

    - +

    Unit tests

    Unit tests are performed against dummy JDBC interfaces using http://jmock.org/. These tests verify that various implementations render correct SQL and bind variables correctly.

    - +

    Integration tests

    This is the most important part of the jOOQ test suites. Some 1500 queries are currently run against a standard integration test database. Both the test database and the queries are translated into every one of the 14 supported SQL dialects to ensure that regressions are unlikely to be introduced into the code base. @@ -16114,17 +16114,17 @@ FROM t

    jOOQ integration tests run the weirdest and most unrealistic queries. As a side-effect of these extensive integration test suites, many corner-case bugs for JDBC drivers and/or open source databases have been discovered, feature requests submitted through jOOQ and reported mainly to CUBRID, Derby, H2, HSQLDB.

    - +

    Code generation tests

    For every one of the 14 supported integration test databases, source code is generated and the tiniest differences in generated source code can be discovered. In case of compilation errors in generated source code, new test tables/views/columns are added to avoid regressions in this field.

    - +

    API Usability tests and proofs of concept

    jOOQ is used in jOOQ-meta as a proof of concept. This includes complex queries such as the following Postgres query

    - + These rather complex queries show that the jOOQ API is fit for advanced SQL use-cases, compared to the rather simple, often unrealistic queries in the integration test suite.

    - +

    Clean API and implementation. Code is kept DRY

    As a general rule of thumb throughout the jOOQ code, everything is kept DRY. Some examples: @@ -16189,19 +16189,19 @@ for (Record record : create.select(

    - +
    Migrating to jOOQ 3.0

    This section is for all users of jOOQ 2.x who wish to upgrade to the next major release. In the next sub-sections, the most important changes are explained. Some code hints are also added to help you fix compilation errors.

    - +

    Type-safe row value expressions

    Support for has been added in jOOQ 2.6. In jOOQ 3.0, many API parts were thoroughly (but often incompatibly) changed, in order to provide you with even more type-safety.

    - +

    Here are some affected API parts:

    @@ -16211,11 +16211,11 @@ for (Record record : create.select(
  • IN predicates and comparison predicates taking subselects changed incompatibly
  • INSERT and MERGE statements now take typesafe VALUES() clauses
  • - +

    Some hints related to row value expressions:

    - + record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result> result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch(); @@ -16223,31 +16223,31 @@ Result> result = create.select(BOOK.TITLE, BOOK.ID).fro // But Record2 extends Record. You don't have to use the additional typesafety: Record record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch();]]> - +

    SelectQuery and SelectXXXStep are now generic

    In order to support type-safe row value expressions and type-safe Record[N] types, SelectQuery is now generic: SelectQuery<R>

    - +

    SimpleSelectQuery and SimpleSelectXXXStep API were removed

    The duplication of the SELECT API is no longer useful, now that SelectQuery and SelectXXXStep are generic.

    - +

    Factory was split into DSL (query building) and DSLContext (query execution)

    The pre-existing Factory class has been split into two parts:

    - +
    1. 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
    2. 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 renamed to DSLContext. An example:

    - + - +

    Quantified comparison predicates

    Field.equalAny(...) and similar methods have been removed in favour of Field.equal(any(...)). This greatly simplified the Field API. An example:

    - + > subselect = any(select(BOOK.ID).from(BOOK)); Condition condition = BOOK.ID.equal(subselect);]]> - +

    FieldProvider

    The FieldProvider marker interface was removed. Its methods still exist on FieldProvider subtypes. Note, they have changed names from getField() to field() and from getIndex() to indexOf()

    - +

    GroupField

    GroupField has been introduced as a DSL marker interface to denote fields that can be passed to GROUP BY clauses. This includes all org.jooq.Field types. However, fields obtained from ROLLUP(), CUBE(), and GROUPING SETS() functions no longer implement Field. Instead, they only implement GroupField. An example:

    - + field1a = Factory.rollup(...); // OK Field field2a = Factory.one(); // OK @@ -16293,19 +16293,19 @@ GroupField field1b = DSL.rollup(...); // OK Field field1c = DSL.rollup(...); // Compilation error GroupField field2b = DSL.one(); // OK Field field2c = DSL.one(); // OK]]> - +

    NULL predicate

    Beware! Previously, Field.equal(null) was translated internally to an IS NULL predicate. This is no longer the case. Binding Java "null" to a comparison predicate will result in a regular comparison predicate (which never returns true). This was changed for several reasons:

    - +
    • To most users, this was a surprising "feature".
    • Other predicates didn't behave in such a way, e.g. the IN predicate, the BETWEEN predicate, or the LIKE predicate.
    • Variable binding behaved unpredictably, as IS NULL predicates don't bind any variables.
    • The generated SQL depended on the possible combinations of bind values, which creates unnecessary hard-parses every time a new unique SQL statement is rendered.
    - +

    Here is an example how to check if a field has a given value, without applying SQL's ternary NULL logic:

    @@ -16318,7 +16318,7 @@ Condition condition1 = BOOK.TITLE.equal(possiblyNull); // jOOQ 3.0 Condition condition2 = BOOK.TITLE.equal(possiblyNull).or(BOOK.TITLE.isNull().and(val(possiblyNull).isNull())); Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    Configuration

    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 @@ -16332,7 +16332,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> In order to resolve confusion that used to arise because of different lifecycle durations, these types are now no longer formally connected through inheritance.

    - +

    ConnectionProvider

    In order to allow for simpler connection / data source management, jOOQ externalised connection handling in a new ConnectionProvider type. The previous two connection modes are maintained backwards-compatibly (JDBC standalone connection mode, pooled DataSource mode). Other connection modes can be injected using: @@ -16342,24 +16342,24 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    These are some side-effects of the above change

    - +
    • 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. This resolves many class loader issues that were encountered before. It also helps listener implementations control their lifecycles themselves.

    - +

    Data type API

    The data type API has been changed drastically in order to enable some new DataType-related features. These changes include: @@ -16369,16 +16369,16 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]>[SQLDialect]DataType and SQLDataType no longer implement DataType. They're mere constant containers

  • Various minor API changes have been done.
  • - +

    Object renames

    These objects have been moved / renamed:

    - +
    • jOOU: a library used to represent unsigned integer types was moved from org.jooq.util.unsigned to org.jooq.util.types (which already contained INTERVAL data types)
    - +

    Feature removals

    Here are some minor features that have been removed in jOOQ 3.0 @@ -16472,7 +16472,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> --> diff --git a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.9.xml b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.9.xml index fb21e71615..48424e3b12 100644 --- a/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.9.xml +++ b/jOOQ-manual/src/main/resources/org/jooq/web/manual-3.9.xml @@ -126,7 +126,7 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ's reason for being - compared to SQL / JDBC

    So why not just use SQL? @@ -149,14 +149,14 @@

    jOOQ has come to fill this gap.

    - +

    jOOQ is different

    SQL was never meant to be abstracted. To be confined in the narrow boundaries of heavy mappers, hiding the beauty and simplicity of relational data. SQL was never meant to be object-oriented. SQL was never meant to be anything other than... SQL!

    - + - +
    Getting started with jOOQ @@ -346,12 +346,12 @@ limitations under the License.

    This section helps you correctly interpret this manual in the context of jOOQ.

    - +

    Code blocks

    The following are code blocks:

    - + @@ -367,7 +367,7 @@ org.jooq.property=value]]>

    These are useful to provide examples in code. Often, with jOOQ, it is even more useful to compare SQL code with its corresponding Java/jOOQ code. When this is done, the blocks are aligned side-by-side, with SQL usually being on the left, and an equivalent jOOQ DSL query in Java usually being on the right:

    - + @@ -379,17 +379,17 @@ create.selectOne().fetch()]]>

    The contents of code blocks follow conventions, too. If nothing else is mentioned next to any given code block, then the following can be assumed:

    - - + + - +

    Your naming may differ, of course. For instance, you could name the "create" instance "db", instead.

    - +

    Execution

    - +

    When you're coding PL/SQL, T-SQL or some other procedural SQL language, SQL statements are always executed immediately at the semi-colon. This is not the case in jOOQ, because as an internal DSL, jOOQ can never be sure that your statement is complete until you call fetch() or execute(). The manual tries to apply fetch() and execute() as thoroughly as possible. If not, it is implied:

    @@ -429,7 +429,7 @@ create.update(T).set(T.V, 1).execute();]]>

    jOOQ allows to override runtime behaviour using . If nothing is specified, the default runtime settings are assumed.

    - +

    Sample database

    jOOQ query examples run against the sample database. See the manual's section about to learn more about the sample database. @@ -464,7 +464,7 @@ CREATE TABLE book ( title VARCHAR2(400) NOT NULL, published_in NUMBER(7) NOT NULL, language_id NUMBER(7) NOT NULL, - + CONSTRAINT fk_book_author FOREIGN KEY (author_id) REFERENCES author(id), CONSTRAINT fk_book_language FOREIGN KEY (language_id) REFERENCES language(id) ); @@ -477,7 +477,7 @@ CREATE TABLE book_to_book_store ( name VARCHAR2(400) NOT NULL, book_id INTEGER NOT NULL, stock INTEGER, - + PRIMARY KEY(name, book_id), CONSTRAINT fk_b2bs_book_store FOREIGN KEY (name) REFERENCES book_store (name) ON DELETE CASCADE, CONSTRAINT fk_b2bs_book FOREIGN KEY (book_id) REFERENCES book (id) ON DELETE CASCADE @@ -488,7 +488,7 @@ CREATE TABLE book_to_book_store (

    In addition to the above, you may assume the following sample data:

    - + Effectively, jOOQ was originally designed to replace any other database abstraction framework short of the ones handling connection pooling (and more sophisticated )

    - +

    Use jOOQ the way you prefer

    ... but open source is community-driven. And the community has shown various ways of using jOOQ that diverge from its original intent. Some use cases encountered are: @@ -547,7 +547,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]>Using jOOQ for SQL building and Spring Data for SQL execution

  • Using jOOQ without the to build the basis of a framework for dynamic SQL execution.
  • - +

    The following sections explain about various use cases for using jOOQ in your application.

    @@ -560,7 +560,7 @@ INSERT INTO book_to_book_store VALUES ('Buchhandlung im Volkshaus', 3, 1 );]]> This is the most simple of all use cases, allowing for construction of valid SQL for any database. In this use case, you will not use and probably not even . Instead, you'll use to wrap strings, literals and other user-defined objects into an object-oriented, type-safe AST modelling your SQL statements. An example is given here:

    - + - +

    The SQL string built with the jOOQ query DSL can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools (note that since jOOQ uses PreparedStatement by default, this will generate a bind variable for "1948". ).

    @@ -597,7 +597,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID)) .where(BOOK.PUBLISHED_IN.equal(1948)) .getSQL();]]> - +

    The SQL string that you can generate as such can then be executed using JDBC directly, using Spring's JdbcTemplate, using Apache DbUtils and many other tools.

    @@ -617,7 +617,7 @@ String sql = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    Instead of any tool mentioned in the previous chapters, you can also use jOOQ directly to execute your jOOQ-generated SQL statements. This will add a lot of convenience on top of the previously discussed API for typesafe SQL construction, when you can re-use the information from generated classes to fetch records and custom data types. An example is given here:

    - + > result = create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) @@ -671,10 +671,10 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { // Skip previously distinguished authors if ((int) author.getDistinguished() == 1) continue; - + // Check if the author has written more than 5 books if (author.fetchChildren(Keys.FK_BOOK_AUTHOR).size() > 5) { - + // Mark the author as a "distinguished" author author.setDistinguished(1); author.store(); @@ -691,7 +691,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {
    - +
    jOOQ for PROs @@ -729,7 +729,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { This manual section is intended for new users, to help them get a running application with jOOQ, quickly.

    - +
    Step 1: Preparation @@ -738,13 +738,13 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { If you haven't already downloaded it, download jOOQ:
    http://www.jooq.org/download

    - +

    Alternatively, you can create a Maven dependency to download jOOQ artefacts:

    - +

    Open Source Edition

    - + org.jooq jooq @@ -760,9 +760,9 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { jooq-codegen {jooq-version} ]]> - +

    Commercial Editions (Java 8+)

    - + org.jooq.pro @@ -779,9 +779,9 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { jooq-codegen {jooq-version} ]]> - +

    Commercial Editions (Java 6+)

    - + org.jooq.pro-java-6 @@ -798,22 +798,22 @@ for (AuthorRecord author : create.fetch(AUTHOR)) { jooq-codegen {jooq-version} ]]> - +

    Commercial Editions (Free Trial)

    - + - org.jooq + org.jooq.trial jooq {jooq-version} - org.jooq + org.jooq.trial jooq-meta {jooq-version} - org.jooq + org.jooq.trial jooq-codegen {jooq-version} ]]> @@ -821,7 +821,7 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    Note that only the jOOQ Open Source Edition is available from Maven Central. If you're using the jOOQ Professional Edition or the jOOQ Enterprise Edition, you will have to manually install jOOQ in your local Nexus, or in your local Maven cache. For more information, please refer to the licensing pages.

    - +

    Please refer to the manual's section about to learn how to use jOOQ's code generator with Maven.

    @@ -836,14 +836,14 @@ for (AuthorRecord author : create.fetch(AUTHOR)) {

    - +
    Step 2: Your database

    We're going to create a database called "library" and a corresponding "author" table. Connect to MySQL via your command line client and type the following:

    - + CREATE DATABASE `library`; USE `library`; @@ -857,7 +857,7 @@ CREATE TABLE `author` (
    - +
    Step 3: Code generation @@ -869,7 +869,7 @@ CREATE TABLE `author` (

    The easiest way to generate a schema is to copy the jOOQ jar files (there should be 3) and the MySQL Connector jar file to a temporary directory. Then, create a library.xml that looks like this:

    - + @@ -926,7 +926,7 @@ CREATE TABLE `author` (

    generator.target.directory - the directory to output to.

    - +

    Once you have the JAR files and library.xml in your temp directory, type this on a Windows machine:

    @@ -946,7 +946,7 @@ CREATE TABLE `author` (

    Note: jOOQ will try loading the library.xml from your classpath. This is also why there is a trailing period (.) on the classpath. If the file cannot be found on the classpath, jOOQ will look on the file system from the current working directory.

    - +

    Replace the filenames with your actual filenames. In this example, jOOQ {jooq-version} is being used. If everything has worked, you should see this in your console output:

    @@ -1008,17 +1008,17 @@ INFO: Packages fetched : 0 (0 included, 0 excluded) Nov 1, 2011 7:25:08 PM org.jooq.impl.JooqLogger info INFO: GENERATION FINISHED! : Total: 791.688ms, +9.143ms - +
    - +
    Step 4: Connect to your database

    Let's just write a vanilla main class in the project containing the generated classes:

    - +
    - +
    Step 5: Querying

    Let's add a simple query constructed with jOOQ's query DSL:

    - + result = create.select().from(AUTHOR).fetch();]]> @@ -1068,7 +1068,7 @@ Result result = create.select().from(AUTHOR).fetch();]]>

    - +
    Step 6: Iterating @@ -1087,7 +1087,7 @@ Result result = create.select().from(AUTHOR).fetch();]]>

    The full program should now look like this:

    - +
    - +
    Step 7: Explore! @@ -1183,7 +1183,7 @@ public class Main {
  • Another example using Spring and Guice for transaction management can be downloaded from GitHub.
  • Another, excellent tutorial by Petri Kainulainen can be found here.
  • - +

    Add the required Maven dependencies

    For this example, we'll create the following Maven dependencies @@ -1199,11 +1199,11 @@ public class Main { org.jooq jooq @@ -1269,7 +1269,7 @@ public class Main {

    The above dependencies are configured together using a Spring Beans configuration:

    - + - + - + @@ -1327,7 +1327,7 @@ public class Main { - + ]]> @@ -1378,7 +1378,7 @@ public class QueryTest {

    The following example shows how you can use Spring's TransactionManager to explicitly handle transactions:

    - +
    - +
    Using jOOQ with Flyway

    Flyway - Database Migrations Made EasyWhen performing database migrations, we at Data Geekery recommend using jOOQ with Flyway - Database Migrations Made Easy. In this chapter, we're going to look into a simple way to get started with the two frameworks.

    - +

    Philosophy

    - +

    There are a variety of ways how jOOQ and Flyway could interact with each other in various development setups. In this tutorial we're going to show just one variant of such framework team play - a variant that we find particularly compelling for most use cases.

    - +

    The general philosophy behind the following approach can be summarised as this:

    - +
    • 1. Database increment
    • 2. Database migration
    • 3. Code re-generation
    • 4. Development
    - +

    The four steps above can be repeated time and again, every time you need to modify something in your database. More concretely, let's consider:

    - +
    • 1. Database increment - You need a new column in your database, so you write the necessary DDL in a Flyway script
    • 2. Database migration - This Flyway script is now part of your deliverable, which you can share with all developers who can migrate their databases with it, the next time they check out your change
    • @@ -1524,23 +1524,23 @@ public class TransactionTest { ]]>

      0. Maven Project Configuration - Dependencies

      - +

      While jOOQ and Flyway could be used in standalone migration scripts, in this tutorial, we'll be using Maven for the standard project setup. You will also find the source code of this tutorial on GitHub at https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-flyway-example, and the full pom.xml file here.

      - +

      These are the dependencies that we're using in our Maven configuration:

      - + org.jooq jooq @@ -1618,11 +1618,11 @@ public class TransactionTest { org.jooq jooq-codegen-maven @@ -1879,14 +1879,14 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre;

    - +
    Using jOOQ with JAX-RS

    In some use-cases, having a lean, single-tier server-side architecture is desirable. Typically, such architectures expose a RESTful API implementing client code and the UI using something like AngularJS.

    - +

    In Java, the standard API for RESTful applications is JAX-RS, which is part of JEE 7, along with a standard JSON implementation. But you can use JAX-RS also outside of a JEE container. The following example shows how to set up a simple license server using these technologies:

    @@ -1899,9 +1899,9 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre;

    For the example, we'll use a PostgreSQL database.

    - +

    Creating the license server database

    - +

    We'll keep the example simple and use a LICENSE table to store all license keys and associated information, whereas a LOG_VERIFY table is used to log access to the license server. Here's the DDL:

    @@ -1913,7 +1913,7 @@ ALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre; LICENSEE TEXT NOT NULL, -- The e-mail address of the licensee LICENSE TEXT NOT NULL, -- The license key VERSION VARCHAR(50) NOT NULL DEFAULT '.*', -- The licensed version(s), a regular expression - + CONSTRAINT PK_LICENSE PRIMARY KEY (ID), CONSTRAINT UK_LICENSE UNIQUE (LICENSE) ); @@ -1926,7 +1926,7 @@ CREATE TABLE LICENSE_SERVER.LOG_VERIFY ( REQUEST_IP VARCHAR(50) NOT NULL, -- The request IP verifying the license VERSION VARCHAR(50) NOT NULL, -- The version that is being verified MATCH BOOLEAN NOT NULL, -- Whether the verification was successful - + CONSTRAINT PK_LOG_VERIFY PRIMARY KEY (ID) );]]> @@ -1948,13 +1948,13 @@ $$ LANGUAGE PLPGSQL;

    The actual algorithm might be using a secret salt to hash the function arguments. For the sake of a tutorial, a constant string will suffice.

    - +

    Setting up the project

    - +

    We're going to be setting up the

    - + 9966 - + org.jooq jooq-codegen-maven @@ -2027,14 +2027,14 @@ $$ LANGUAGE PLPGSQL; servlet-api 2.5 - + org.jooq jooq @@ -2056,13 +2056,13 @@ $$ LANGUAGE PLPGSQL;

    With the above setup, we're now pretty ready to start developing our license service as a JAX-RS service.

    - +

    The license service class

    - +

    Once we've run the , we can write the following service class:

    - + /license/verify checks if a given licensee has access to version using a license. * @@ -2122,7 +2122,7 @@ public class LicenseService { @Override public String run(DSLContext ctx) { String v = (version == null || version.equals("")) ? "" : version; - + // Use the jOOQ query DSL API to generate a log entry return ctx.insertInto(LOG_VERIFY) @@ -2143,10 +2143,10 @@ public class LicenseService { } }); } - + // [...] }]]> - +

    The INSERT INTO LOG_VERIFY query is actually rather interesting. In plain SQL, it would look like this:

    @@ -2175,7 +2175,7 @@ RETURNING MATCH;]]> .set(new DefaultConnectionProvider(c)) .set(SQLDialect.POSTGRES) .set(new Settings().withExecuteLogging(false))); - + return runnable.run(ctx); } catch (Exception e) { @@ -2184,13 +2184,13 @@ RETURNING MATCH;]]> return "Service Unavailable - Please contact support@datageekery.com for help"; } } - + private interface CtxRunnable { String run(DSLContext ctx); }]]>

    Configuring Spring and Jetty

    - +

    All we need now is to configure Spring...

    @@ -2248,7 +2248,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/sch

    Using the license server

    - +

    You can now use the license server at the following URLs

    @@ -2265,7 +2265,7 @@ http://localhost:8088/jooq-jax-rs-example/license/verify?mail=test@example.com&l

    Let's verify what happened, in the database:

    - + - +

    Downloading the complete example

    - +

    The complete example can be downloaded for free and under the terms of the Apache Software License 2.0 from here:
    https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-jax-rs-example @@ -2295,21 +2295,21 @@ select * from license_server.log_verify

    - +
    jOOQ and Java 8

    Java 8 has introduced a great set of enhancements, among which lambda expressions and the new Streams API. These new constructs align very well with jOOQ's fluent API as can be seen in the following examples:

    - +

    jOOQ and lambda expressions

    jOOQ's API is fully Java-8-ready, which basically means that it is a SAM (Single Abstract Method) type, which can be instanciated using a lambda expression. Consider this example:

    - + - +

    The above example shows how jOOQ's method can receive a lambda expression that implements to map from jOOQ to your custom types.

    - +

    jOOQ and the Streams API

    @@ -2370,7 +2370,7 @@ select * from license_server.log_verify // Just emit a CREATE TABLE statement System.out.println( "CREATE TABLE " + table + " ("); - + // Map each "Column" type into a String // containing the column specification, // and join them using comma and @@ -2381,15 +2381,15 @@ select * from license_server.log_verify " " + col.type) .collect(Collectors.joining(",\n")) ); - + System.out.println(");"); } );]]> - +

    The above example is explained more in depth in this blog post: http://blog.jooq.org/2014/04/11/java-8-friday-no-more-need-for-orms/. For more information about Java 8, consider these resources:

    - +
    - +
    jOOQ and Nashorn

    With Java 8 and the new built-in JavaScript engine Nashorn, a whole new ecosystem of software can finally make easy use of jOOQ in server-side JavaScript. A very simple example can be seen here:

    - +

    - More details about how to use jOOQ, JDBC, and SQL with Nashorn can be seen here. + More details about how to use jOOQ, JDBC, and SQL with Nashorn can be seen here.

    - +
    jOOQ and Scala @@ -2622,7 +2622,7 @@ print(
  • Type inference using "var" and "val" keywords
  • Lambda expressions and for-comprehension syntax for record iteration and data type conversion
  • - +

    But jOOQ also leverages other useful Scala features, such as

    @@ -2630,15 +2630,15 @@ print(
  • implicit defs for operator overloading
  • Scala Macros (soon to come)
  • - +

    All of the above heavily improve jOOQ's querying DSL API experience for Scala developers.

    - +

    A short example jOOQ application in Scala might look like this:

    - +
    - - + +
    jOOQ and Groovy @@ -2700,7 +2700,7 @@ object Test { //

    A short example jOOQ application in Groovy might look like this:

    - +
    - - + +
    jOOQ and Kotlin @@ -2751,7 +2751,7 @@ DSL.using(sql.connection)

    A short example jOOQ application in Kotlin might look like this:

    - + ) { properties.getProperty("db.url"), properties.getProperty("db.username"), properties.getProperty("db.password") - + // The below "use" method is an adapted version of the one in kotlin.io // See also: https://github.com/JetBrains/kotlin/pull/807 ).use { @@ -2792,11 +2792,11 @@ fun main(args: Array) {

    Note that Kotlin supports some means of operator overloading. For instance, a + b in Kotlin maps to a formal a.plus(b) method invocation, and jOOQ provides the required synonyms in its API to help you write such expressions.

    - +

    One particularly nice language feature is the fact that [square brackets] allow for accessing any object's contents via get() and set() methods. Instead of using the above value1(), value2(), and value3() methods, we could also iterate as such:

    - + ) { println("${it[BOOK.TITLE]} by ${it[AUTHOR.FIRST_NAME]} ${it[AUTHOR.LAST_NAME]}") // Notice: ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ }]]> - +

    A caveat of Kotlin operator overloading is the fact that operators such as == or >= map to a.equals(b), a.compareTo(b) == 0, a.compareTo(b) >= 0 respectively. This behaviour does not make sense in a fluent API such as jOOQ.

    - +
    jOOQ and NoSQL @@ -2829,7 +2829,7 @@ fun main(args: Array) {

    - +
    Dependencies @@ -2847,7 +2847,7 @@ fun main(args: Array) {
    - +
    Build your own @@ -2876,7 +2876,7 @@ fun main(args: Array) {
    - +
    jOOQ and backwards-compatibility @@ -2888,7 +2888,7 @@ fun main(args: Array) {
  • If a minor release includes backwards-compatible, API-relevant new features, [Y] is incremented by one and [Z] is reset to zero.
  • If a major release includes backwards-incompatible, API-relevant new features, [X] is incremented by one and [Y], [Z] are reset to zero.
  • - +

    jOOQ's understanding of backwards-compatibility

    Backwards-compatibility is important to jOOQ. You've chosen jOOQ as a strategic SQL engine and you don't want your SQL to break. That is why there is at most one major release per year, which changes only those parts of jOOQ's API and functionality, which were agreed upon on the user group. During the year, only minor releases are shipped, adding new features in a backwards-compatible way @@ -2901,15 +2901,15 @@ fun main(args: Array) {

  • Overloading methods for convenience
  • Changing the type hierarchy of interfaces
  • - +

    It becomes obvious that it would be impossible to add new language elements (e.g. new , new ) to the API without breaking any client code that actually implements those interfaces. Hence, the following rule should be observed:

    - +

    jOOQ's DSL interfaces should not be implemented by client code! Extend only those extension points that are explicitly documented as "extendable" (e.g. )

    - +

    jOOQ-codegen and jOOQ-meta

    While a reasonable amount of care is spent to maintain these two modules under the rules of semantic versioning, it may well be that minor releases introduce backwards-incompatible changes. This will be announced in the respective release notes and should be the exception. @@ -2937,7 +2937,7 @@ fun main(args: Array) { - +

    The query DSL type @@ -2968,7 +2968,7 @@ fun main(args: Array) { // ... which is in fact the same as: DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    DSL subclasses @@ -2987,7 +2987,7 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME));
    - + @@ -2996,14 +2996,14 @@ DSL.concat(DSL.trim(FIRST_NAME), DSL.trim(LAST_NAME)); - +
    The DSLContext class

    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.

    - +

    Fluent creation of a DSLContext object

    The DSLContext object can be created fluently from the : @@ -3018,7 +3018,7 @@ DSLContext create = DSL.using(connection, dialect);]]>

    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

    A Configuration can be supplied with these objects: @@ -3037,7 +3037,7 @@ DSLContext create = DSL.using(connection, dialect);]]> - +

    Wrapping a Configuration object, a DSLContext can construct , for later . An example is given here:

    @@ -3079,7 +3079,7 @@ DSL.using(connection, dialect) CONNECT BY clause to the query */ -@Support({ SQLDialect.CUBRID, SQLDialect.}) +@Support({ SQLDialect.CUBRID, SQLDialect.ORACLE }) SelectConnectByConditionStep connectBy(Condition condition);]]>

    @@ -3101,7 +3101,7 @@ SelectSelectStep select(Field... fields);]]>

    Nevertheless, the IS DISTINCT FROM predicate is supported by jOOQ in all dialects, as its semantics can be expressed with an equivalent . For more details, see the manual's section about the .

    - +

    jOOQ and the Oracle SQL dialect

    Oracle SQL is much more expressive than many other SQL dialects. It features many unique keywords, clauses and functions that are out of scope for the SQL standard. Some examples for this are @@ -3125,13 +3125,13 @@ SelectSelectStep select(Field... fields);]]>

    In jOOQ 3.1, the notion of a SQLDialect.family() was introduced, in order to group several similar into a common family. An example for this is SQL Server, which is supported by jOOQ in various versions:

    - +
    • : The "version-less" SQL Server version. This always maps to the latest supported version of SQL Server
    • : The SQL Server version 2012
    • : The SQL Server version 2008
    - +

    In the above list, SQLSERVER is both a dialect and a family of three dialects. This distinction is used internally by jOOQ to distinguish whether to use the clause (SQL Server 2012), or whether to emulate it using ROW_NUMBER() OVER() (SQL Server 2008).

    @@ -3148,7 +3148,7 @@ SelectSelectStep select(Field... fields);]]>

    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.

    - +

    Interact with JDBC DataSources

    If you're in a J2EE or Spring context, however, you may wish to use a instead. Connections obtained from such a DataSource will be closed after query execution by jOOQ. The semantics of such a close operation should be the returning of the connection into a connection pool, not the actual closing of the underlying connection. Typically, this makes sense in an environment using distributed JTA transactions. An example of using DataSources with jOOQ can be seen in the tutorial section about . @@ -3156,17 +3156,17 @@ SelectSelectStep select(Field... fields);]]>

    Note, in this case, jOOQ will internally use a , which you can reference directly if you prefer that.

    - +

    Inject custom behaviour

    If your specific environment works differently from any of the above approaches, you can inject your own custom implementation of a ConnectionProvider into jOOQ. This is the API contract you have to fulfil:

    - + @@ -3176,19 +3176,19 @@ 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...

    - +
    - +

    Here is an example of how to use the custom data API. Let's assume that you have written an , that prevents INSERT statements, when a given flag is set to true:

    @@ -3198,10 +3198,10 @@ public class NoInsertListener extends DefaultExecuteListener { @Override public void start(ExecuteContext ctx) { - + // This listener is active only, when your custom flag is set to true 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) { throw new DataAccessException("No INSERT statements allowed"); @@ -3212,11 +3212,11 @@ public class NoInsertListener extends DefaultExecuteListener {

    See the manual's section about to learn more about how to implement an ExecuteListener.

    - +

    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:

    - + ExecuteListeners are a useful tool to...

    - +
    • implement custom logging
    • apply triggers written in Java
    • collect query execution statistics
    - +

    ExecuteListeners are hooked into your by returning them from an :

    @@ -3274,7 +3274,7 @@ configuration.set( new DefaultExecuteListenerProvider(new PerformanceLoggingListener()), new DefaultExecuteListenerProvider(new NoInsertListener()) );]]>
    - +

    See the manual's section about to see examples of such listener implementations.

    @@ -3318,22 +3318,22 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - +

    All Settings

    - +

    This section of the manual explains all the available Settings flags as available from the XSD specification.

    - + false - + ... @@ -3344,17 +3344,17 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - UPPER_CASED : UPPER - lower_cased : LOWER - CasedAsReportedByTheDatabase : AS_IS - + Defaults to "QUOTED" --> LOWER UPPER - + false @@ -3362,54 +3362,54 @@ DSLContext create = DSL.using(connection, dialect, settings);]]> - question marks : INDEXED - named parameters : NAMED - inlined values : INLINED - + Defaults to "INDEXED". - + This value is overridden by statementType == STATIC_STATEMENT, in case of which, this defaults to INLINED --> INDEXED - + PREPARED_STATEMENT - + true false true false ]]> - +

    More details

    - +

    Please refer to the jOOQ runtime configuration XSD for more details:
    http://www.jooq.org/xsd/jooq-runtime-{runtime-xsd-version}.xsd

    - +
    Runtime schema and table mapping @@ -3417,7 +3417,7 @@ DSLContext create = DSL.using(connection, dialect, settings);]]>

    You may wish to design your database in a way that you have several instances of your schema. This is useful when you want to cleanly separate data belonging to several customers / organisation units / branches / users and put each of those entities' data in a separate database or schema.

    - +

    In our AUTHOR example this would mean that you provide a book reference database to several companies, such as My Book World and Books R Us. In that case, you'll probably have a schema setup like this:

    @@ -3447,7 +3447,7 @@ create.selectFrom(AUTHOR).fetch();

    The query executed with a Configuration equipped with the above mapping will in fact produce this SQL statement:

    - + SELECT * FROM MY_BOOK_WORLD.AUTHOR

    Even if AUTHOR was generated from DEV. @@ -3522,13 +3522,13 @@ create.selectFrom(AUTHOR).fetch();

    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

    Table mapping and schema mapping can be applied independently, by specifying several MappedSchema entries in the above configuration. jOOQ will process them in order of appearance and map at first match. Note that you can always omit a MappedSchema's output value, in case of which, only the table mapping is applied. If you omit a MappedSchema's input value, the table mapping is applied to all schemata!

    - +

    Using regular expressions

    All of the above examples were using 1:1 constant name mappings where the input and output schema or table names are fixed by the configuration. With jOOQ 3.8, regular expression can be used as well for mapping, for example: @@ -3581,7 +3581,7 @@ create.selectFrom(AUTHOR).fetch();

    Here is an example to illustrate what that means:

    - + 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) @@ -3653,7 +3653,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); @@ -3680,7 +3680,7 @@ query.addJoin(BOOK, BOOK.AUTHOR_ID.equal(AUTHOR.ID));]]>

    Note, that for historic reasons, the DSL API mixes mutable and immutable behaviour with respect to the internal representation of the being constructed. While creating , (such as functions) assumes immutable behaviour, creating does not. In other words, the following can be said:

    - + select2 = create.selectOne().fetch();]]>

    jOOQ does not explicitly support the asterisk operator in projections. However, you can omit the projection as in these examples:

    - +

    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:

    - + select(Collection> fields); public static SelectSelectStep select(Field... fields); @@ -3962,14 +3962,14 @@ public static SelectSelectStep> select(Field SelectSelectStep> select(Field field1, Field field2); public static SelectSelectStep> select(Field field1, Field field2, Field field3); // [...]]]> - +

    Since the generic R type is bound to some , the associated T type information can be used in various other contexts, e.g. the . Such a SELECT statement can be assigned typesafely:

    > s1 = create.select(BOOK.ID, BOOK.TITLE); Select> s2 = create.select(BOOK.ID, trim(BOOK.TITLE));]]> - +

    For more information about typesafe record types with degree up to {max-row-degree}, see the manual's section about .

    @@ -3995,7 +3995,7 @@ create.selectOne().from(BOOK.as("b"), AUTHOR.as("a")).fetch();]]>

    Read more about aliasing in the manual's section about .

    - +

    More advanced table expressions

    Apart from simple tables, you can pass any arbitrary to the jOOQ FROM clause. This may include in Oracle: @@ -4053,11 +4053,11 @@ DSL.using(SQLDialect.POSTGRES).selectOne().fetch();]]>

  • NATURAL LEFT [ OUTER ] JOIN
  • NATURAL RIGHT [ OUTER ] JOIN
  • - +

    Besides, jOOQ also supports

    - +
    • CROSS APPLY (T-SQL and Oracle 12c specific)
    • OUTER APPLY (T-SQL and Oracle 12c specific)
    • @@ -4187,7 +4187,7 @@ ON BOOK.AUTHOR_ID = AUTHOR.ID

      SEMI JOIN and ANTI JOIN

      - Very few databases (e.g. Apache Impala) ship with a built-in syntax for { LEFT | RIGHT } SEMI JOIN and { LEFT | RIGHT } ANTI JOIN, which are much more concise versions of the SQL standard IN / EXISTS and NOT IN / NOT EXISTS predicates. The idea is that the JOIN syntax is expressed where it belongs, in the FROM clause, not in the WHERE clause. + Very few databases (e.g. Apache Impala) ship with a built-in syntax for { LEFT | RIGHT } SEMI JOIN and { LEFT | RIGHT } ANTI JOIN, which are much more concise versions of the SQL standard IN / EXISTS and NOT IN / NOT EXISTS predicates. The idea is that the JOIN syntax is expressed where it belongs, in the FROM clause, not in the WHERE clause.

      Since jOOQ 3.7, these types of JOIN are also supported and they're emulated using EXISTS and NOT EXISTS respectively. @@ -4195,7 +4195,7 @@ ON BOOK.AUTHOR_ID = AUTHOR.ID

      Here's how SEMI JOIN translates to EXISTS.

      - + - +

      T-SQL's CROSS APPLY and OUTER APPLY

      T-SQL has long known what the SQL standard calls lateral derived tables, lateral joins using the APPLY keyword. To every row resulting from the table expression on the left, we apply the table expression on the right. This is extremely useful for table-valued functions, which are also supported by jOOQ. Some examples:

      - + - +

      The above example shows standard usage of the LATERAL keyword to connect a derived table to the previous table in the . A similar statement can be written in T-SQL:

      - + - +

      While not all forms of LATERAL JOIN have an equivalent APPLY syntax, the inverse is true, and jOOQ can thus emulate OUTER APPLY and CROSS APPLY using LATERAL JOIN.

      - +

      LATERAL JOIN or CROSS APPLY are particularly useful together with , which are also supported by jOOQ.

      @@ -4383,12 +4383,12 @@ ORDER BY 1

      Note that this syntax is also supported in the CUBRID database and might be emulated in other dialects supporting common table expressions in the future.

      - +

      ORDER SIBLINGS

      The Oracle database allows for specifying a SIBLINGS keyword in the . Instead of ordering the overall result, this will only order siblings among each other, keeping the hierarchy intact. An example is given here:

      - + - +
    @@ -4432,7 +4432,7 @@ GROUP BY AUTHOR_ID

    Note, as defined in the SQL standard, when grouping, you may no longer project any columns that are not a formal part of the GROUP BY clause, or .

    - +

    MySQL's deviation from the SQL standard

    MySQL has a peculiar way of not adhering to this standard behaviour. This is documented in the MySQL manual. In short, with MySQL, you can also project any other field that is not part of the GROUP BY clause. The projected values will just be arbitrary values from within the group. You cannot rely on any ordering. For example: @@ -4467,7 +4467,7 @@ GROUP BY () .groupBy() .fetch();]]> - +

    ROLLUP(), CUBE() and GROUPING SETS()

    Some databases support the SQL standard grouping functions and some extensions thereof. See the manual's section about for more details. @@ -4488,7 +4488,7 @@ FROM BOOK GROUP BY AUTHOR_ID HAVING COUNT(*) >= 2 ]]>  -= 4

    - +
    The WINDOW clause

    The SQL:2003 standard as well as PostgreSQL and Sybase SQL Anywhere support a WINDOW clause that allows for specifying WINDOW frames for reuse in and .

    - +   - +

    Note that in order to create such a window definition, we need to first create a using .

    Even if only PostgreSQL and Sybase SQL Anywhere natively support this great feature, jOOQ can emulate it by expanding any and types that you pass to the window() method - if the database supports window functions at all.

    - +

    Some more information about and the WINDOW clause can be found on our blog: http://blog.jooq.org/2013/11/03/probably-the-coolest-sql-feature-window-functions/

    @@ -4686,8 +4686,8 @@ ORDER BY CASE TITLE

    The SQL standard defines that a "query expression" can be ordered, and that query expressions can contain , whose subqueries cannot be ordered. While this is defined as such in the SQL standard, many databases allowing for the in one way or another, do not adhere to this part of the SQL standard. Hence, jOOQ allows for ordering all SELECT statements, regardless whether they are constructed as a part of a UNION or not. Corner-cases are handled internally by jOOQ, by introducing synthetic subselects to adhere to the correct syntax, where this is needed.

    - - + +

    Oracle's ORDER SIBLINGS BY clause

    jOOQ also supports Oracle's SIBLINGS keyword to be used with ORDER BY clauses for @@ -4739,7 +4739,7 @@ SELECT TOP 1 * FROM BOOK

    Things get a little more tricky in those databases that have no native idiom for OFFSET pagination (actual queries may vary):

    - + 1]]>

    As you can see, jOOQ will take care of the incredibly painful ROW_NUMBER() OVER() (or ROWNUM for Oracle) filtering in subselects for you, you'll just have to write limit(1).offset(2) in any dialect.

    - +

    Side-note: If you're interested in understanding why we chose ROWNUM for Oracle, please refer to this very interesting benchmark, comparing the different approaches of doing pagination in Oracle: http://www.inf.unideb.hu/~gabora/pagination/results.html.

    @@ -4786,7 +4786,7 @@ WHERE RN > 1]]>

    - +
    The SEEK clause @@ -4796,7 +4796,7 @@ WHERE RN > 1]]>

    A much faster and more stable way to perform paging is the so-called keyset paging method also called seek method. jOOQ supports a synthetic seek() clause, that can be used to perform keyset paging. Imagine we have these data:

    - + 1]]>

    Now, if we want to display page 6 to the user, instead of going to page 6 by using a record OFFSET, we could just fetch the record strictly after the last record on page 5, which yields the values (533, 2). This is how you would do it with SQL or with jOOQ:

    - + As you can see, the jOOQ SEEK clause is a synthetic clause that does not really exist in SQL. However, the jOOQ syntax is far more intuitive for a variety of reasons:

    - +
    • It replaces OFFSET where you would expect
    • It doesn't force you to mix regular predicates with "seek" predicates
    • It is typesafe
    • It emulates for you, in those databases that do not support them
    - +

    This query now yields:

    - + Note that you cannot combine the SEEK clause with the OFFSET clause.

    - +

    More information about this great feature can be found in the jOOQ blog:

    @@ -4867,11 +4867,11 @@ LIMIT 5
  • http://blog.jooq.org/2013/10/26/faster-sql-paging-with-jooq-using-the-seek-method/
  • http://blog.jooq.org/2013/11/18/faster-sql-pagination-with-keysets-continued/
  • - +

    Further information about offset pagination vs. keyset pagination performance can be found on our partner page:

    - +
    No more offset @@ -4983,7 +4983,7 @@ SELECT * FROM author ORDER BY id DESC;]]>

    SQL allows to perform set operations as understood in standard set theory on result sets. These operations include unions, intersections, subtractions. For two subselects to be combinable by such a set operator, each subselect must return a of the same degree and type.

    - +

    UNION and UNION ALL

    These operators combine two results into one. While UNION removes all duplicate records resulting from this combination, UNION ALL leaves subselect results as they are. Typically, you should prefer UNION ALL over UNION, if you don't really need to remove duplicates. The following example shows how to use such a UNION operation in jOOQ. @@ -4998,16 +4998,16 @@ SELECT * FROM BOOK WHERE ID = 5 .unionAll( create.selectFrom(BOOK).where(BOOK.ID.equal(5))) .fetch();]]> - +

    INTERSECT [ ALL ] and EXCEPT [ ALL ]

    INTERSECT is the operation that produces only those values that are returned by both subselects. EXCEPT (or MINUS in Oracle) is the operation that returns only those values that are returned exclusively in the first subselect. Both operators will remove duplicates from their results.

    - +

    Just like with UNION ALL, these operators have an optional ALL keyword that allows for keeping duplicate rows after intersection or subtraction, which is supported in jOOQ 3.7+.

    - +

    jOOQ's set operators and how they're different from standard SQL

    As previously mentioned in the manual's section about the , jOOQ has slightly changed the semantics of these set operators. While in SQL, a subselect may not contain any or (unless you wrap the subselect into a ), jOOQ allows you to do so. In order to select both the youngest and the oldest author from the database, you can issue the following statement with jOOQ (rendered to the MySQL dialect): @@ -5028,7 +5028,7 @@ ORDER BY 1 .orderBy(AUTHOR.DATE_OF_BIRTH.desc()).limit(1)) .orderBy(1) .fetch();]]> - +

    In case your database doesn't support ordered UNION subselects, the subselects are nested in derived tables:

    @@ -5046,12 +5046,12 @@ SELECT * FROM ( ORDER BY 1]]> - +

    Projection typesafety for degrees between 1 and {max-row-degree}

    Two subselects that are combined by a set operator are required to be of the same degree and, in most databases, also of the same type. jOOQ 3.0's introduction of helps compile-checking these constraints:

    - + > s1 = select(BOOK.ID, BOOK.TITLE).from(BOOK); Select> s2 = selectOne(); @@ -5087,7 +5087,7 @@ s1.union(s4); // OK. The two Record[N] types match]]>

    Note that you can pass any string in the .hint() clause. If you use that clause, the passed string will always be put in between the SELECT [DISTINCT] keywords and the actual projection list. This can be useful in other databases too, such as MySQL, for instance:

    - +
    - +
    Lexical and logical SELECT clause order

    SQL has a lexical and a logical order of SELECT clauses. The lexical order of SELECT clauses is inspired by the English language. As SQL statements are commands for the database, it is natural to express a statement in an imperative tense, such as "SELECT this and that!".

    - +

    Logical SELECT clause order

    The logical order of SELECT clauses, however, does not correspond to the syntax. In fact, the logical order is this:

    - +
    • : First, all data sources are defined and joined
    • : Then, data is filtered as early as possible
    • @@ -5125,11 +5125,11 @@ FROM table1
    • : Then, a paging view is created for the ordered tuples
    • : Finally, pessimistic locking is applied
    - +

    The SQL Server documentation also explains this, with slightly different clauses:

    - +
    • FROM
    • ON
    • @@ -5143,16 +5143,16 @@ FROM table1
    • ORDER BY
    • TOP
    - +

    As can be seen, databases have to logically reorder a SQL statement in order to determine the best execution plan.

    - +

    Alternative syntaxes: LINQ, SLICK

    Some "higher-level" abstractions, such as C#'s LINQ or Scala's SLICK try to inverse the lexical order of SELECT clauses to what appears to be closer to the logical order. The obvious advantage of moving the SELECT clause to the end is the fact that the projection type, which is the record type returned by the SELECT statement can be re-used more easily in the target environment of the internal domain specific language.

    - +

    A LINQ example:

    @@ -5165,11 +5165,11 @@ Where p.UnitsInStock <= p.ReorderLevel AndAlso Not p.Discontinued // SELECT clause Select p]]> - +

    A SLICK example:

    - + INSERT statement is used to insert new records into a database table. The following sections describe the various operation modes of the jOOQ INSERT statement.

    - +
    INSERT .. VALUES - +

    INSERT .. VALUES with a single row

    Records can either be supplied using a VALUES() constructor, or a SELECT statement. jOOQ supports both types of INSERT statements. An example of an INSERT statement using a VALUES() constructor is given here: @@ -5227,7 +5227,7 @@ VALUES (100, 'Hermann', 'Hesse'); create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME); step.values("A", "B", "C"); // ^^^ Doesn't compile, the expected type is Integer]]> - +

    INSERT .. VALUES with multiple rows

    The SQL standard specifies that multiple rows can be supplied to the VALUES() constructor in an INSERT statement. Here's an example of a multi-record INSERT @@ -5265,14 +5265,14 @@ SELECT 101, 'Alfred', 'Döblin' FROM DUAL;

    - +
    INSERT .. DEFAULT VALUES

    A lesser-known syntactic feature of SQL is the INSERT .. DEFAULT VALUES statement, where a single record is inserted, containing only DEFAULT values for every row. It is written as such:

    - + create.insertInto(AUTHOR) .defaultValues() .execute(); - +

    This can make a lot of sense in situations where you want to "reserve" a row in the database for an subsequent within the same transaction. Or if you just want to send an event containing trigger-generated default values, such as IDs or timestamps.

    @@ -5290,18 +5290,18 @@ DEFAULT VALUES;

    -  create.insertInto( AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, ...) .values( - defaultValue(AUTHOR.ID), - defaultValue(AUTHOR.FIRST_NAME), + defaultValue(AUTHOR.ID), + defaultValue(AUTHOR.FIRST_NAME), defaultValue(AUTHOR.LAST_NAME), ...) .execute(); @@ -5310,7 +5310,7 @@ VALUES (

    - +
    INSERT .. SET @@ -5327,13 +5327,13 @@ VALUES ( .set(AUTHOR.FIRST_NAME, "Alfred") .set(AUTHOR.LAST_NAME, "Döblin") .execute(); - +

    As you can see, this syntax is a bit more verbose, but also more readable, as every field can be matched with its value. Internally, the two syntaxes are strictly equivalent. -

    +

    - +
    INSERT .. SELECT @@ -5341,22 +5341,22 @@ VALUES (

    In some occasions, you may prefer the INSERT SELECT syntax, for instance, when you copy records from one table to another:

    - + create.insertInto(AUTHOR_ARCHIVE) .select(selectFrom(AUTHOR).where(AUTHOR.DECEASED.isTrue())) .execute();
    - +
    INSERT .. ON DUPLICATE KEY

    The synthetic ON DUPLICATE KEY UPDATE clause

    - +

    The MySQL database supports a very convenient way to INSERT or UPDATE a record. This is a non-standard extension to the SQL syntax, which is supported by jOOQ and emulated in other RDBMS, where this is possible (i.e. if they support the SQL standard ). Here is an example how to use the ON DUPLICATE KEY UPDATE clause:

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, update the author's name create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -5366,11 +5366,11 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .execute();

    The synthetic ON DUPLICATE KEY IGNORE clause

    - +

    The MySQL database also supports an INSERT IGNORE INTO clause. This is supported by jOOQ using the more convenient SQL syntax variant of ON DUPLICATE KEY IGNORE:

    - + // Add a new author called "Koontz" with ID 3. // If that ID is already present, ignore the INSERT statement create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) @@ -5380,11 +5380,11 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME)

    If the underlying database doesn't have any way to "ignore" failing INSERT statements, (e.g. MySQL via INSERT IGNORE), jOOQ can emulate the statement using a , or using INSERT .. SELECT WHERE NOT EXISTS:

    - +

    Emulating IGNORE with MERGE

    - +

    - The above jOOQ statement can be emulated with the following, equivalent SQL statement: + The above jOOQ statement can be emulated with the following, equivalent SQL statement:

    MERGE INTO AUTHOR @@ -5392,11 +5392,11 @@ USING (SELECT 1 FROM DUAL) ON (AUTHOR.ID = 3) WHEN NOT MATCHED THEN INSERT (ID, LAST_NAME) VALUES (3, 'Koontz') - +

    Emulating IGNORE with INSERT .. SELECT WHERE NOT EXISTS

    - +

    - The above jOOQ statement can be emulated with the following, equivalent SQL statement: + The above jOOQ statement can be emulated with the following, equivalent SQL statement:

    INSERT INTO AUTHOR (ID, LAST_NAME) @@ -5408,11 +5408,11 @@ WHERE NOT EXISTS ( )
    - +
    INSERT .. RETURNING - +

    The Postgres database has native support for an INSERT .. RETURNING clause. This is a very powerful concept that is emulated for all other dialects using JDBC's method. Take this example:

    @@ -5492,7 +5492,7 @@ create.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

    jOOQ supports formal in various contexts, among which the UPDATE statement. Only one row value expression can be updated at a time. Here's an example:

    - + The above row value expressions usages are completely typesafe.

    - +

    UPDATE .. RETURNING

    The Firebird and Postgres databases support a RETURNING clause on their UPDATE statements, similar as the RETURNING clause in . This is useful to fetch trigger-generated values in one go. An example is given here:

    - +

    - The UPDATE .. RETURNING clause is emulated for DB2 using the SQL standard SELECT .. FROM FINAL TABLE(UPDATE ..) construct, and in Oracle, using the PL/SQL UPDATE .. RETURNING statement. + The UPDATE .. RETURNING clause is emulated for DB2 using the SQL standard SELECT .. FROM FINAL TABLE(UPDATE ..) construct, and in Oracle, using the PL/SQL UPDATE .. RETURNING statement.

    @@ -5609,7 +5609,7 @@ WHEN NOT MATCHED THEN INSERT (LAST_NAME) VALUES ('Hitchcock');

    The H2 database ships with a somewhat less powerful but a little more intuitive syntax for its own version of the MERGE statement. An example more or less equivalent to the previous one can be seen here:

    - + -- Check if there is already an author called 'Hitchcock' -- If there is, rename him to John. If there isn't add him. @@ -5629,7 +5629,7 @@ VALUES ('John', 'Hitchcock') This syntax can be fully emulated by jOOQ for all other databases that support the SQL standard MERGE statement. For more information about the H2 MERGE syntax, see the documentation here:
    http://www.h2database.com/html/grammar.html#merge

    - +

    Typesafety of VALUES() for degrees up to {max-row-degree}

    Much like the , the MERGE statement's VALUES() clause provides typesafety for degrees up to {max-row-degree}, in both the standard syntax variant as well as the H2 variant. @@ -5745,7 +5745,7 @@ create.alterViewIfExists("old_view").renameTo("new_view").execute();]]>

    - +
    The CREATE statement @@ -5807,7 +5807,7 @@ create.createTable("TOP_AUTHORS").as( selectCount().from(BOOK) .where(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) ))).execute(); - + // Create a table only if it doesn't exists (not all databases support this) create.createTableIfNotExists("TOP_AUTHORS") ...]]> @@ -5825,13 +5825,13 @@ create.createView("V_TOP_AUTHORS").as( selectCount().from(BOOK) .where(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) ))).execute(); - + // Create a view only if it doesn't exists (not all databases support this) create.createTableIfNotExists("TOP_AUTHORS") ...]]>
    - +
    The DROP statement @@ -5900,24 +5900,24 @@ create.dropViewIfExists(V_AUTHOR).execute();]]>

    - - + +
    Generating DDL from objects

    When using jOOQ's , a whole set of meta data is generated with the generated artefacts, such as schemas, tables, columns, data types, constraints, default values, etc.

    - +

    This meta data can be used to generate DDL CREATE statements in any SQL dialect, in order to partially restore the original schema again on a new database instance. This is particularly useful, for instance, when working with an Oracle production database, and an H2 in-memory test database. The following code produces the DDL for a schema:

    - + @@ -5926,7 +5926,7 @@ for (Query query : ddl.queries()) { When executing the above, you should see something like the following:

    - - +

    Do note that these features only restore parts of the original schema. For instance, vendor-specific storage clauses that are not available to jOOQ's generated meta data cannot be reproduced this way.

    @@ -5963,13 +5963,13 @@ alter table "PUBLIC"."T_BOOK"

    Most databases know some sort of namespace to group objects like , , and others into a common catalog or schema. jOOQ uses the types and to model these groupings, following SQL standard naming.

    - +

    The catalog

    - +

    A catalog is a collection of schemas. In many databases, the catalog corresponds to the database, or the database instance. Most often, catalogs are completely independent and their tables cannot be joined or combined in any way in a single query. The exception here is SQL Server, which allows for fully referencing tables from multiple catalogs:

    - + @@ -5981,17 +5981,17 @@ JOIN [Catalog2].[Schema2].[Table2] AS [t2] ON [t1].[ID] = [t2].[ID]]]> jOOQ's generates subpackages for each catalog.

    - +

    The schema

    - +

    A schema is a collection of objects, such as tables. Most databases support some sort of schema (except for some embedded databases like Access, Firebird, SQLite). In most databases, the schema is an independent structural entity. In Oracle, the schema and the user / owner is mostly treated as the same thing. An example of a query that uses fully qualified tables including schema names is:

    - + - +

    By default, the Settings.renderSettings flag is turned on. jOOQ will thus generate fully qualified object names, including the setting name. For more information about this setting, see

    @@ -6013,7 +6013,7 @@ JOIN "Schema2"."Table2" AS "t2" ON "t1"."ID" = "t2"."ID"]]>

    Most of the times, when thinking about a you're probably thinking about an actual table in your database schema. If you're using jOOQ's , you will have all tables from your database schema available to you as type safe Java objects. You can then use these tables in SQL , or in other , just like any other table expression. An example is given here:

    - +
    - +

    The above example shows how AUTHOR and BOOK tables are joined in a . It also shows how you can access by dereferencing the relevant Java attributes of their tables.

    @@ -6066,11 +6066,11 @@ create.select() .and(a.FIRST_NAME.equal("Paulo"))) .orderBy(b.TITLE) .fetch();]]> - +

    As you can see in the above example, calling as() on generated tables returns an object of the same type as the table. This means that the resulting object can be used to dereference fields from the aliased table. This is quite powerful in terms of having your Java compiler check the syntax of your SQL statements. If you remove a column from a table, dereferencing that column from that table alias will cause compilation errors.

    - +

    Dereferencing columns from other table expressions

    Only few table expressions provide the SQL syntax typesafety as shown above, where generated tables are used. Most tables, however, expose their fields through field() methods: @@ -6082,12 +6082,12 @@ Table a = AUTHOR.as("a"); // Get fields from a: Field id = a.field("ID"); Field firstName = a.field("FIRST_NAME");]]> - +

    Derived column lists

    The SQL standard specifies how a table can be renamed / aliased in one go along with its columns. It references the term "derived column list" for the following syntax (as supported by Postgres, for instance):

    - + In jOOQ, you would simply specify a varargs list of column aliases as such:

    - + The that can be used in are the most powerful and best supported means of creating new in SQL. Informally, the following can be said:

    - + A(colA1, ..., colAn) "join" B(colB1, ..., colBm) "produces" C(colA1, ..., colAn, colB1, ..., colBm)

    @@ -6162,7 +6162,7 @@ create.select().from(values(

    jOOQ supports all of these JOIN types (including semi-join and anti-join) directly on any :

    - + table) @@ -6221,7 +6221,7 @@ TableOnStep join(Name)]]>

    Some databases allow for expressing in-memory temporary tables using a VALUES() constructor. This constructor usually works the same way as the VALUES() clause known from the or from the . With jOOQ, you can also use the VALUES() table constructor, to create tables that can be used in a :

    - + Note, that it is usually quite useful to provide column aliases ("derived column lists") along with the table alias for the VALUES() constructor.

    - +

    The above statement is emulated by jOOQ for those databases that do not support the VALUES() constructor, natively (actual emulations may vary):

    - + A can appear almost anywhere a can. Such a "nested SELECT" is often called a "derived table". Apart from many convenience methods accepting objects directly, a SELECT statement can always be transformed into a object using the asTable() method.

    - +

    Example: Scalar subquery

    - + If you are closely coupling your application to an Oracle database, you can take advantage of some Oracle-specific features, such as the PIVOT clause, used for statistical analyses. The formal syntax definition is as follows:

    - + -- SELECT .. FROM table PIVOT (aggregateFunction [, aggregateFunction] FOR column IN (expression [, expression])) -- WHERE .. - +

    The PIVOT clause is available from the type, as pivoting is done directly on a table. Currently, only Oracle's PIVOT clause is supported. Support for SQL Server's slightly different PIVOT clause will be added later. Also, jOOQ may emulate PIVOT for other dialects in the future.

    @@ -6413,7 +6413,7 @@ WHERE NOT EXISTS (

    The SQL standard specifies how SQL databases should implement ARRAY and TABLE types, as well as CURSOR types. Put simply, a CURSOR is a pointer to any materialised . Depending on the cursor's features, this table expression can be scrolled through in both directions, records can be locked, updated, removed, inserted, etc. Often, CURSOR types contain s, whereas ARRAY and TABLE types contain simple scalar values, although that is not a requirement

    - +

    ARRAY types in SQL are similar to Java's array types. They contain a "component type" or "element type" and a "dimension". This sort of ARRAY type is implemented in H2, HSQLDB and Postgres and supported by jOOQ as such. Oracle uses strongly-typed arrays, which means that an ARRAY type (VARRAY or TABLE type) has a name and possibly a maximum capacity associated with it.

    @@ -6436,7 +6436,7 @@ FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(null, null, 'ALLSTATS'));

    - +
    Table-valued functions @@ -6459,11 +6459,11 @@ BEGIN ORDER BY id RETURN END]]> - +

    The jOOQ code generator will now produce a from the above, which can be used as a SQL function:

    - + r1 = create.selectFrom(fBooks(null)).fetch(); @@ -6471,7 +6471,7 @@ Result r1 = create.selectFrom(fBooks(null)).fetch(); create.select(BOOK.ID, F_BOOKS.TITLE) .from(BOOK.crossApply(fBooks(BOOK.ID))) .fetch();]]> - +
    ¨ @@ -6545,12 +6545,12 @@ DSL.using(SQLDialect.SYBASE ).selectOne().getSQL();]]>

    Column expressions can be used in various SQL clauses in order to refer to one or several columns. This chapter explains how to form various types of column expressions with jOOQ. A particular type of column expression is given in the section about , where an expression may have a degree of more than one.

    - +

    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:

    - + field1 = BOOK.TITLE; @@ -6606,7 +6606,7 @@ ORDER BY BOOK.TITLE

    Just like , columns can be renamed using aliases. Here is an example:

    - + SELECT FIRST_NAME || ' ' || LAST_NAME author, COUNT(*) books FROM AUTHOR JOIN BOOK ON AUTHOR.ID = AUTHOR_ID @@ -6615,7 +6615,7 @@ GROUP BY FIRST_NAME, LAST_NAME;

    Here is how it's done with jOOQ:

    - + Record record = create.select( concat(AUTHOR.FIRST_NAME, val(" "), AUTHOR.LAST_NAME).as("author"), count().as("books")) @@ -6623,14 +6623,14 @@ GROUP BY FIRST_NAME, LAST_NAME; .join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID)) .groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .fetchAny(); - +

    When you alias Fields like above, you can access those Fields' values using the alias name:

    - + System.out.println("Author : " + record.getValue("author")); System.out.println("Books : " + record.getValue("books")); - + @@ -6643,7 +6643,7 @@ System.out.println("Books : " + record.getValue("books"));

    Sometimes, this automatic mapping might not be what you needed, or jOOQ cannot know the type of a field. In those cases you would write SQL type CAST like this:

    - + -- Let's say, your Postgres column LAST_NAME was VARCHAR(30) -- Then you could do this: SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL @@ -6651,27 +6651,27 @@ SELECT CAST(AUTHOR.LAST_NAME AS TEXT) FROM DUAL

    in jOOQ, you can write something like that:

    - + create.select(TAuthor.LAST_NAME.cast(PostgresDataType.TEXT)).fetch();

    The same thing can be achieved by casting a Field directly to String.class, as TEXT is the default data type in Postgres to map to Java's String

    - + create.select(TAuthor.LAST_NAME.cast(String.class)).fetch(); - +

    The complete CAST API in consists of these three methods:

    - + { // Cast this field to the type of another field Field cast(Field field); - + // Cast this field to a given DataType Field cast(DataType type); - + // Cast this field to the default DataType for a given Class Field cast(Class type); } @@ -6694,14 +6694,14 @@ public class DSL {

    A slightly different use case than are data type coercions, which are not rendered through to generated SQL. Sometimes, you may want to pretend that a numeric value is really treated as a string value, for instance when binding a numeric :

    - + field1 = val(1).coerce(String.class); Field field2 = val("1").coerce(Integer.class);]]>

    In the above example, field1 will be treated by jOOQ as a Field<String>, binding the numeric literal 1 as a VARCHAR value. The same applies to field2, whose string literal "1" will be bound as an INTEGER value.

    - +

    This technique is better than performing unsafe or rawtype casting in Java, if you cannot access the "right" field type from any given expression.

    @@ -6721,15 +6721,15 @@ Field field2 = val("1").coerce(Integer.class);]]>

    In order to express a SQL query like this one:

    - + SELECT ((1 + 2) * (5 - 3) / 2) % 10 FROM DUAL - +

    You can write something like this in jOOQ:

    - + create.select(val(1).add(2).mul(val(5).sub(3)).div(2).mod(10)).fetch(); - +

    Operator precedence

    jOOQ does not know any operator precedence (see also ). All operations are evaluated from left to right, as with any object-oriented API. The two following expressions are the same: @@ -6757,14 +6757,14 @@ Field field2 = val("1").coerce(Integer.class);]]> - +

    String concatenation

    The SQL standard defines the concatenation operator to be an infix operator, similar to the ones we've seen in the chapter about . This operator looks like this: ||. Some other dialects do not support this operator, but expect a concat() function, instead. jOOQ renders the right operator / function, depending on your :

    - + SELECT 'A' || 'B' || 'C' FROM DUAL -- Or in MySQL: @@ -6792,13 +6792,13 @@ create.select(concat("A", "B", "C")).fetch();
  • NVL: Get the first non-null value among two arguments.
  • NVL2: Get the second argument if the first is null, or the third argument, otherwise.
  • - +

    Please refer to the for more details.

    - +
    Numeric functions @@ -6808,7 +6808,7 @@ create.select(concat("A", "B", "C")).fetch();

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ABS: Get the absolute value of a value.
    • ACOS: Get the arc cosine of a value.
    • @@ -6839,7 +6839,7 @@ create.select(concat("A", "B", "C")).fetch();
    • TANH: Get the hyperbolic tangent of a value.
    • TRUNC: Truncate the decimals off a given value.
    - +

    Please refer to the for more details.

    @@ -6864,13 +6864,13 @@ create.select(concat("A", "B", "C")).fetch();
  • SHL: Shift bits to the left
  • SHR: Shift bits to the right
  • - +

    Some background about bitwise operation emulation

    As stated before, not all databases support all of these bitwise operations. jOOQ emulates them wherever this is possible. More details can be seen in this blog post:
    http://blog.jooq.org/2011/10/30/the-comprehensive-sql-bitwise-operations-compatibility-list/

    - +
    @@ -6883,7 +6883,7 @@ create.select(concat("A", "B", "C")).fetch();

    This is a list of numeric functions supported by jOOQ's :

    - +
    • ASCII: Get the ASCII code of a character.
    • BIT_LENGTH: Get the length of a string in bits.
    • @@ -6904,16 +6904,16 @@ create.select(concat("A", "B", "C")).fetch();
    • TRIM: Trim a string on both sides.
    • UPPER: Get a string in upper case letters.
    - +

    Please refer to the for more details.

    - +

    Regular expressions, REGEXP, REGEXP_LIKE, etc.

    Various databases have some means of searching through columns using regular expressions if the does not provide sufficient pattern matching power. While there are many different functions and operators in the various databases, jOOQ settled for the SQL:2008 standard REGEX_LIKE operator. Being an operator (and not a function), you should use the corresponding method on :

    - +

    @@ -6922,7 +6922,7 @@ create.select(concat("A", "B", "C")).fetch(); - +

    Case sensitivity with strings @@ -6935,20 +6935,20 @@ create.select(concat("A", "B", "C")).fetch();

    For these ad-hoc ordering use-cases, most people resort to using LOWER() or UPPER() as follows:

    - + -- Case-insensitive filtering: -SELECT * FROM BOOK +SELECT * FROM BOOK WHERE upper(TITLE) = 'ANIMAL FARM' -- Case-insensitive ordering: -SELECT * +SELECT * FROM AUTHOR ORDER BY upper(FIRST_NAME), upper(LAST_NAME) // Case-insensitive filtering: create.selectFrom(BOOK) .where(upper(BOOK.TITLE).eq("ANIMAL FARM")).fetch(); - + // Case-insensitive ordering: create.selectFrom(AUTHOR) .orderBy(upper(AUTHOR.FIRST_NAME), upper(AUTHOR.LAST_NAME)) @@ -6965,7 +6965,7 @@ create.selectFrom(AUTHOR)

    This is a list of date and time functions supported by jOOQ's :

    - +
    • CURRENT_DATE: Get current date as a DATE object.
    • CURRENT_TIME: Get current time as a TIME object.
    • @@ -6975,7 +6975,7 @@ create.selectFrom(AUTHOR)
    • TIMESTAMP_ADD: Add a number of days or an interval to a timestamp.
    • TIMESTAMP_DIFF: Get the difference as an INTERVAL DAY TO SECOND between two dates.
    - +

    Intervals in jOOQ

    jOOQ fills a gap opened by JDBC, which neglects an important SQL data type as defined by the SQL standards: INTERVAL types. See the manual's section about for more details. @@ -7127,7 +7127,7 @@ GROUP BY AUTHOR_ID WindowOverStep rank(); WindowOverStep denseRank(); WindowOverStep percentRank(); - + // Windowing functions WindowIgnoreNullsStep firstValue(Field field); WindowIgnoreNullsStep lastValue(Field field); @@ -7145,13 +7145,13 @@ GROUP BY AUTHOR_ID // Statistical functions WindowOverStep cumeDist(); WindowOverStep ntile(int number); - + // Inverse distribution functions OrderedAggregateFunction precentileCont(Number number); OrderedAggregateFunction precentileCont(Field number); OrderedAggregateFunction precentileDisc(Number number); OrderedAggregateFunction precentileDisc(Field number);]]> - +

    SQL distinguishes between various window function types (e.g. "ranking functions"). Depending on the function, SQL expects mandatory PARTITION BY or ORDER BY clauses within the OVER() clause. jOOQ does not enforce those rules for two reasons:

    @@ -7166,14 +7166,14 @@ GROUP BY AUTHOR_ID

    Here are some simple examples of window functions with jOOQ:

    - + -- Sample uses of ROW_NUMBER() ROW_NUMBER() OVER() ROW_NUMBER() OVER(PARTITION BY 1) ROW_NUMBER() OVER(ORDER BY BOOK.ID) ROW_NUMBER() OVER(PARTITION BY BOOK.AUTHOR_ID ORDER BY BOOK.ID) - + -- Sample uses of FIRST_VALUE FIRST_VALUE(BOOK.ID) OVER() FIRST_VALUE(BOOK.ID IGNORE NULLS) OVER() @@ -7184,14 +7184,14 @@ rowNumber().over() rowNumber().over().partitionByOne() rowNumber().over().partitionBy(BOOK.AUTHOR_ID) rowNumber().over().partitionBy(BOOK.AUTHOR_ID).orderBy(BOOK.ID) - + // Sample uses of firstValue() firstValue(BOOK.ID).over() firstValue(BOOK.ID).ignoreNulls().over() firstValue(BOOK.ID).respectNulls().over()
    - +

    An advanced window function example

    Window functions can be used for things like calculating a "running total". The following example fetches transactions and the running total for every transaction going back to the beginning of the transaction table (ordered by booked_at). Window functions are accessible from the previously seen type using the over() method: @@ -7219,7 +7219,7 @@ firstValue(BOOK.ID).respectNulls().over()

    In the previous chapter about , we have seen the concept of "ordered-set aggregate functions", such as Oracle's LISTAGG(). These functions have a window function / analytical function variant, as well. For example:

    - + SELECT LISTAGG(TITLE, ', ') WITHIN GROUP (ORDER BY TITLE) @@ -7304,7 +7304,7 @@ ORDER BY 1 NULLS LAST, 2 NULLS LAST

    In English, the ROLLUP() grouping function provides N+1 groupings, when N is the number of arguments to the ROLLUP() function. Each grouping has an additional group field from the ROLLUP() argument field list. The results of the second query might look something like this:

    - + GROUPING SETS() and other grouping functions:
    http://msdn.microsoft.com/en-us/library/bb510427(v=sql.105)

    - +

    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:

    - + ... fields); GroupField cube(Field... fields); @@ -7407,7 +7407,7 @@ Field groupingId(Field...);]]>

    MySQL and CUBRID don't know any grouping functions, but they support a WITH ROLLUP clause, that is equivalent to simple ROLLUP() grouping functions. jOOQ emulates ROLLUP() in MySQL and CUBRID, by rendering this WITH ROLLUP clause. The following two statements mean the same:

    - + Some databases support user-defined functions, which can be embedded in any SQL statement, if you're using jOOQ's . Let's say you have the following simple function in Oracle SQL:

    - + The above function will be made available from a generated class. You can use it like any other :

    - + - +

    Note that user-defined functions returning or data types can also be used wherever can be used, if they are

    @@ -7459,7 +7459,7 @@ END echo;

    Some databases support user-defined aggregate functions, which can then be used along with or as . An example for such a database is Oracle. With Oracle, you can define the following OBJECT type (the example was taken from the Oracle 11g documentation):

    - +

    jOOQ's will detect such aggregate functions and generate them differently from regular . They implement the type, as mentioned in the manual's section about . Here's how you can use the SECOND_MAX() aggregate function with jOOQ:

    - +
    - +
    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:

    - + Row1 row(T1 t1) { ... } public static Row2 row(T1 t1, T2 t2) { ... } @@ -7689,12 +7689,12 @@ public static RowN row(Object... values) { ... }]]>

    See the relevant sections for more details about how to use row value expressions in predicates.

    - +

    Using row value expressions in UPDATE statements

    The also supports a variant where row value expressions are updated, rather than single columns. See the relevant section for more details

    - +

    Higher-degree row value expressions

    jOOQ chose to explicitly support degrees up to {max-row-degree} to match Scala's typesafe tuple, function and product support. Unlike Scala, however, jOOQ also supports higher degrees without the additional typesafety. @@ -7718,7 +7718,7 @@ public static RowN row(Object... values) { ... }]]>

  • The of a
  • The 's ON clause
  • - +

    Boolean types in SQL

    Before SQL:1999, boolean types did not really exist in SQL. They were modelled by 0 and 1 numeric/char values. With SQL:1999, true booleans were introduced and are now supported by most databases. In short, these are possible boolean values: @@ -7814,7 +7814,7 @@ Condition combined2 = combined1.andNot(c); // The left-hand side of the AND NOT

    Here are all boolean operators on the interface:

    - + < to test for being strictly less
  • <= to test for being less or equal
  • - +

    Unfortunately, Java does not support operator overloading, hence these operators are also implemented as methods in jOOQ, like any other SQL syntax elements. The relevant parts of the interface are these:

    - + ); // = (some column expression) eq or equal(Select>); // = (some scalar SELECT statement) @@ -7876,12 +7876,12 @@ ge or greaterOrEqual(Select>); // >= (some scalar SELECT st

    Note that every operator is represented by two methods. A verbose one (such as equal()) and a two-character one (such as eq()). Both methods are the same. You may choose either one, depending on your taste. The manual will always use the more verbose one.

    - +

    jOOQ's convenience methods using comparison operators

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using comparison predicates:

    - +
    - +
    Boolean operator precedence @@ -7908,7 +7908,7 @@ BOOK.TITLE.notEqualIgnoreCase("animal farm")]]>

    In SQL, the two expressions wouldn't be the same, as SQL natively knows operator precedence.

    - + A AND B OR C AND D OR E -- Precedence is applied (((A AND B) OR C) AND D) OR E -- Precedence is overridden @@ -7922,7 +7922,7 @@ BOOK.TITLE.notEqualIgnoreCase("animal farm")]]>

    All variants of the that we've seen in the previous chapter also work for . If your database does not support row value expression comparison predicates, jOOQ emulates them the way they are defined in the SQL standard:

    - + (X, Y))]]>

    jOOQ supports all of the above row value expression comparison predicates, both with and at the right-hand side:

    - +
    - +
    Quantified comparison predicate @@ -8019,7 +8019,7 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    It is interesting to note that the SQL standard defines the in terms of the ANY-quantified predicate. The following two expressions are equivalent:

    - + @@ -8030,14 +8030,14 @@ BOOK.PUBLISHED_IN.greaterThan(all(1920, 1940));]]>

    - +
    NULL predicate

    In SQL, you cannot compare NULL with any value using , as the result would yield NULL again, which is neither TRUE nor FALSE (see also the manual's section about ). In order to test a for NULL, use the NULL predicate as such:

    - + @@ -8075,7 +8075,7 @@ NOT((A, B) IS NOT NULL)]]>

    The SQL standard contains a nice truth table for the above rules:

    - + +-----------------------+-----------+---------------+---------------+-------------------+ | Expression | R IS NULL | R IS NOT NULL | NOT R IS NULL | NOT R IS NOT NULL | +-----------------------+-----------+---------------+---------------+-------------------+ @@ -8089,13 +8089,13 @@ NOT((A, B) IS NOT NULL)]]>

    In jOOQ, you would simply use the isNull() and isNotNull() methods on row value expressions. Again, as with the , the row value expression NULL predicate is emulated by jOOQ, if your database does not natively support it:

    - +
    - +
    DISTINCT predicate @@ -8122,7 +8122,7 @@ BOOK.TITLE.isNotDistinctFrom(BOOK.SUB_TITLE)]]>

    If your database does not natively support the DISTINCT predicate, jOOQ emulates it with an equivalent , modelling the above truth table:

    - + ... or better, if the INTERSECT set operation is supported:

    - + - +
    @@ -8163,7 +8163,7 @@ EXISTS(SELECT a INTERSECT SELECT b)

    The BETWEEN predicate can be seen as syntactic sugar for a pair of . According to the SQL standard, the following two predicates are equivalent:

    - + = [B] AND [A] <= [C]]]> @@ -8184,7 +8184,7 @@ BOOK.PUBLISHED_IN.notBetween(1920).and(1940)]]>

    The SQL standard defines the SYMMETRIC keyword to be used along with BETWEEN to indicate that you do not care which bound of the range is larger than the other. A database system should simply swap range bounds, in case the first bound is greater than the second one. jOOQ supports this keyword as well, emulating it if necessary.

    - + @@ -8195,7 +8195,7 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The emulation is done trivially:

    - + @@ -8210,27 +8210,27 @@ BOOK.PUBLISHED_IN.notBetweenSymmetric(1940).and(1920)]]>

    The SQL BETWEEN predicate also works well for . Much like the , it is defined in terms of a pair of regular :

    - + = [B] AND [A] <= [C] ([A] >= [B] AND [A] <= [C]) OR ([A] >= [C] AND [A] <= [B])]]> - +

    The above can be factored out according to the rules listed in the manual's section about .

    - +

    jOOQ supports the BETWEEN [SYMMETRIC] predicate and emulates it in all SQL dialects where necessary. An example is given here:

    - + - + - +
    LIKE predicate @@ -8251,7 +8251,7 @@ TITLE NOT LIKE '%abc%']]> - +

    Escaping operands with the LIKE predicate

    Often, your pattern may contain any of the wildcard characters "_" and "%", in case of which you may want to escape them. jOOQ does not automatically escape patterns in like() and notLike() methods. Instead, you can explicitly define an escape character as such: @@ -8270,12 +8270,12 @@ BOOK.TITLE.notLike("%The !%-Sign Book%", '!')]]>

    Please refer to your database manual for more details about escaping patterns with the LIKE predicate.

    - +

    jOOQ's convenience methods using the LIKE predicate

    In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using the LIKE predicate. Typical operations are "contains predicates", "starts with predicates", "ends with predicates", etc. Here is the full convenience API wrapping LIKE predicates:

    - + >) // Construct a NOT IN predicate from a subse

    A sample IN predicate might look like this:

    - + @@ -8328,12 +8328,12 @@ TITLE NOT IN ('Animal Farm', '1984')]]>
    BOOK.TITLE.notIn("Animal Farm", "1984")]]>
    - +

    NOT IN and NULL values

    Beware that you should probably not have any NULL values in the right hand side of a NOT IN predicate, as the whole expression would evaluate to NULL, which is rarely desired. This can be shown informally using the following reasoning:

    - + -- The following conditional expressions are formally or informally equivalent A NOT IN (B, C) A != ANY(B, C) @@ -8374,7 +8374,7 @@ NULL -- [ANY] AND NULL yields NULL -- Using a subselect (BOOK.ID, BOOK.TITLE) IN ( SELECT T.ID, T.TITLE - FROM T + FROM T )]]> - +

    In both cases, i.e. when using an IN list or when using a subselect, the type of the predicate is checked. Both sides of the predicate must be of equal degree and row type.

    - +

    - Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value. + Emulation of the IN predicate where row value expressions aren't well supported is currently only available for IN predicates that do not take a subselect as an IN predicate value.

    - +
    EXISTS predicate @@ -8408,7 +8408,7 @@ row(BOOK.ID, BOOK.TITLE).in(
  • From a using
  • From a using , and from other clauses
  • - +

    An example of an EXISTS predicate can be seen here:

    @@ -8427,7 +8427,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

    - +

    Performance of IN vs. EXISTS

    In theory, the two types of predicates can perform equally well. If your database system ships with a sophisticated cost-based optimiser, it will be able to transform one predicate into the other, if you have all necessary constraints set (e.g. referential constraints, not null constraints). However, in reality, performance between the two might differ substantially. An interesting blog post investigating this topic on the MySQL database can be seen here:
    @@ -8435,7 +8435,7 @@ notExists(create.selectOne().from(BOOK)

    - +
    OVERLAPS predicate @@ -8473,7 +8473,7 @@ row(Date.valueOf('2010-01-01'), new DayToSecond(2)).overlaps(Date.valueOf('2010-

    Unlike the standard (or any database implementing the standard), jOOQ also supports the OVERLAPS predicate for comparing arbitrary . For instance, (1, 3) OVERLAPS (2, 4) will yield true in jOOQ. This is emulated as such

    - +
    - +
    Dynamic SQL

    In most cases, , , and as introduced in the previous chapters will be embedded into different SQL statement clauses as if the statement were a static SQL statement (e.g. in a view or stored procedure):

    - + - +

    It is, however, interesting to think of all of the above expressions as what they are: expressions. And as such, nothing keeps users from extracting expressions and referencing them from outside the statement. The following statement is exactly equivalent:

    @@ -8517,26 +8517,26 @@ create.select(select) .groupBy(groupBy) .orderBy() .fetch();]]> - +

    Each individual expression, and collection of expressions can be seen as an independent entity that can be

    - +
    1. Constructed dynamically
    2. Reused across queries
    - +

    Dynamic construction is particularly useful in the case of the , for dynamic predicate building. For instance:

    - +

    The dynamic SQL building power may be one of the biggest advantages of using a runtime query model like the one offered by jOOQ. Queries can be created dynamically, of arbitrary complexity. In the above example, we've just constructed a dynamic . The same can be done for any other clauses, including dynamic , or adding additional as needed.

    @@ -8572,7 +8572,7 @@ create.select()
  • - +

    You'll probably find other examples. If verbosity scares you off, don't worry. The verbose use-cases for jOOQ are rather rare, and when they come up, you do have an option. Just write SQL the way you're used to!

    @@ -8602,7 +8602,7 @@ Condition condition(String sql, Object... bindings); // Construct a condition taking other jOOQ object arguments // Example: condition("a = {0}", val(1)); 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 DSL:

    @@ -8660,7 +8660,7 @@ Result fetch(String sql, QueryPart... parts);]]>

    Apart from the general factory methods, plain SQL is also available in various other contexts. For instance, when adding a .where("a = b") clause to a query. Hence, there exist several convenience methods where plain SQL can be inserted usefully. This is an example displaying all various use-cases in one single query:

    - + LAST_NAME = create.field("a.LAST_NAME"); @@ -8781,7 +8781,7 @@ Name name = name("AUTHOR", "TITLE");]]> On a JDBC level, you can also reuse the SQL string and prepared statement object instead of constructing it again, as you can bind new values to the prepared statement. jOOQ currently does not cache prepared statements, internally. - +

    The following sections explain how you can introduce bind values in jOOQ, and how you can control the way they are rendered and bound to SQL.

    @@ -8794,7 +8794,7 @@ Name name = name("AUTHOR", "TITLE");]]>

    JDBC only knows indexed bind values. A typical example for using bind values with JDBC is this:

    - + With dynamic SQL, keeping track of the number of question marks and their corresponding index may turn out to be hard. jOOQ abstracts this and lets you provide the bind value right where it is needed. A trivial example is this:

    - + 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

    Should you decide to run the above query outside of jOOQ, using your own , you can do so as follows:

    - + select = create.select().from(BOOK).where(BOOK.ID.equal(5)).and(BOOK.TITLE.equal("Animal Farm")); // Render the SQL statement: @@ -8947,25 +8947,25 @@ create.select()
    SQL injection - +

    SQL injection is serious

    SQL injection is a serious problem that needs to be taken care of thoroughly. A single vulnerability can be enough for an attacker to dump your whole database, and potentially seize your database server. We've blogged about the severity of this threat on the jOOQ blog.

    - +

    SQL injection happens because a programming language (SQL) is used to dynamically create arbitrary server-side statements based on user input. Programmers must take lots of care not to mix the language parts (SQL) with the user input ()

    - +

    SQL injection in jOOQ

    With jOOQ, SQL is usually created via a type safe, non-dynamic Java abstract syntax tree, where bind variables are a part of that abstract syntax tree. It is not possible to expose SQL injection vulnerabilities this way.

    - +

    However, jOOQ offers convenient ways of introducing in various places of the jOOQ API (which are annotated using since jOOQ 3.6). While jOOQ's API allows you to specify bind values for use with plain SQL, you're not forced to do that. For instance, both of the following queries will lead to the same, valid result:

    - +

    A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] FROM AUTHOR JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID @@ -9108,15 +9108,15 @@ public final void accept(Context context) {

    As mentioned in the previous chapter about , there are some elements in the that are used for formatting / pretty-printing rendered SQL. In order to obtain pretty-printed SQL, just use the following :

    - - + +

    And then, use the above DSLContext to render pretty-printed SQL:

    - + A simple example can be provided by checking out jOOQ's internal representation of a (simplified) . It is used for any comparing two fields as for example the AUTHOR.ID = BOOK.AUTHOR_ID condition here:

    - + -- [...] WHERE AUTHOR.ID = ? -- [...] @@ -9209,11 +9209,11 @@ public final void bind(BindContext context) throws DataAccessException {

    Converters

    - +

    The simplest use-case of injecting custom data types is by using . A Converter can convert from a database type <T> to a user-defined type <U> and vice versa. You'll be implementing this SPI:

    - + { // Your conversion logic goes into these two methods, that can convert @@ -9224,8 +9224,8 @@ public final void bind(BindContext context) throws DataAccessException { // You need to provide Class instances for each type, too: Class fromType(); Class toType(); -}]]> - +}]]> +

    If, for instance, you want to use Java 8's for SQL DATE and for SQL TIMESTAMP, you write a converter like this:

    @@ -9256,14 +9256,14 @@ public class LocalDateConverter implements Converter { public Class toType() { return LocalDate.class; } -}]]> +}]]>

    This converter can now be used in a variety of jOOQ API, most importanly to create a new data type:

    - + type = SQLDataType.DATE.asConvertedDataType(new LocalDateConverter());]]> - +

    And data types, in turn, can be used with any , i.e. with any , including or based ones:

    @@ -9276,15 +9276,15 @@ Field date1 = DSL.field("my_table.my_column", type); // Name based Field date2 = DSL.field(name("my_table", "my_column"), type);]]> - +

    Bindings

    - +

    While converters are very useful for simple use-cases, is useful when you need to customise data type interactions at a JDBC level, e.g. when you want to bind a PostgreSQL JSON data type. Custom bindings implement the following SPI:

    - + extends Serializable { // A converter that does the conversion between the database type T @@ -9304,11 +9304,11 @@ Field date2 = DSL.field(name("my_table", "my_column"), type);]]> ctx) throws SQLException; void get(BindingGetSQLInputContext ctx) throws SQLException; }]]> - +

    Below is full fledged example implementation that uses Google Gson to model JSON documents in Java

    - + { public void get(BindingGetSQLInputContext ctx) throws SQLException { throw new SQLFeatureNotSupportedException(); } -}]]> - +}]]> +

    Code generation

    There is a special section in the manual explaining how to automatically tie your Converters and Bindings to your generated code. The relevant sections are:

    - +
    - +
    Custom syntax elements

    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:

    - + extends AbstractField {} public abstract class CustomCondition extends AbstractCondition {} public abstract class CustomTable> extends TableImpl {} @@ -9419,7 +9419,7 @@ public abstract class CustomRecord> extends TableRecord

    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 method, as discussed before:

    - + 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 showing how to create a field multiplying another field by 2

    - + IDx2 = new CustomField(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(" * ?"); @@ -9459,10 +9459,10 @@ final Field IDx2 = new CustomField(BOOK.ID.getName(), BOOK.ID. @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(DSL.val(2)); } @@ -9481,7 +9481,7 @@ create.select(IDx2).from(BOOK);]]>

    Many vendor-specific functions are not officially supported by jOOQ, but you can implement such support yourself using CustomField, for instance. Here's an example showing how to implement Oracle's TO_CHAR() function, emulating it in SQL Server using CONVERT():

    - + { @@ -9518,7 +9518,7 @@ class ToChar extends CustomField {

    The above CustomField implementation can be exposed from your own custom DSL class:

    - + toChar(Field field, String format) { return new ToChar(field, DSL.inline(format)); @@ -9526,7 +9526,7 @@ class ToChar extends CustomField { }]]>
    - +
    Plain SQL QueryParts @@ -9540,10 +9540,10 @@ class ToChar extends CustomField {

    The above distinction is best explained using an example:

    - + Note that for historic reasons the two API usages can also be mixed, although this is not recommended and the exact behaviour is unspecified.

    - +

    Plain SQL templating specification

    - +

    Templating with QueryPart placeholders (or bind value placeholders) requires a simple parsing logic to be applied to SQL strings. The jOOQ template parser behaves according to the following rules:

    @@ -9578,13 +9578,13 @@ create.selectFrom(BOOK).where(
  • QueryPart placeholders ({number}) are replaced by the matching QueryPart.
  • Keywords ({identifier}) are treated like keywords and rendered in the correct case according to .
  • - +

    Tools for templating

    - +

    A variety of API is provided to create template elements that are intended for use with the above templating mechanism. These tools can be found in

    - +

    - +
    Custom SQL transformation @@ -9630,7 +9630,7 @@ create.attach(select);]]> With jOOQ 3.2's SPI, it is possible to perform custom SQL transformation to implement things like shared-schema multi-tenancy, or a security layer centrally preventing access to certain data. This SPI is extremely powerful, as you can make ad-hoc decisions at runtime regarding local or global transformation of your SQL statement. The following sections show a couple of simple, yet real-world use-cases.

    - +
    Logging abbreviated bind values @@ -9638,7 +9638,7 @@ create.attach(select);]]>

    When implementing a logger, one needs to carefully assess how much information should really be disclosed on what logger level. In log4j and similar frameworks, we distinguish between FATAL, ERROR, WARN, INFO, DEBUG, and TRACE. In DEBUG level, jOOQ's logs all executed statements including inlined bind values as such:

    - + with bind values : select * from "BOOK" where "BOOK"."TITLE" like 'How I stopped worrying%']]> @@ -9654,7 +9654,7 @@ public class BindValueAbbreviator extends DefaultVisitListener { @Override public void visitStart(VisitContext context) { - + // Transform only when rendering values if (context.renderContext() != null) { QueryPart part = context.queryPart(); @@ -9668,16 +9668,16 @@ public class BindValueAbbreviator extends DefaultVisitListener { // e.g. using commons-lang's StringUtils.abbreviate() if (value instanceof String && ((String) value).length() > maxLength) { anyAbbreviations = true; - + // ... and replace it in the current rendering context (not in the Query) context.queryPart(val(abbreviate((String) value, maxLength))); } - + // If the bind value is a byte[] (or Blob) of a given length, abbreviate it // e.g. by removing bytes from the array else if (value instanceof byte[] && ((byte[]) value).length > maxLength) { anyAbbreviations = true; - + // ... and replace it in the current rendering context (not in the Query) context.queryPart(val(Arrays.copyOf((byte[]) value, maxLength))); } @@ -9687,10 +9687,10 @@ public class BindValueAbbreviator extends DefaultVisitListener { @Override public void visitEnd(VisitContext context) { - + // If any abbreviations were performed before... if (anyAbbreviations) { - + // ... and if this is the top-level QueryPart, then append a SQL comment to indicate the abbreviation if (context.queryPartsLength() == 1) { context.renderContext().sql(" -- Bind values may have been abbreviated"); @@ -9722,7 +9722,7 @@ public class BindValueAbbreviator extends DefaultVisitListener {

    jOOQ includes a SQL parser API (EXPERIMENTAL in jOOQ 3.9), which allows for parsing a SQL String into a of a specified type, including:

    - +
    • A set of
    • A single
    • @@ -9730,11 +9730,11 @@ public class BindValueAbbreviator extends DefaultVisitListener {
    • A
    • A
    - +

    The current implementation of the parser is dialect agnostic and will try to parse any SQL dialect into a standard jOOQ expression tree, for instance:

    - + jOOQ-Scala is a maven module used for leveraging some advanced Scala features for those users that wish to use jOOQ with Scala.

    - +

    Using Scala's implicit defs to allow for operator overloading

    The most obvious Scala feature to use in jOOQ are implicit defs for implicit conversions in order to enhance the type with SQL-esque operators. @@ -9760,7 +9760,7 @@ assertEquals(ctx.select(inline(1)), ctx.parser().parseQuery("select 1 from dual"

    The following depicts a trait which wraps all fields:

    - + The following depicts a trait which wraps numeric fields:

    - + An example query using such overloaded operators would then look like this:

    - +

    In a previous section of the manual, we've seen how jOOQ can be used to that can be executed with any API including JDBC or ... jOOQ. This section of the manual deals with various means of actually executing SQL with jOOQ.

    - +

    SQL execution with JDBC

    JDBC calls executable objects "". It distinguishes between three types of statements: @@ -9900,7 +9900,7 @@ fetch]]>

    Today, the JDBC API may look weird to users being used to object-oriented design. While statements hide a lot of SQL dialect-specific implementation details quite well, they assume a lot of knowledge about the internal state of a statement. For instance, you can use the method, to add a the prepared statement being created to an "internal list" of batch statements. Instead of returning a new type, this method forces user to reflect on the prepared statement's internal state or "mode".

    - +

    jOOQ is wrapping JDBC

    These things are abstracted away by jOOQ, which exposes such concepts in a more object-oriented way. For more details about jOOQ's batch query execution, see the manual's section about . @@ -9908,7 +9908,7 @@ fetch]]>

    The following sections of this manual will show how jOOQ is wrapping JDBC for SQL execution

    - +

    Alternative execution modes

    Just because you can, doesn't mean you must. At the end of this chapter, we'll show how you can use jOOQ to generate SQL statements that are then executed with other APIs, such as Spring's JdbcTemplate, or Hibernate. For more information see the . @@ -9927,7 +9927,7 @@ fetch]]>

  • Both APIs return the number of affected records in non-result queries. JDBC: , jOOQ:
  • Both APIs return a scrollable result set type from result queries. JDBC: , jOOQ:
  • - +

    Differences to JDBC

    Some of the most important differences between JDBC and jOOQ are listed here: @@ -9943,14 +9943,14 @@ fetch]]>

    - +
    Query vs. ResultQuery

    Unlike JDBC, jOOQ has a lot of knowledge about a SQL query's structure and internals (see the manual's section about ). Hence, jOOQ distinguishes between these two fundamental types of queries. While every can be executed, only can return results (see the manual's section about to learn more about fetching results). With plain SQL, the distinction can be made clear most easily:

    - + result = resultQuery.fetch();]]>
  • : Some databases allow for returning many result sets from a single query. JDBC can handle this but it's very verbose. A list of results should be returned instead.
  • : Some queries take too long to execute to wait for their results. You should be able to spawn query execution in a separate process.
  • - +

    Convenience and how ResultQuery, Result, and Record share API

    The term "fetch" is always reused in jOOQ when you can fetch data from the database. An provides many overloaded means of fetching data:

    - +

    Various modes of fetching

    These modes of fetching are also documented in subsequent sections of the manual

    - + fetch(); @@ -10016,7 +10016,7 @@ List> fetchMany(); // Execute a ResultQuery with jOOQ, but return a JDBC ResultSet, not a jOOQ object ResultSet fetchResultSet();]]> - +

    Fetch convenience

    These means of fetching are also available from and APIs @@ -10062,11 +10062,11 @@ ResultSet fetchResultSet();]]>

    These means of fetching are also available from and APIs

    - + Map fetchMap(Field key); Map fetchMap(Field key, Field value); @@ -10106,7 +10106,7 @@ ResultSet fetchResultSet();]]>

    Yet, still, sometimes you wish to use strongly typed records, when you know that you're selecting only from a single table:

    - +

    Fetching strongly or weakly typed records

    When fetching data only from a single table, the type is known to jOOQ if you use jOOQ's to generate for your database tables. In order to fetch such strongly typed records, you will have to use the : @@ -10118,7 +10118,7 @@ BookRecord book = create.selectFrom(BOOK).where(BOOK.ID.equal(1)).fetchOne(); // Typesafe field access is now possible: 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:

    @@ -10126,11 +10126,11 @@ System.out.println("Published in: " + book.getPublishedIn());]]>
  • - +

    Mapping custom row types to strongly typed records

    - +

    Sometimes, you may want to explicitly select only a subset of your columns, but still use strongly typed records. Alternatively, you may want to join a one-to-one relationship and receive the two individual strongly typed records after the join.

    @@ -10191,7 +10191,7 @@ System.out.println("Author : " + author.getFirstName() + " " + author.getLa

    By default, jOOQ returns an object, which is essentially a of . Often, you will find yourself wanting to transform this result object into a type that corresponds more to your specific needs. Or you just want to list all values of one specific column. Here are some examples to illustrate those use cases:

    - + titles1 = create.select().from(BOOK).fetch().getValues(BOOK.TITLE); List titles2 = create.select().from(BOOK).fetch(BOOK.TITLE); @@ -10226,7 +10226,7 @@ Map> group4 = create.selectFrom(BOOK).fetchGroups(BO

    In a more functional operating mode, you might want to write callbacks that receive records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + () {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -10261,7 +10261,7 @@ create.selectFrom(BOOK)

    In a more functional operating mode, you might want to write callbacks that map records from your select statement results in order to do some processing. This is a common data access pattern in Spring's JdbcTemplate, and it is also available in jOOQ. With jOOQ, you can implement your own classes and plug them into jOOQ's :

    - + ids = create.selectFrom(BOOK) @@ -10273,12 +10273,12 @@ create.selectFrom(BOOK) return book.getId(); } }); - + // Or more concisely create.selectFrom(BOOK) .orderBy(BOOK.ID) .fetch(new RecordMapper() {...}); - + // Or even more concisely with Java 8's lambda expressions: create.selectFrom(BOOK) .orderBy(BOOK.ID) @@ -10304,7 +10304,7 @@ create.selectFrom(BOOK)

    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. See the manual's section about to see how to modify jOOQ's standard POJO mapping behaviour.

    - +

    Using JPA-annotated POJOs

    jOOQ tries to find JPA annotations on your POJO types. If it finds any, they are used as the primary source for mapping meta-information. Only the annotation is used and understood by jOOQ. An example: @@ -10314,7 +10314,7 @@ create.selectFrom(BOOK) public class MyBook { @Column(name = "ID") public int myId; - + @Column(name = "TITLE") public String myTitle; } @@ -10323,16 +10323,16 @@ public class MyBook { MyBook myBook = create.select().from(BOOK).fetchAny().into(MyBook.class); List myBooks = create.select().from(BOOK).fetch().into(MyBook.class); List myBooks = create.select().from(BOOK).fetchInto(MyBook.class);]]> - +

    Just as with any other JPA implementation, you can put the annotation on any class member, including attributes, setters and getters. Please refer to the Javadoc for more details.

    - +

    Using simple POJOs

    If jOOQ does not find any JPA-annotations, columns are mapped to the "best-matching" constructor, attribute or setter. An example illustrates this:

    - + myBooks = create.select().from(BOOK).fetchInto(MyBook1.class);]]><

    Please refer to the Javadoc for more details.

    - +

    Using "immutable" POJOs

    If jOOQ does not find any default constructor, columns are mapped to the "best-matching" constructor. This allows for using "immutable" POJOs with jOOQ. An example illustrates this:

    - + myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchInto( public class MyBook3 { public final String title; public final int id; - + @ConstructorProperties({ "title", "id"}) public MyBook2(String title, int id) { this.title = title; @@ -10387,7 +10387,7 @@ MyBook3 myBook = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchA List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetch().into(MyBook3.class); List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchInto(MyBook3.class); ]]> - +

    Please refer to the Javadoc for more details.

    @@ -10396,12 +10396,12 @@ List myBooks = create.select(BOOK.ID, BOOK.AUTHOR_ID).from(BOOK).fetchI

    jOOQ also allows for fetching data into abstract classes or interfaces, or in other words, "proxyable" types. This means that jOOQ will return a wrapped in a implementing your custom type. An example of this is given here:

    - + - +

    Note: Because of your manual setting of ID = 10, jOOQ's store() method will asume that you want to insert a new record. See the manual's section about for more details on this.

    - +

    Interaction with DAOs

    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: @@ -10468,21 +10468,21 @@ bookDao.update(book); // Delete it again bookDao.delete(book);]]> - +

    More complex data structures

    jOOQ currently doesn't support more complex data structures, the way Hibernate/JPA attempt to map relational data onto POJOs. While future developments in this direction are not excluded, jOOQ claims that generic mapping strategies lead to an enormous additional complexity that only serves very few use cases. You are likely to find a solution using any of jOOQ's various , with only little boiler-plate code on the client side.

    - +
    POJOs with RecordMappers

    In the previous sections we have seen how to create types to map jOOQ records onto arbitrary objects. We have also seen how jOOQ provides default algorithms to map jOOQ records onto . Your own custom domain model might be much more complex, but you want to avoid looking up the most appropriate RecordMapper every time you need one. For this, you can provide jOOQ's with your own implementation of the interface. An example is given here:

    - + } } } - + // Books might be joined with their authors, create a 1:1 mapping if (type == Book.class) { return new BookMapper(); @@ -10519,12 +10519,12 @@ bookDao.delete(book);]]>

    The above is a very simple example showing that you will have complete flexibility in how to override jOOQ's record to POJO mapping mechanisms.

    - +

    Using third party libraries

    A couple of useful libraries exist out there, which implement custom, more generic mapping algorithms. Some of them have been specifically made to work with jOOQ. Among them are:

    - +
    • ModelMapper (with an explicit jOOQ integration)
    • SimpleFlatMapper (with an explicit jOOQ integration)
    • @@ -10539,14 +10539,14 @@ bookDao.delete(book);]]>

      Unlike JDBC's , jOOQ's does not represent an open database cursor with various fetch modes and scroll modes, that needs to be closed after usage. jOOQ's results are simple in-memory Java objects, containing all of the result values. If your result sets are large, or if you have a lot of network latency, you may wish to fetch records one-by-one, or in small chunks. jOOQ supports a type for that purpose. In order to obtain such a reference, use the method. An example is given here:

      - + cursor = create.selectFrom(BOOK).fetchLazy()) { // Cursor has similar methods as Iterator while (cursor.hasNext()) { BookRecord book = cursor.fetchOne(); - + Util.doThingsWithBook(book); } }]]> @@ -10554,7 +10554,7 @@ try (Cursor cursor = create.selectFrom(BOOK).fetchLazy()) {

      As a holds an internal reference to an open , it may need to be closed at the end of iteration. If a cursor is completely scrolled through, it will conveniently close the underlying ResultSet. However, you should not rely on that.

      - +

      Cursors ship with all the other fetch features

      Like or , gives access to all of the other fetch features that we've seen so far, i.e. @@ -10574,7 +10574,7 @@ try (Cursor cursor = create.selectFrom(BOOK).fetchLazy()) {

      jOOQ 3.7+ supports Java 8, and with Java 8, it supports . This opens up a range of possibilities of combining the declarative aspects of SQL with the functional aspects of the new Stream API. Much like , such a Stream keeps an internal reference to a JDBC , which means that the Stream has to be treated like a resource. Here's an example of using such a stream:

      - + stream = create.selectFrom(BOOK).stream()) { stream.forEach(Util::doThingsWithBook); @@ -10619,7 +10619,7 @@ try (Stream stream = create.selectFrom(BOOK).stream()) { " " + col.getValue()) .collect(Collectors.joining(",\n")) ); - + System.out.println(");"); });]]> @@ -10660,7 +10660,7 @@ CREATE TABLE COLUMNS( REMARKS VARCHAR, SOURCE_DATA_TYPE SMALLINT );]]> - +
    @@ -10692,7 +10692,7 @@ CREATE TABLE COLUMNS(

    The correct (and verbose) way to do this with JDBC is as follows:

    - +

    As previously discussed in the chapter about , jOOQ does not rely on an internal state of any JDBC object, which is "externalised" by Javadoc. Instead, it has a straight-forward API allowing you to do the above in a one-liner:

    - + @@ -10733,22 +10733,22 @@ Results results = create.fetchMany("sp_help 'author'");]]> Later fetching

    Using Java 8 CompletableFutures

    - +

    Java 8 has introduced the new type, which allows for functional composition of asynchronous execution units. When applying this to SQL and jOOQ, you might be writing code as follows:

    - + + .supplyAsync(() -> DSL.using(configuration) .insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .values(3, "Hitchcock") .execute() ) - + // This will supply an AuthorRecord value for the newly inserted author .handleAsync((rows, throwable) -> DSL.using(configuration) @@ -10761,30 +10761,30 @@ CompletableFuture record.changed(true); return record.insert(); }) - + // This will supply an int value indicating the number of deleted rows - .handleAsync((rows, throwable) -> + .handleAsync((rows, throwable) -> DSL.using(configuration) .delete(AUTHOR) .where(AUTHOR.ID.eq(3)) .execute() ) .join();]]> - +

    The above example will execute four actions one after the other, but asynchronously in the JDK's default or common . -

    - +

    +

    For more information, please refer to the Javadoc and official documentation. -

    - +

    +

    Using deprecated API

    - +

    Some queries take very long to execute, yet they are not crucial for the continuation of the main program. For instance, you could be generating a complicated report in a Swing application, and while this report is being calculated in your database, you want to display a background progress bar, allowing the user to pursue some other work. This can be achived simply with jOOQ, by creating a , a type that extends . An example is given here:

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(); @@ -10800,7 +10800,7 @@ Result result = future.get();]]>

    Note, that instead of letting jOOQ spawn a new thread, you can also provide jOOQ with your own :

    - + future = create.selectFrom(BOOK).where(... complex predicates ...).fetchLater(service);]]> @@ -10814,7 +10814,7 @@ FutureResult future = create.selectFrom(BOOK).where(... complex pred

    When interacting with legacy applications, you may prefer to have jOOQ return a , rather than jOOQ's own types. This can be done simply, in two ways:

    - + cursor = create.fetchLazy(rs);]]>

    You can also tighten the interaction with jOOQ's data type system and features, by passing the record type to the above fetch methods:

    - + result = create.fetch (rs, Integer.class, String.class); Cursor result = create.fetchLazy(rs, Integer.class, String.class); @@ -10878,7 +10878,7 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Apart from a few extra features (), jOOQ only supports basic types as supported by the JDBC API. In your application, you may choose to transform these data types into your own ones, without writing too much boiler-plate code. This can be done using jOOQ's types. A converter essentially allows for two-way conversion between two Java data types <T> and <U>. By convention, the <T> type corresponds to the type in your database whereas the <U> type corresponds to your own user type. The Converter API is given here:

    - + extends Serializable { /** @@ -10905,12 +10905,12 @@ Cursor result = create.fetchLazy(rs, BOOK.ID, BOOK.TITLE);]]> Such a converter can be used in many parts of the jOOQ API. Some examples have been illustrated in the manual's section about .

    - +

    A Converter for GregorianCalendar

    Here is a some more elaborate example involving a Converter for :

    - + { @@ -10941,12 +10941,12 @@ public class CalendarConverter implements Converter dates1 = create.selectFrom(BOOK).fetch().getValues(BOOK.PUBLISHING_DATE, new CalendarConverter()); List dates2 = create.selectFrom(BOOK).fetch(BOOK.PUBLISHING_DATE, new CalendarConverter()); ]]> - +

    Enum Converters

    jOOQ ships with a built-in default , that you can use to map VARCHAR values to enum literals or NUMBER values to enum ordinals (both modes are supported). Let's say, you want to map a YES / NO / MAYBE column to a custom Enum:

    - + - +

    Using Converters in generated source code

    jOOQ also allows for generated source code to reference your own custom converters, in order to permanently replace a <T> type by your own, custom <U> type. See the manual's section about for details. @@ -11008,20 +11008,20 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE) .join(AUTHOR).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) .intern(BOOK.AUTHOR_ID) .fetch();]]> - +

    You can specify as many fields as you want for interning. The above has the following effect:

    - +
    • If the interned Field is of type , then is called upon each string
    • If the interned Field is of any other type, then the call is ignored
    - +

    Future versions of jOOQ will implement interning of data for non-String data types by collecting values in , removing duplicate instances.

    - +

    Note, that jOOQ will not use interned data for identity comparisons: string1 == string2. Interning is used only to reduce the memory footprint of objects.

    @@ -11029,7 +11029,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)
    - +
    Static statements vs. Prepared Statements @@ -11039,7 +11039,7 @@ Result r1 = create.select(BOOK.ID, BOOK.AUTHOR_ID, BOOK.TITLE)

    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:

    - + @@ -11069,7 +11069,7 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    Whichever aproach is more optimal for you cannot be decided by jOOQ. In most cases, prepared statements are probably better. But you always have the option of forcing jOOQ to render inlined bind values.

    - +

    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 @@ -11083,15 +11083,15 @@ inlined.select(val(1)).where(val(1).equal(1)).fetch();]]>

    As previously discussed in the chapter about , reusing PreparedStatements is handled a bit differently in jOOQ from how it is handled in JDBC

    - +

    Keeping open PreparedStatements with JDBC

    With JDBC, you can easily reuse a by not closing it between subsequent executions. An example is given here:

    - + The above technique can be quite useful when you want to reuse expensive database resources. This can be the case when your statement is executed very frequently and your database would take non-negligible time to soft-parse the prepared statement and generate a new statement / cursor resource.

    - +

    Keeping open PreparedStatements with jOOQ

    This is also modeled in jOOQ. However, the difference to JDBC is that closing a statement is the default action, whereas keeping it open has to be configured explicitly. This is better than JDBC, because the default action should be the one that is used most often. Keeping open statements is rarely done in average applications. Here's an example of how to keep open PreparedStatements with jOOQ:

    - + query = create.selectOne().keepStatement(true)) { Result result1 = query.fetch(); // This will lazily create a new PreparedStatement @@ -11126,7 +11126,7 @@ try (ResultQuery query = create.selectOne().keepStatement(true)) {

    JDBC knows a couple of execution flags and modes, which can be set through the jOOQ API as well. jOOQ essentially supports these flags and execution modes:

    - + query = create.selectOne().keepStatement(true)) { // The query execution timeout. // ----------------------------------------------------------- Query queryTimeout(int timeout); - + }]]> - + extends Query { // [...] @@ -11159,25 +11159,25 @@ try (ResultQuery query = create.selectOne().keepStatement(true)) { // The maximum number of rows to be fetched by JDBC // ----------------------------------------------------------- ResultQuery maxRows(int rows); - + }]]>

    Using ResultSet concurrency with ExecuteListeners

    An example of why you might want to manually set a ResultSet's concurrency flag to something non-default is given here:

    - + - +

    In the above example, your custom is triggered before jOOQ loads a new Record from the JDBC ResultSet. With the concurrency being set to ResultSet.CONCUR_UPDATABLE, you can now modify the database cursor through the standard JDBC ResultSet API.

    @@ -11235,22 +11235,22 @@ try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO author(id stmt.setString(2, "Erich"); stmt.setString(3, "Gamma"); stmt.addBatch(); - + stmt.setInt(1, 2); stmt.setString(2, "Richard"); stmt.setString(3, "Helm"); stmt.addBatch(); - + stmt.setInt(1, 3); stmt.setString(2, "Ralph"); stmt.setString(3, "Johnson"); stmt.addBatch(); - + stmt.setInt(1, 4); stmt.setString(2, "John"); stmt.setString(3, "Vlissides"); stmt.addBatch(); - + int[] result = stmt.executeBatch(); }]]>
    @@ -11259,7 +11259,7 @@ try (PreparedStatement stmt = connection.prepareStatement("INSERT INTO author(id

    jOOQ supports executing queries in batch mode as follows:

    - + - +

    When creating a batch execution with a single query and multiple bind values, you will still have to provide jOOQ with dummy bind values for the original query. In the above example, these are set to null. For subsequent calls to bind(), there will be no type safety provided by jOOQ.

    @@ -11295,18 +11295,18 @@ create.batch(create.insertInto(AUTHOR, ID, FIRST_NAME, LAST_NAME ).values((Inte

    Instead of actually phrasing a select statement, you can also use the convenience methods:

    - + - +

    Inlining sequence references in SQL

    You can inline sequence references in jOOQ SQL statements. The following are examples of how to do that:

    - + The general distinction between (stored) procedures and (stored) functions can be summarised like this:

    - +

    Procedures

    • Are called using JDBC CallableStatement
    • Have no return value
    • Usually support OUT parameters
    - +

    Functions

    • Can be used in SQL statements
    • Have a return value
    • Usually don't support OUT parameters
    - +

    Exceptions to these rules

    • DB2, H2, and HSQLDB don't allow for JDBC escape syntax when calling functions. Functions must be used in a SELECT statement
    • @@ -11367,19 +11367,19 @@ create.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)

      To simplify things a little bit, jOOQ handles both procedures and functions the same way, using a more general type.

      - +

      Using jOOQ for standalone calls to stored procedures and functions

      If you're using jOOQ's , it will generate objects for you. Let's consider the following example:

      - +

      The generated artefacts can then be used as follows:

      - + - +

      But you can also call the procedure using a generated convenience method in a global Routines class:

      @@ -11406,7 +11406,7 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]>

      For more details about for procedures, see the manual's section about .

      - +

      Inlining stored function references in SQL

      Unlike procedures, functions can be inlined in SQL statements to generate or , if you're using . Assume you have a function like this: @@ -11414,11 +11414,11 @@ assertEquals(new BigDecimal("2"), procedure.getId();]]> - +

      The generated artefacts can then be used as follows:

      - + boolean exists = create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]> - +

      For more info about inlining stored function references in SQL statements, please refer to the manual's section about .

      @@ -11459,7 +11459,7 @@ create.select(authorExists("Paulo")).fetchOne(0, boolean.class);]]>

      Oracle UDTs can have object-oriented structures including member functions and procedures. With Oracle, you can do things like this:

      - + {"schema":"schema-n","table":"table-n","name":"field-n","type":"type-n"}], "records":[[value-1-1,value-1-2,...,value-1-n], [value-2-1,value-2-2,...,value-2-n]]} - +

      Note: This format has been modified in jOOQ 2.6.0 and 3.7.0

      @@ -11774,7 +11774,7 @@ Query query = error.query();]]>
    - +
    Importing JSON @@ -11808,7 +11808,7 @@ create.loadInto(BOOK)

    - +
    Importing Records @@ -11838,7 +11838,7 @@ DSL.using(configuration1)

    - +
    Importing Arrays @@ -11884,12 +11884,12 @@ DSL.using(configuration1)

    CRUD always uses the same patterns, regardless of the nature of underlying tables. This again, leads to a lot of boilerplate code, if you have to issue your statements yourself. Like Hibernate / JPA and other ORMs, jOOQ facilitates CRUD using a specific API involving types.

    - +

    Primary keys and updatability

    In normalised databases, every table has a primary key by which a tuple/record within that table can be uniquely identified. In simple cases, this is a (possibly auto-generated) number called ID. But in many cases, primary keys include several non-numeric columns. An important feature of such keys is the fact that in most databases, they are enforced using an index that allows for very fast random access to the table. A typical way to access / modify / delete a book is this:

    - + - +

    Normalised databases assume that a primary key is unique "forever", i.e. that a key, once inserted into a table, will never be changed or re-inserted after deletion. In order to use jOOQ's operations correctly, you should design your database accordingly.

    @@ -11910,7 +11910,7 @@ DELETE FROM BOOK WHERE ID = 5;]]>

    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:

    - + - +

    See the manual's section about for some more insight on "attached" objects.

    - +

    Storing

    Storing a record will perform an or an . In general, new records are always inserted, whereas records loaded from the database are always updated. This is best visualised in code: @@ -11949,7 +11949,7 @@ BookRecord book2 = create.fetchOne(BOOK, BOOK.ID.equal(id)); // Update the record: UPDATE BOOK SET TITLE = 'Animal Farm' WHERE ID = [id] book2.setTitle("Animal Farm"); book2.store();]]> - +

    Some remarks about storing:

    @@ -11959,18 +11959,18 @@ book2.store();]]>
  • When loading records from , jOOQ will assume the record is a new record. It will hence attempt to INSERT it.
  • When you activate , storing a record may fail, if the underlying database record has been changed in the mean time.
  • - +

    Deleting

    Deleting a record will remove it from the database. Here's how you delete records:

    - + - +

    Refreshing

    Refreshing a record from the database means that jOOQ will issue a to refresh all record values that are not the primary key. This is particularly useful when you use jOOQ's feature, in case a modified record is "stale" and cannot be stored to the database, because the underlying database record has changed in the mean time. @@ -11989,7 +11989,7 @@ book.refresh();]]>

    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 :

    - + The "original" value, i.e. the value as it was originally fetched from the database or null, if the record was never in the database
  • The "changed" flag, indicating if the value was ever changed through the Record API.
  • - +

    The purpose of the above information is for jOOQ's to know, which values need to be stored to the database, and which values have been left untouched.

    @@ -12025,19 +12025,19 @@ for (BookRecord book : create.fetch(BOOK, BOOK.PUBLISHED_IN.equal(1948))) {

    Many databases support the concept of IDENTITY values, or key values. This is reflected by JDBC's method. jOOQ abstracts using this method as many databases and JDBC drivers behave differently with respect to generated keys. Let's assume the following SQL Server BOOK table:

    - +

    If you're using jOOQ's , the above table will generate a with an IDENTITY column. This information is used by jOOQ internally, to update IDs after calling :

    - +

    and contain foreign key navigation methods. These navigation methods allow for "navigating" inbound or outbound foreign key references by executing an appropriate query. An example is given here:

    - + books = author.fetchChildren(FK_BOOK_AUTHOR);]]>

    Tables without a PRIMARY KEY are considered non-updatable by jOOQ, as jOOQ has no way of uniquely identifying such a record within the database. If you're using jOOQ's , such tables will generate classes, instead of classes. When you fetch from such a table, the returned records will not allow for calling any of the methods.

    - +

    Note, that some databases use internal rowid or object-id values to identify such records. jOOQ does not support these vendor-specific record meta-data.

    @@ -12168,7 +12168,7 @@ Result books = author.fetchChildren(FK_BOOK_AUTHOR);]]>
    - +

    Optimised optimistic locking using TIMESTAMP fields

    If you're using jOOQ's , you can take indicate TIMESTAMP or UPDATE COUNTER fields for every generated table in the . Let's say we have this table:

    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:

    - +

    As before, without the added TIMESTAMP column, optimistic locking is transparent to the API.

    - +

    Optimised optimistic locking using VERSION fields

    Instead of using TIMESTAMPs, you may also use numeric VERSION fields, containing version numbers that are incremented by jOOQ upon store() calls. @@ -12237,7 +12237,7 @@ book2.store();]]>

    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:

    - + books = create.fetch(BOOK); @@ -12253,7 +12253,7 @@ create.batchStore(books);]]>

    - +
    CRUD SPI: RecordListener @@ -12264,11 +12264,11 @@ create.batchStore(books);]]>
  • Adding a central ID generation algorithm, generating UUIDs for all of your records.
  • Adding a central record initialisation mechanism, preparing the database prior to inserting a new record.
  • - +

    An example of such a RecordListener is given here:

    - + - +

    Now, configure jOOQ's runtime to load your listener

    @@ -12308,7 +12308,7 @@ DSLContext create = DSL.using(configuration);]]>

    If you're using jOOQ's , you can configure it to generate and DAOs for you. jOOQ then generates one DAO per , i.e. per table with a single-column primary key. Generated DAOs implement a common jOOQ type called . This type contains the following methods:

    - + corresponds to the DAO's related table //

    corresponds to the DAO's related generated POJO type // corresponds to the DAO's related table's primary key type. @@ -12319,23 +12319,23 @@ public interface DAO, P, T> { void insert(P object) throws DataAccessException; void insert(P... objects) throws DataAccessException; void insert(Collection

    objects) throws DataAccessException; - + // These methods allow for updating POJOs based on their primary key void update(P object) throws DataAccessException; void update(P... objects) throws DataAccessException; void update(Collection

    objects) throws DataAccessException; - + // These methods allow for deleting POJOs based on their primary key void delete(P... objects) throws DataAccessException; void delete(Collection

    objects) throws DataAccessException; void deleteById(T... ids) throws DataAccessException; void deleteById(Collection ids) throws DataAccessException; - + // These methods allow for checking record existence boolean exists(P object) throws DataAccessException; boolean existsById(T id) throws DataAccessException; long count() throws DataAccessException; - + // These methods allow for retrieving POJOs by primary key or by some other field List

    findAll() throws DataAccessException; P findById(T id) throws DataAccessException; @@ -12364,7 +12364,7 @@ public class BookDao extends DAOImpl {

    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:

    - +

    Note how the lambda expression receives a new, derived configuration that should be used within the local scope:

    - + { // Wrap configuration in a new DSLContext: DSL.using(configuration).insertInto(...); DSL.using(configuration).insertInto(...); - + // Or, reuse the new DSLContext within the transaction scope: DSLContext ctx = DSL.using(configuration); ctx.insertInto(...); ctx.insertInto(...); - + // ... but avoid using the scope from outside the transaction: create.insertInto(...); create.insertInto(...); }); ]]> - +

    - While some implementations (e.g. ones based on ThreadLocals, e.g. Spring or JTA) may allow you to reuse the globally scoped reference, the jOOQ transaction API design allows for TransactionProvider implementations that require your transactional code to use the new, locally scoped Configuration, instead. + While some implementations (e.g. ones based on ThreadLocals, e.g. Spring or JTA) may allow you to reuse the globally scoped reference, the jOOQ transaction API design allows for TransactionProvider implementations that require your transactional code to use the new, locally scoped Configuration, instead.

    @@ -12585,7 +12585,7 @@ class SpringTransaction implements Transaction {

    With jOOQ, it's simple. All of jOOQ's exceptions are "system exceptions", hence they are all unchecked.

    - +

    jOOQ's DataAccessException

    jOOQ uses its own to wrap any underlying that might have occurred. Note that all methods in jOOQ that may cause such a DataAccessException document this both in the Javadoc as well as in their method signature. @@ -12601,7 +12601,7 @@ class SpringTransaction implements Transaction {

  • InvalidResultException: An operation was performed expecting only one result, but several results were returned.
  • MappingException: Something went wrong when loading a record from a or when mapping a record into a POJO
  • - +

    Override jOOQ's exception handling

    The following section about documents means of overriding jOOQ's exception handling, if you wish to deal separately with some types of constraint violations, or if you raise business errors from your database, etc. @@ -12618,7 +12618,7 @@ class SpringTransaction implements Transaction {

    For convenience and better backwards-compatibility, consider extending instead of implementing this interface.

    - +

    Example: Query statistics ExecuteListener

    Here is a sample implementation of an ExecuteListener, that is simply counting the number of queries per type that are being executed using jOOQ: @@ -12635,11 +12635,11 @@ public class StatisticsListener extends DefaultExecuteListener { public void start(ExecuteContext ctx) { synchronized (STATISTICS) { Integer count = STATISTICS.get(ctx.type()); - + if (count == null) { count = 0; } - + STATISTICS.put(ctx.type(), count + 1); } } @@ -12682,7 +12682,7 @@ for (ExecuteType type : ExecuteType.values()) {

    Please read the for more details

    - +

    Example: Custom Logging ExecuteListener

    The following depicts an example of a custom ExecuteListener, which pretty-prints all queries being executed by jOOQ to stdout: @@ -12705,7 +12705,7 @@ public class PrettyPrinter extends DefaultExecuteListener { // Create a new DSLContext for logging rendering purposes // This DSLContext doesn't need a connection, only the SQLDialect... DSLContext create = DSL.using(ctx.dialect(), - + // ... and the flag for pretty-printing new Settings().withRenderFormatted(true)); @@ -12713,12 +12713,12 @@ public class PrettyPrinter extends DefaultExecuteListener { if (ctx.query() != null) { System.out.println(create.renderInlined(ctx.query())); } - + // If we're executing a routine else if (ctx.routine() != null) { System.out.println(create.renderInlined(ctx.routine())); } - + // If we're executing anything else (e.g. plain SQL) else if (!StringUtils.isBlank(ctx.sql())) { System.out.println(ctx.sql()); @@ -12728,12 +12728,12 @@ public class PrettyPrinter extends DefaultExecuteListener {

    See also the manual's sections about for more sample implementations of actual ExecuteListeners.

    - +

    Example: Bad query execution ExecuteListener

    You can also use ExecuteListeners to interact with your SQL statements, for instance when you want to check if executed or statements contain a WHERE clause. This can be achieved trivially with the following sample ExecuteListener:

    - + 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:

    - + @@ -12785,7 +12785,7 @@ public class DeleteOrUpdateWithoutWhereException extends RuntimeException {}

    With the above configuration, let's fetch some data with jOOQ

    - +

    @@ -12833,14 +12833,14 @@ Finishing : Total: 4.814ms, +3.375ms

  • 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
  • - +

    Optimise wisely

    Don't be put off by the above paragraphs. You should optimise wisely, i.e. only in places where you really need very high throughput to your database. jOOQ's overhead compared to plain JDBC is typically less than 1ms per query.

    - +
    Alternative execution models @@ -12850,7 +12850,7 @@ Finishing : Total: 4.814ms, +3.375ms

    - +
    Using jOOQ with JPA @@ -12859,11 +12859,11 @@ Finishing : Total: 4.814ms, +3.375ms

    These sections will show how to use jOOQ with JPA's native query API in order to fetch tuples or managed entities using the Java EE standards.

    - +

    In all of the following sections, let's assume we have the following JPA entities to model our database:

    - + - +
    Using jOOQ with JPA Native Query @@ -12967,7 +12967,7 @@ nativeQuery(em, DSL.using(configuration) books.forEach((Object[] book) -> System.out.println(book[0] + " " + book[1] + " wrote " + book[2]));]]>
    - +
    Using jOOQ with JPA entities @@ -12975,7 +12975,7 @@ books.forEach((Object[] book) -> System.out.println(book[0] + " " + book[1] + "

    The simplest way to fetch entities via the native query API is by passing the entity class along to the native query method. The following example maps jOOQ query results to JPA entities (). Just add the following utility method:

    - + List nativeQuery(EntityManager em, org.jooq.Query query, Class type) { // Extract the SQL statement from the jOOQ query: @@ -13017,7 +13017,7 @@ static Object convertToDatabaseType(Param param) {

    With the above simple API, we're ready to write complex jOOQ queries and map their results to JPA entities:

    - + authors = nativeQuery(em, DSL.using(configuration) @@ -13028,14 +13028,14 @@ nativeQuery(em, authors.forEach(author -> { System.out.println(author.firstName + " " + author.lastName + " wrote"); - + books.forEach(book -> { System.out.println(" " + book.title); }); });]]>
    - +
    Using jOOQ with JPA EntityResult @@ -13043,11 +13043,11 @@ authors.forEach(author -> {

    While JPA specifies how the mapping should be implemented (e.g. using ), there are no limitations regarding how you want to generate the SQL statement. The following, simple example shows how you can produce JPABook and JPAAuthor entities () from a jOOQ-generated SQL statement.

    - +

    In order to do so, we'll need to specify the . This can be done on any entity, and in this case, we're using :

    - + { } ) } -)]]> - +)]]> +

    Note how we need to map between:

    @@ -13077,11 +13077,11 @@ authors.forEach(author -> {
  • , which corresponds to the entity's attribute name
  • , which corresponds to the SQL result's column name
  • - +

    With the above boilerplate in place, we can now fetch entities using jOOQ and JPA:

    - + List nativeQuery(EntityManager em, org.jooq.Query query, String resultSetMapping) { // Extract the SQL statement from the jOOQ query: @@ -13099,7 +13099,7 @@ authors.forEach(author -> {

    Note, if you're using or , make sure to take those into account as well. E.g. as follows:

    - + List nativeQuery(EntityManager em, org.jooq.Query query, String resultSetMapping) { // Extract the SQL statement from the jOOQ query: @@ -13120,11 +13120,11 @@ static Object convertToDatabaseType(Param param) { }]]>

    Using the above API

    - +

    Now that we have everything setup, we can use the above API to run a jOOQ query to fetch JPA entities like this:

    - + result = nativeQuery(em, DSL.using(configuration @@ -13138,7 +13138,7 @@ nativeQuery(em, ) .from(AUTHOR) .join(BOOK).on(BOOK.AUTHOR_ID.eq(AUTHOR.ID)) - .orderBy(BOOK.ID)), + .orderBy(BOOK.ID)), "bookmapping" // The name of the SqlResultSetMapping ); @@ -13147,11 +13147,11 @@ result.forEach((Object[] entities) -> { JPABook book = (JPABook) entities[0]; System.out.println(author.firstName + " " + author.lastName + " wrote " + book.title); -});]]> +});]]>

    The entities are now ready to be modified and persisted again.

    - +

    Caveats:

    @@ -13163,7 +13163,7 @@ result.forEach((Object[] entities) -> {
    -
    +
    @@ -13217,7 +13217,7 @@ result.forEach((Object[] entities) -> {

    You need to tell jOOQ some things about your database connection. Here's an example of how to do it for an Oracle database

    - + @@ -13226,7 +13226,7 @@ result.forEach((Object[] entities) -> { jdbc:oracle:thin:@[your jdbc connection parameters] [your database user] [your database password] - + user[db-user] @@ -13238,9 +13238,9 @@ result.forEach((Object[] entities) -> { org.jooq.util.oracle.OracleDatabase @@ -13274,9 +13274,9 @@ result.forEach((Object[] entities) -> { Use the pipe to separate several expressions) Watch out for case-sensitivity. Depending on your database, this might be important! - + You can create case-insensitive regular expressions using this syntax: (?i:expr) - + Whitespace is ignored and comments are possible. --> .* @@ -13307,7 +13307,7 @@ result.forEach((Object[] entities) -> { @@ -13328,13 +13328,13 @@ result.forEach((Object[] entities) -> {

    Code generation works by calling this class with the above property file as argument.

    - + org.jooq.util.GenerationTool /jooq-config.xml

    Be sure that these elements are located on the classpath:

    - +
    • The XML configuration file
    • jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar
    • @@ -13359,7 +13359,7 @@ result.forEach((Object[] entities) -> {
    • this example uses jOOQ's log4j support by adding log4j.xml and log4j.jar to the project classpath.
    • the actual jooq-{jooq-version}.jar, jooq-meta-{jooq-version}.jar, jooq-codegen-{jooq-version}.jar artefacts may contain version numbers in the file names.
    - +
    Eclipse configuration
    @@ -13401,11 +13401,11 @@ result.forEach((Object[] entities) -> { org.jooq jooq-codegen-maven @@ -13479,7 +13479,7 @@ result.forEach((Object[] entities) -> { In the we have seen how jOOQ's source code generator is configured and run within a few steps. In this chapter we'll cover some advanced settings, individually.

    - +
    Logging @@ -13525,7 +13525,7 @@ result.forEach((Object[] entities) -> {
    - +
    Jdbc @@ -13542,7 +13542,7 @@ result.forEach((Object[] entities) -> { com.mysql.jdbc.Driver jdbc:mysql://localhost/testdb - @@ -13562,7 +13562,7 @@ result.forEach((Object[] entities) -> { .withUrl("jdbc:mysql://localhost/testdb") .withUser("root") .withPassword("secret"));]]> - +

    Note that when using the programmatic configuration API through the GenerationTool, you can also pass a pre-existing JDBC connection to the GenerationTool and leave this configuration element alone.

    @@ -13581,7 +13581,7 @@ result.forEach((Object[] entities) -> { }]]>

    Optional JDBC properties

    - +

    JDBC drivers allow for passing to the JDBC driver when creating a connection. This is also supported in the code generator configuration with a list of key/value pairs as follows:

    @@ -13643,7 +13643,7 @@ result.forEach((Object[] entities) -> { }]]>

    Using variables in Maven

    - +

    Quite often, you'd like to keep passwords (or other elements) out of your configuration, or you'd like to repeat common values for different plugins, e.g. for both . In those cases, the programmatic configuration makes it easiest to quickly replace them, because those values are just ordinary Java local variables for that API. When you use the XML configuration with Maven, you can also very simply use Maven's property mechanism to achieve something like this:

    @@ -13665,7 +13665,7 @@ result.forEach((Object[] entities) -> {

    - +
    Generator @@ -13681,17 +13681,17 @@ result.forEach((Object[] entities) -> { ... - + ... - + ... - + ... - - + + ... ]]> @@ -13707,7 +13707,7 @@ result.forEach((Object[] entities) -> { .withDatabase(new Database()) .withGenerate(new Generate()) .withTarget(new Target())));]]> - +

    Gradle configuration

    @@ -13715,8 +13715,8 @@ result.forEach((Object[] entities) -> { {
  • - +

    For more details, please refer to the relevant sections, above.

    - +

    jooq-meta and jooq-codegen configuration

    - +
    Database, name, and properties @@ -13799,7 +13799,7 @@ result.forEach((Object[] entities) -> { .withProperties( new Property().withKey("dialect").withValue("MYSQL"), new Property().withKey("xml-file").withValue("/path/to/database.xml")))));]]> - +

    Gradle configuration

    @@ -13847,37 +13847,37 @@ result.forEach((Object[] entities) -> {
  • org.jooq.util.sybase.SybaseDatabase
  • org.jooq.util.vertica.VerticaDatabase
  • - +

    Alternatively, you can also specify the following database if you want to reverse-engineer a generic JDBC

    - +
    • org.jooq.util.jdbc.JDBCDatabase
    - +

    Furthermore, there are two out-of-the-box database meta data sources, that do not rely on a JDBC connection: the (to reverse engineer JPA annotated entities) and the (to reverse engineer an XML file). Please refer to the respective sections for more details.

    - +

    Last, but not least, you can of course implement your own by implementing org.jooq.util.Database from the jooq-meta module.

    - +
    RegexFlags

    A lot of configuration elements rely on regular expressions. The most prominent examples are the useful elements. All of these regular expressions use the Java API, with all of its features. The Pattern API allows for specifying flags and for your configuration convenience, the applied flags are, by default:

    - +
    • COMMENTS: This allows for embedding comments (and, as a side-effect: meaningless whitespace) in regular expressions, which makes them much more readable.
    • CASE_INSENSITIVE: Most schemas are case insensitive, so case-sensitive regular expressions are a bit of a pain, especially in multi-vendor setups, where databases like PostgreSQL (mostly lower case) and Oracle (mostly UPPER CASE) need to be supported simultaneously.
    - +

    But of course, this default setting may get in your way, for instance if you rely on case sensitive identifiers and whitespace in identifiers a lot, it might be better for you to turn off the above defaults:

    @@ -13885,7 +13885,7 @@ result.forEach((Object[] entities) -> {

    XML configuration (standalone and Maven)

    - + @@ -13902,7 +13902,7 @@ result.forEach((Object[] entities) -> { .withGenerator(new Generator( .withDatabase(new Database() .withRegexFlags("COMMENTS DOTALL"))));]]> - +

    Gradle configuration

    @@ -13920,18 +13920,18 @@ result.forEach((Object[] entities) -> {

    - +
    Includes and Excludes

    Perhaps the most important elements of the code generation configuration are used for the inclusion and exclusion of content as reported by your

    - +

    These expressions match any of the following object types, either by their fully qualified names (catalog.schema.object_name), or by their names only (object_name):

    - +
    • Array types
    • Domains
    • @@ -13944,7 +13944,7 @@ result.forEach((Object[] entities) -> {
    • Tables
    • UDTs
    - +

    Excludes match before includes, meaning that something that has been excluded cannot be included again. Remember, these expressions are , so multiple names need to be separated with the pipe symbol "|", not with commas, etc. For example:

    @@ -13952,7 +13952,7 @@ result.forEach((Object[] entities) -> {

    XML configuration (standalone and Maven)

    - + @@ -13976,7 +13976,7 @@ result.forEach((Object[] entities) -> { .withDatabase(new Database() .withIncludes(".*") .withExcludes("UNUSED_TABLE|PREFIX_.*|SECRET_SCHEMA\.SECRET_TABLE|SECRET_ROUTINE"))));]]> - +

    Gradle configuration

    @@ -14018,7 +14018,7 @@ result.forEach((Object[] entities) -> { .withIncludes(".*") .withExcludes("INVISIBLE_COL") .withIncludeExcludeColumns(true))));]]> - +

    Gradle configuration

    @@ -14035,7 +14035,7 @@ result.forEach((Object[] entities) -> {
    - +
    Include object types @@ -14077,7 +14077,7 @@ result.forEach((Object[] entities) -> { .withIncludePrimaryKeys(false) .withIncludeUniqueKeys(false) .withIncludeForeignKeys(false))));]]> - +

    Gradle configuration

    @@ -14101,7 +14101,7 @@ result.forEach((Object[] entities) -> {

    - +
    Record Version and Timestamp Fields @@ -14131,7 +14131,7 @@ result.forEach((Object[] entities) -> { .withDatabase(new Database() .withRecordVersionFields("REC_VERSION") .withRecordTimestampFields("REC_TIMESTAMP"))));]]> - +

    Gradle configuration

    @@ -14178,7 +14178,7 @@ result.forEach((Object[] entities) -> { .withGenerator(new Generator( .withDatabase(new Database() .withSyntheticIdentities("SCHEMA\.TABLE\.ID"))));]]> - +

    Gradle configuration

    @@ -14224,7 +14224,7 @@ result.forEach((Object[] entities) -> { .withGenerator(new Generator( .withDatabase(new Database() .withSyntheticPrimaryKeys("SCHEMA\.TABLE\.COLUMN(1|2)"))));]]> - +

    Gradle configuration

    @@ -14246,7 +14246,7 @@ result.forEach((Object[] entities) -> {

    - +
    Override primary keys @@ -14274,7 +14274,7 @@ result.forEach((Object[] entities) -> { .withGenerator(new Generator( .withDatabase(new Database() .withOverridePrimaryKeys("MY_UNIQUE_KEY_NAME"))));]]> - +

    Gradle configuration

    @@ -14296,7 +14296,7 @@ result.forEach((Object[] entities) -> {

    - +
    Date as timestamp @@ -14328,7 +14328,7 @@ result.forEach((Object[] entities) -> { .withGenerator(new Generator( .withDatabase(new Database() .withDateAsTimestamp(true))));]]> - +

    Gradle configuration

    @@ -14346,14 +14346,14 @@ result.forEach((Object[] entities) -> {

    - +
    Ignore procedure return values (deprecated)

    In jOOQ 3.6.0, #4106 was implemented to support Transact-SQL's optional return values from stored procedures. This turns all procedures into Routine<Integer> (instead of Routine<Void>). For backwards-compatibility reasons, users can suppress this change in jOOQ 3.x

    - +

    This feature is deprecated as of jOOQ 3.6.0 and will be removed again in jOOQ 4.0.

    @@ -14378,7 +14378,7 @@ result.forEach((Object[] entities) -> { .withGenerator(new Generator( .withDatabase(new Database() .withIgnoreProcedureReturnValues(true))));]]> - +

    Gradle configuration

    @@ -14392,21 +14392,21 @@ result.forEach((Object[] entities) -> { }]]>
    - +
    Unsigned types

    The JDBC and Java type system don't know any unsigned integer data types, but some databases do, most importantly MySQL. This flag allows for overriding the default mapping from unsigned to signed integers and generates jOOU types instead:

    - +
    - +

    Those types work just like ordinary wrapper types, except that there is no primitive version of them. The configuration looks like follows:

    @@ -14431,7 +14431,7 @@ result.forEach((Object[] entities) -> { .withGenerator(new Generator( .withDatabase(new Database() .withUnsignedTypes(true))));]]> - +

    Gradle configuration

    @@ -14445,7 +14445,7 @@ result.forEach((Object[] entities) -> { }]]>
    - +
    Catalog and schema mapping @@ -14509,7 +14509,7 @@ result.forEach((Object[] entities) -> { .withDatabase(new Database() .withInputCatalog("my_catalog") .withInputSchema("my_schema"))));]]> - +

    Gradle configuration

    @@ -14617,7 +14617,7 @@ configuration new Schema().withInputSchema("schema2")))))); ]]> - +

    Gradle configuration

    @@ -14730,7 +14730,7 @@ configuration .withOutputCatalogToDefault(true) .withInputSchema("my_input_schema") .withOutputSchemaToDefault(true))));]]> - +

    Gradle configuration

    @@ -14764,7 +14764,7 @@ configuration {

    - +
    Catalog and schema version providers @@ -14812,7 +14812,7 @@ configuration { .withDatabase(new Database() .withCatalogVersionProvider("SELECT :catalog_name || '_' || MAX(\"version\") FROM \"schema_version\"") .withSchemaVersionProvider("SELECT :schema_name || '_' || MAX(\"version\") FROM \"schema_version\""))));]]> - +

    Gradle configuration

    @@ -14828,24 +14828,24 @@ configuration {
    - +
    Forced types

    The code generator allows users to override column data types in three different ways:

    - +
    • By rewriting them to some other data type using the .
    • By mapping them to some user type using the and a custom .
    • By mapping them to some user type using the and a custom .
    - +

    All of this can be done using forced types.

    - +

    Data type rewriting

    @@ -14864,7 +14864,7 @@ configuration { .*\.IS_VALID - + ]]> - +

    Load the above using standard JAXB API:

    - +

    - +
    Custom generator strategies @@ -15183,7 +15183,7 @@ GeberationTool.generate(configuration);]]>

    jOOQ allows you to override default implementations of the code generator or the generator strategy. Specifically, the latter can be very useful if you want to inject custom behaviour into jOOQ's code generator with respect to naming classes, members, methods, and other Java objects.

    - + @@ -15413,58 +15413,58 @@ public class Book implements java.io.Serializable { - + MY_SCHEMA - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - +
    - + MY_TABLE - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomInterface - + --> MatcherRule com.example.MyOptionalCustomBaseClass com.example.MyOptionalCustomInterface
    - + - + MY_FIELD - + --> MatcherRule --> MatcherRule @@ -15472,30 +15472,30 @@ public class Book implements java.io.Serializable { --> MatcherRule - + - + MY_ROUTINE - + --> MatcherRule --> MatcherRule com.example.MyOptionalCustomInterface - + - + MY_SEQUENCE - + --> MatcherRule @@ -15511,19 +15511,19 @@ public class Book implements java.io.Serializable { CAMEL - + PREFIX_$0_SUFFIX ]]> - +

    Some examples

    The following example shows a matcher strategy that adds a "T_" prefix to all table classes and to table identifiers: @@ -15534,7 +15534,7 @@ public class Book implements java.io.Serializable { - + UPPER @@ -15569,13 +15569,13 @@ public class Book implements java.io.Serializable { ]]> - +

    For more information about each XML tag, please refer to the http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd XSD file.

    - +
    Custom code sections @@ -15622,7 +15622,7 @@ public class Book implements java.io.Serializable {

    Any of the below methods can be overridden:

    - + Tables.java: This file contains all table objects in the form of static member references to the actual singleton object
  • UDTs.java: This file contains all UDT objects in the form of static member references to the actual singleton object
  • - +

    Referencing global artefacts

    When referencing global artefacts from your client application, you would typically static import them as such:

    - + @@ -15718,7 +15718,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate a implementation that looks like this:

    - + { // The singleton instance @@ -15734,7 +15734,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE) public Book as(java.lang.String alias) { return new Book(alias); } - + // [...] }]]> @@ -15753,7 +15753,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)
  • instanceFields: This flag controls the "static" keyword on table columns, as well as aliasing convenience
  • records: The generated record type is referenced from tables allowing for type-safe single-table record fetching
  • - +

    Flags controlling table generation

    Table generation cannot be deactivated @@ -15767,7 +15767,7 @@ create.insertInto(com.example.generated.Tables.MY_TABLE)

    Every table in your database will generate an implementation that looks like this:

    - + - +

    Flags influencing generated records

    These flags from the influence generated records: @@ -15825,7 +15825,7 @@ implements IBook {

  • interfaces: If interfaces are generated, records will implement them
  • jpaAnnotations: JPA annotations are used on generated records
  • - +

    Flags controlling record generation

    Record generation can be deactivated using the records flag @@ -15839,7 +15839,7 @@ implements IBook {

    Every table in your database will generate a POJO implementation that looks like this:

    - + - +

    Flags influencing generated POJOs

    These flags from the influence generated POJOs: @@ -15888,7 +15888,7 @@ public class Book implements java.io.Serializable

  • jpaAnnotations: JPA annotations are used on generated records
  • validationAnnotations: JSR-303 validation annotations are used on generated records
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the pojos flag @@ -15902,16 +15902,16 @@ public class Book implements java.io.Serializable

    Every table in your database will generate an interface that looks like this:

    - + - +

    Flags influencing generated interfaces

    These flags from the influence generated interfaces: @@ -15920,7 +15920,7 @@ public class Book implements java.io.Serializable

  • dateAsTimestamp: This influences all relevant getters and setters
  • unsignedTypes: This influences all relevant getters and setters
  • - +

    Flags controlling POJO generation

    POJO generation can be activated using the interfaces flag @@ -15935,7 +15935,7 @@ public class Book implements java.io.Serializable

    Every table in your database will generate a implementation that looks like this:

    - + { // Generated constructors @@ -15959,10 +15959,10 @@ public class Book implements java.io.Serializable public List fetchByAuthorId(Integer... values) { return fetch(BOOK.AUTHOR_ID, values); } - + // [...] }]]> - +

    Flags controlling DAO generation

    DAO generation can be activated using the daos flag @@ -15976,13 +15976,13 @@ public class Book implements java.io.Serializable

    Every sequence in your database will generate a implementation that looks like this:

    - + S_AUTHOR_ID = new SequenceImpl("S_AUTHOR_ID", TEST, SQLDataType.INTEGER); }]]> - +

    Flags controlling sequence generation

    Sequence generation cannot be deactivated @@ -16020,7 +16020,7 @@ public class Book implements java.io.Serializable public BigDecimal getResult() { return getValue(RESULT); } - + // [...] }]]> @@ -16042,7 +16042,7 @@ public class Book implements java.io.Serializable

    Every UDT in your database will generate a implementation that looks like this:

    - + { // The singleton UDT instance @@ -16055,10 +16055,10 @@ public class Book implements java.io.Serializable createField("CITY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); public static final UDTField COUNTRY = createField("COUNTRY", SQLDataType.VARCHAR, U_ADDRESS_TYPE); - + // [...] }]]> - +

    Besides the implementation, a implementation is also generated

    @@ -16073,7 +16073,7 @@ public class Book implements java.io.Serializable public String getCity() {...} public void setCountry(String value) {...} public String getCountry() {...} - + // [...] }]]>
    @@ -16102,20 +16102,20 @@ public class Book implements java.io.Serializable BOOLEAN .*\.IS_VALID - + .* @@ -16139,7 +16139,7 @@ public class Book implements java.io.Serializable

    When using a custom type in jOOQ, you need to let jOOQ know about its associated . Ad-hoc usages of such converters has been discussed in the chapter about . However, when mapping a custom type onto a standard JDBC type, a more common use-case is to let jOOQ know about custom types at code generation time (if you're using non-standard JDBC types, like for example JSON or HSTORE, see the ). Use the following configuration elements to specify, that you'd like to use GregorianCalendar for all database fields that start with DATE_OF_

    - +

    There's a simple configuration using only <forcedTypes/> configuration elements, and an advanced configuration using both <forcedTypes/> and <customTypes/> elements, which allow for greater reuse.

    @@ -16155,29 +16155,29 @@ public class Book implements java.io.Serializable - + java.util.GregorianCalendar com.example.CalendarConverter - + .*\.DATE_OF_.* - + .* @@ -16187,7 +16187,7 @@ public class Book implements java.io.Serializable

    Advanced configuration

    - The advanced configuration allows for specifying <customTypes/>, which can be used to reuse configuration elements for user type / converter / binding combinations by giving them a name: + The advanced configuration allows for specifying <customTypes/>, which can be used to reuse configuration elements for user type / converter / binding combinations by giving them a name:

    @@ -16196,7 +16196,7 @@ public class Book implements java.io.Serializable GregorianCalendar - + java.util.GregorianCalendar @@ -16212,21 +16212,21 @@ public class Book implements java.io.Serializable GregorianCalendar .*\.DATE_OF_.* - + .* @@ -16260,15 +16260,15 @@ create.selectFrom(AUTHOR)
    - - + +
    Custom data type binding

    The previous section discussed the case where your custom data type is mapped onto a standard JDBC type as contained in . In some cases, however, you want to map your own type onto a type that is not explicitly supported by JDBC, such as for instance, PostgreSQL's various advanced data types like JSON or HSTORE, or PostGIS types. For this, you can register an for relevant columns in your code generator. Consider the following trivial implementation of a binding for PostgreSQL's JSON data type, which binds the JSON string in PostgreSQL to a Google GSON object:

    - + {

    The above implementation intercepts all the interaction on a JDBC level, such that jOOQ will never need to know how to crrectly serialise / deserialise your custom data type. Similar to what we've seen in the previous section about , we can now register such a binding to the code generator. Note that you will reuse the same types of XML elements (<customType/> and <forcedType/>):

    - + @@ -16368,26 +16368,26 @@ public class PostgresJSONGsonBinding implements Binding { com.example.PostgresJSONGsonBinding .*JSON.* - + .* -]]> +]]>

    See also the section about to learn about an alternative use of <forcedTypes/>. @@ -16407,7 +16407,7 @@ public class PostgresJSONGsonBinding implements Binding {

    - +
    Mapping generated catalogs and schemas @@ -16415,7 +16415,7 @@ public class PostgresJSONGsonBinding implements Binding {

    We've seen previously in the chapter about , that catalogs, schemata and tables can be mapped at runtime to other names. But you can also hard-wire catalog and schema mapping in generated artefacts at code generation time, e.g. when you have 5 developers with their own dedicated developer databases, and a common integration database. In the code generation configuration, you would then write.

    - +

    Schema mapping

    @@ -16443,7 +16443,7 @@ public class PostgresJSONGsonBinding implements Binding { PROD - + ... @@ -16453,23 +16453,23 @@ public class PostgresJSONGsonBinding implements Binding {

    - +
    Code generation for large schemas

    Databases can become very large in real-world applications. This is not a problem for jOOQ's code generator, but it can be for the Java compiler. jOOQ generates some classes for . These classes can hit two sorts of limits of the compiler / JVM:

    - +
    • Methods (including static / instance initialisers) are allowed to contain only 64kb of bytecode.
    • Classes are allowed to contain at most 64k of constant literals
    - +

    While there exist workarounds for the above two limitations (delegating initialisations to nested classes, inheriting constant literals from implemented interfaces), the preferred approach is either one of these:

    - +
    • Distribute your database objects in several schemas. That is probably a good idea anyway for such large databases
    • to exclude excess database objects
    • @@ -16544,7 +16544,7 @@ public class PostgresJSONGsonBinding implements Binding {

      In such a setup, you might have a pre-existing schema implemented using JPA-annotated entities. Your real database schema might not be accessible while developing, or it is not a first-class citizen in your application (i.e. you follow a Java-first approach). This section explains how you can generate jOOQ classes from such a JPA model. Consider this model:

      - + org.jooq jooq-meta-extensions @@ -16602,7 +16602,7 @@ public class Book {

      With that dependency in place, you can now specify the JPADatabase in your code generator configuration:

      - + org.jooq.util.jpa.JPADatabase @@ -16621,7 +16621,7 @@ public class Book {

    - +
    Generating code from XML files @@ -16637,7 +16637,7 @@ public class Book {

    An example schema definition containing simple schema, table, column definitions can be seen below:

    - + @@ -16698,7 +16698,7 @@ public class Book { ... - + TEST @@ -16713,18 +16713,18 @@ public class Book {

    The above file can be made available to the code generator configuration by using the XMLDatabase as follows:

    - + org.jooq.util.xml.XMLDatabase - + dialect ORACLE - + xml-file @@ -16735,16 +16735,16 @@ public class Book { ]]>

    - If you already have a different XML format for your database, you can either XSL transform your own format into the one above via an additional Maven plugin, or pass the location of an XSL file to the XMLDatabase by providing an additional property: + If you already have a different XML format for your database, you can either XSL transform your own format into the one above via an additional Maven plugin, or pass the location of an XSL file to the XMLDatabase by providing an additional property:

    - + org.jooq.util.xml.XMLDatabase - + ... - + xsl-file @@ -16755,7 +16755,7 @@ public class Book { ]]>

    - This XML configuration can now be checked in and versioned, and modified independently from your live database schema. + This XML configuration can now be checked in and versioned, and modified independently from your live database schema.

    @@ -16770,14 +16770,14 @@ public class Book { - - + ]]> @@ -16796,7 +16796,7 @@ public class Book { generate-sources - @@ -16808,20 +16808,20 @@ public class Book { - + - org.jooq + org.jooq.trial jooq-codegen {jooq-version} @@ -16829,7 +16829,7 @@ public class Book { ]]> - +
    Running the code generator with Gradle @@ -16837,7 +16837,7 @@ public class Book {

    We recommend using the Gradle plugin by Etienne Studer (from Gradle Inc.). It provides a concise DSL that allows you to tune all configuration properties supported by each jOOQ version. Please direct any support questions or issues you may find directly to the third party plugin vendor.

    - +

    Alternatively, the XML MarkupBuilder can be used

    If you don't want to use the above third party plugin, there's also the possibility to use jOOQ's standalone code generator for simplicity. The following working example build.gradle script should work out of the box: @@ -16931,11 +16931,11 @@ org.jooq.util.GenerationTool.generate(

    When writing unit tests for your data access layer, you have probably used some generic mocking tool offered by popular providers like Mockito, jmock, mockrunner, or even DBUnit. With jOOQ, you can take advantage of the built-in JDBC mock API that allows you to emulate a simple database on the JDBC level for precisely those SQL/JDBC use cases supported by jOOQ.

    - +

    - Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider. + Disclaimer: The general idea of mocking a JDBC connection with this jOOQ API is to provide quick workarounds, injection points, etc. using a very simple JDBC abstraction. It is NOT RECOMMENDED to emulate an entire database (including complex state transitions, transactions, locking, etc.) using this mock API. Once you have this requirement, please consider using an actual database instead for integration testing, rather than implementing your test database inside of a MockDataProvider.

    - +

    Mocking the JDBC API

    JDBC is a very complex API. It takes a lot of time to write a useful and correct mock implementation, implementing at least these interfaces: @@ -16948,16 +16948,16 @@ org.jooq.util.GenerationTool.generate(

  • - +

    Optionally, you may even want to implement interfaces, such as , , , and many others. In addition to the above, you might need to find a way to simultaneously support incompatible JDBC minor versions, such as 4.0, 4.1

    - +

    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 :

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    As you can see, the configuration setup is simple. Now, the MockDataProvider acts as your single point of contact with JDBC / jOOQ. It unifies any of these execution modes, transparently:

    - +
    • Statements without results
    • Statements without results but with generated keys
    • @@ -16980,16 +16980,16 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
    • Batch statements with single queries and multiple bind value sets
    • Batch statements with multiple queries and no bind values
    - +

    The above are the execution modes supported by jOOQ. Whether you're using any of jOOQ's various fetching modes (e.g. , , , ) is irrelevant, as those modes are all built on top of the standard JDBC API.

    - +

    Implementing MockDataProvider

    Now, here's how to implement MockDataProvider:

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc // 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 String sql = ctx.sql(); - + // Exceptions are propagated through the JDBC and jOOQ APIs if (sql.toUpperCase().startsWith("DROP")) { throw new SQLException("Statement not supported: " + sql); } - + // You decide, whether any given statement returns results, and how many else if (sql.toUpperCase().startsWith("SELECT")) { - + // Always return one author record Result result = create.newResult(AUTHOR); result.add(create.newRecord(AUTHOR)); @@ -17017,12 +17017,12 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc result.get(0).setValue(AUTHOR.LAST_NAME, "Orwell"); mock[0] = new MockResult(1, result); } - + // You can detect batch statements easily else if (ctx.batch()) { // [...] } - + return mock; } }]]> @@ -17034,25 +17034,25 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc
  • : The number of affected rows
  • : The result set
  • - +

    You should return as many MockResult objects as there were query executions (in ) or results (in ). Instead of an awkward JDBC ResultSet, however, you can construct a "friendlier" with your own record types. The jOOQ mock API will use meta data provided with this Result in order to create the necessary JDBC

    - +

    See the for a list of rules that you should follow.

    - - + +
    API validation using the Checker Framework

    Java 8 introduced JSR 308 (type annotations) and with it, the Checker Framework was born. The Checker Framework allows for implementing compiler plugins that run sophisticated checks on your Java AST to introduce rich annotation based type semantics, e.g.

    - + result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc

    jOOQ has two annotations that are very interesting for the Checker Framework to type check, namely:

    - +
    • : This annotation documents jOOQ DSL API with valuable information about which database supports a given SQL clause or function, etc. For instance, only CUBRID, Informix, and Oracle currently support .
    • : This annotation documents jOOQ DSL API which operates on . Plain SQL being string-based SQL that is injected into a jOOQ expression tree, these API elements introduce a certain SQL injection risk (just like JDBC in general), if users are not careful.
    - +

    Using the optional jooq-checker module (available only from Maven Central), users can now type-check their code to work only with a given set of dialects, or to forbid access to plain SQL.

    - +

    Example:

    - +

    A detailed blog post shows how this works in depth. By adding a simple dependency to your Maven build:

    - + @@ -17088,27 +17088,27 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc jooq-checker {jooq-version} ]]> - +

    ... you can now include one of the two checkers:

    - +

    SQLDialectChecker

    - +

    The SQLDialect checker reads all of the and annotations in your source code and checks if the jOOQ API you're using is allowed and/or required in a given context, where that context can be any scope, including:

    - +
    • A package
    • A class
    • A method
    - +

    Configure this compiler plugin:

    - + maven-compiler-plugin 3.3 @@ -17124,11 +17124,11 @@ Result result = create.selectFrom(BOOK).where(BOOK.ID.equal(5)).fetc ]]> - +

    ... annotate your packages, e.g.

    - + // Scope: entire package (put in package-info.java) @Allow(ORACLE) package org.jooq.example.checker; @@ -17136,17 +17136,17 @@ package org.jooq.example.checker;

    And now, you'll no longer be able to use any SQL Server specific functionality that is not available in Oracle, for instance. Perfect!

    - +

    There are quite some delicate rules that play into this when you nest these annotations. Please refer to this blog post for details.

    - +

    PlainSQLChecker

    - +

    This checker is much simpler. Just add the following compiler plugin to deactivate plain SQL usage by default:

    - + maven-compiler-plugin 3.3 @@ -17166,7 +17166,7 @@ package org.jooq.example.checker;

    From now on, you won't risk any SQL injection in your jOOQ code anymore, because your compiler will reject all such API usage. If, however, you need to place an exception on a given package / class / method, simply add the annotation, as such:

    - + iKnowWhatImDoing() { @@ -17191,20 +17191,20 @@ public List iKnowWhatImDoing() {

    Gudu Software Ltd has been selling enterprise quality SQL software to hundreds of customers to help them migrate from one database to another using the General SQL Parser. Now you can take advantage of their knowledge to parse your SQL statements and transform them directly into jOOQ statements using a free trial version of SQL 2 jOOQ!

    - +

    It's as simple as this!

    - +
    • Create a JDBC connection
    • Create a new SQL2jOOQ converter object
    • Convert your SQL code
    • Get the result
    - +

    See it in action:

    - + If all goes well, the above program yields:

    - + > result = create.select( Actor.ACTOR.FIRST_NAME, Actor.ACTOR.LAST_NAME ) @@ -17268,21 +17268,21 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    Please take note of the fact that the sql2jooq library is Open Source, but it depends on the commercial gsp.jar parser, whose trial licensing terms can be seen here:

    - +

    https://github.com/sqlparser/sql2jooq/blob/master/sql2jooq/LICENSE-GSQLPARSER.txt

    - +

    For more information about the General SQL Parser, please refer to the product blog.

    - +

    Please report any issues, ideas, wishes to the jOOQ user group or the sql2jooq GitHub project.

    - +
    jOOQ Console @@ -17331,7 +17331,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • Sybase Adaptive Server Enterprise 15.5
  • Sybase SQL Anywhere 12
  • - +

    For an up-to-date list of currently supported RDBMS, please refer to http://www.jooq.org/legal/licensing/#databases.

    @@ -17352,7 +17352,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME, This chapter should document the most important notes about SQL, JDBC and jOOQ data types.

    - +
    BLOBs and CLOBs @@ -17362,7 +17362,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    Unsigned integer types @@ -17386,7 +17386,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
    - +
    INTERVAL data types @@ -17397,11 +17397,11 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • YEAR TO MONTH: This interval type models a number of months and years
  • DAY TO SECOND: This interval type models a number of days, hours, minutes, seconds and milliseconds
  • - +

    Both interval types ship with a variant of subtypes, such as DAY TO HOUR, HOUR TO SECOND, etc. jOOQ models these types as Java objects extending : (where Number.intValue() corresponds to the absolute number of months) and (where Number.intValue() corresponds to the absolute number of milliseconds)

    - +

    Interval arithmetic

    In addition to the documented previously, interval arithmetic is also supported by jOOQ. Essentially, the following operations are supported: @@ -17416,7 +17416,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    XML data types @@ -17425,7 +17425,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    Geospacial data types @@ -17435,7 +17435,7 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    - +
    CURSOR data types @@ -17444,22 +17444,22 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,

    > cursor;]]> - +

    In fact, such a cursor will be fetched immediately by jOOQ and wrapped in an object.

    - +
    ARRAY and TABLE data types

    The SQL standard specifies ARRAY data types, that can be mapped to Java arrays as such:

    - + intArray;]]> - +

    The above array type is supported by these SQL dialects:

    @@ -17468,33 +17468,33 @@ Result> result = create.select( Actor.ACTOR.FIRST_NAME,
  • HSQLDB
  • Postgres
  • - +

    Oracle typed arrays

    Oracle has strongly-typed arrays and table types (as opposed to the previously seen anonymously typed arrays). These arrays are wrapped by types.

    - +
    Oracle DATE data type

    - Oracle's DATE data type does not conform to the SQL standard. It is really a TIMESTAMP(0), i.e. a TIMESTAMP with a fractional second precision of zero. The most appropriate JDBC type for Oracle DATE types is . + Oracle's DATE data type does not conform to the SQL standard. It is really a TIMESTAMP(0), i.e. a TIMESTAMP with a fractional second precision of zero. The most appropriate JDBC type for Oracle DATE types is .

    - +

    Performance implications

    - +

    When binding TIMESTAMP variables to SQL statements, instead of truncating such variables to DATE, the cost based optimiser may choose to widen the database column from DATE to TIMESTAMP using an Oracle INTERNAL_FUNCTION(), which prevents index usage. Details about this behaviour can be seen in this Stack Overflow question.

    - +

    Use a data type binding to work around this issue

    - +

    The best way to work around this issue is to implement a , which generates the CAST expression for every bind variable:

    - + ctx) throws SQLException { render.keyword("cast").sql('(') @@ -17503,15 +17503,15 @@ public final void sql(BindingSQLContext ctx) throws SQLException { }]]>

    Deprecated functionality

    - +

    Historic versions of jOOQ used to support a <dateAsTimestamp/> flag, which can be used with the out-of-the-box as a :

    - + true - + @@ -17524,7 +17524,7 @@ public final void sql(BindingSQLContext ctx) throws SQLException {

    For more information, please refer to . -

    +

    @@ -17536,12 +17536,12 @@ public final void sql(BindingSQLContext ctx) throws SQLException {

    jOOQ takes SQL as an external domain-specific language and maps it onto Java, creating an internal domain-specific language. Internal DSLs cannot 100% implement their external language counter parts, as they have to adhere to the syntax rules of their host or target language (i.e. Java). This section explains the various problems and workarounds encountered and implemented in jOOQ.

    - +

    SQL allows for "keywordless" syntax

    SQL syntax does not always need keywords to form expressions. The clause takes various argument assignments:

    - + UPDATE t SET a = 1, b = 2 update(t).set(a, 1).set(b, 2) @@ -17559,12 +17559,12 @@ public final void sql(BindingSQLContext ctx) throws SQLException {

    In this case, ROW is an actual (optional) SQL keyword, implemented by at least PostgreSQL.

    - +

    SQL contains "composed" keywords

    As most languages, SQL does not attribute any meaning to whitespace. However, whitespace is important when forming "composed" keywords, i.e. SQL clauses composed of several keywords. jOOQ follows standard Java method naming conventions to map SQL keywords (case-insensitive) to Java methods (case-sensitive, camel-cased). Some examples:

    - + GROUP BY ORDER BY @@ -17577,7 +17577,7 @@ whenMatchedThenUpdate()

    Future versions of jOOQ may use all-uppercased method names in addition to the camel-cased ones (to prevent collisions with Java keywords):

    - + GROUP BY ORDER BY @@ -17608,7 +17608,7 @@ WHEN_MATCHED_THEN_UPDATE()

    The above example omits THEN and END keywords in Java. Future versions of jOOQ may comprise a more complete DSL, including such keywords again though, to provide a more 1:1 match for the SQL language.

    - +

    SQL contains "superfluous" syntactic elements

    Some SQL constructs are hard to map to Java, but they are also not really necessary. SQL often expects syntactic parentheses where they wouldn't really be needed, or where they feel slightly inconsistent with the rest of the SQL language. @@ -17645,7 +17645,7 @@ WHEN_MATCHED_THEN_UPDATE()

    jOOQ replaces those keywords by "synonyms":

    - + CASE .. ELSE PIVOT .. FOR .. IN .. @@ -17673,7 +17673,7 @@ pivot(..).on(..).in(..)

    Most SQL operators have to be mapped to descriptive method names in Java, as Java does not allow operator overloading:

    - + , != @@ -17702,7 +17702,7 @@ set(a, b)

    This is less of a syntactic SQL feature than a semantic one. In SQL, objects can be referenced before (i.e. "lexicographically before") they are declared. This is particularly true for

    - + @@ -17713,7 +17713,7 @@ select(t.a).from(t)]]>

    A more sophisticated example are common table expressions (CTE), which are currently not supported by jOOQ:

    - + WITH t(a, b) AS ( SELECT 1, 2 FROM DUAL ) @@ -17725,7 +17725,7 @@ FROM t

    - +
    jOOQ's BNF pseudo-notation @@ -17734,7 +17734,7 @@ FROM t

    - +
    Quality Assurance @@ -17746,16 +17746,16 @@ FROM t
  • To add lots of type-safety to your inline SQL
  • To increase productivity when writing inline SQL using your favourite IDE's autocompletion capabilities
  • - +

    With jOOQ being in the core of your application, you want to be sure that you can trust jOOQ. That is why jOOQ is heavily unit and integration tested with a strong focus on integration tests:

    - +

    Unit tests

    Unit tests are performed against dummy JDBC interfaces using http://jmock.org/. These tests verify that various implementations render correct SQL and bind variables correctly.

    - +

    Integration tests

    This is the most important part of the jOOQ test suites. Some 1500 queries are currently run against a standard integration test database. Both the test database and the queries are translated into every one of the 14 supported SQL dialects to ensure that regressions are unlikely to be introduced into the code base. @@ -17766,17 +17766,17 @@ FROM t

    jOOQ integration tests run the weirdest and most unrealistic queries. As a side-effect of these extensive integration test suites, many corner-case bugs for JDBC drivers and/or open source databases have been discovered, feature requests submitted through jOOQ and reported mainly to CUBRID, Derby, H2, HSQLDB.

    - +

    Code generation tests

    For every one of the 14 supported integration test databases, source code is generated and the tiniest differences in generated source code can be discovered. In case of compilation errors in generated source code, new test tables/views/columns are added to avoid regressions in this field.

    - +

    API Usability tests and proofs of concept

    jOOQ is used in jOOQ-meta as a proof of concept. This includes complex queries such as the following Postgres query

    - + These rather complex queries show that the jOOQ API is fit for advanced SQL use-cases, compared to the rather simple, often unrealistic queries in the integration test suite.

    - +

    Clean API and implementation. Code is kept DRY

    As a general rule of thumb throughout the jOOQ code, everything is kept DRY. Some examples: @@ -17841,19 +17841,19 @@ for (Record record : create.select(

    - +
    Migrating to jOOQ 3.0

    This section is for all users of jOOQ 2.x who wish to upgrade to the next major release. In the next sub-sections, the most important changes are explained. Some code hints are also added to help you fix compilation errors.

    - +

    Type-safe row value expressions

    Support for has been added in jOOQ 2.6. In jOOQ 3.0, many API parts were thoroughly (but often incompatibly) changed, in order to provide you with even more type-safety.

    - +

    Here are some affected API parts:

    @@ -17863,11 +17863,11 @@ for (Record record : create.select(
  • IN predicates and comparison predicates taking subselects changed incompatibly
  • INSERT and MERGE statements now take typesafe VALUES() clauses
  • - +

    Some hints related to row value expressions:

    - + record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result> result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch(); @@ -17875,31 +17875,31 @@ Result> result = create.select(BOOK.TITLE, BOOK.ID).fro // But Record2 extends Record. You don't have to use the additional typesafety: Record record = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).where(ID.eq(1)).fetchOne(); Result result = create.select(BOOK.TITLE, BOOK.ID).from(BOOK).fetch();]]> - +

    SelectQuery and SelectXXXStep are now generic

    In order to support type-safe row value expressions and type-safe Record[N] types, SelectQuery is now generic: SelectQuery<R>

    - +

    SimpleSelectQuery and SimpleSelectXXXStep API were removed

    The duplication of the SELECT API is no longer useful, now that SelectQuery and SelectXXXStep are generic.

    - +

    Factory was split into DSL (query building) and DSLContext (query execution)

    The pre-existing Factory class has been split into two parts:

    - +
    1. 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
    2. 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 renamed to DSLContext. An example:

    - + - +

    Quantified comparison predicates

    Field.equalAny(...) and similar methods have been removed in favour of Field.equal(any(...)). This greatly simplified the Field API. An example:

    - + > subselect = any(select(BOOK.ID).from(BOOK)); Condition condition = BOOK.ID.equal(subselect);]]> - +

    FieldProvider

    The FieldProvider marker interface was removed. Its methods still exist on FieldProvider subtypes. Note, they have changed names from getField() to field() and from getIndex() to indexOf()

    - +

    GroupField

    GroupField has been introduced as a DSL marker interface to denote fields that can be passed to GROUP BY clauses. This includes all org.jooq.Field types. However, fields obtained from ROLLUP(), CUBE(), and GROUPING SETS() functions no longer implement Field. Instead, they only implement GroupField. An example:

    - + field1a = Factory.rollup(...); // OK Field field2a = Factory.one(); // OK @@ -17945,19 +17945,19 @@ GroupField field1b = DSL.rollup(...); // OK Field field1c = DSL.rollup(...); // Compilation error GroupField field2b = DSL.one(); // OK Field field2c = DSL.one(); // OK]]> - +

    NULL predicate

    Beware! Previously, Field.equal(null) was translated internally to an IS NULL predicate. This is no longer the case. Binding Java "null" to a comparison predicate will result in a regular comparison predicate (which never returns true). This was changed for several reasons:

    - +
    • To most users, this was a surprising "feature".
    • Other predicates didn't behave in such a way, e.g. the IN predicate, the BETWEEN predicate, or the LIKE predicate.
    • Variable binding behaved unpredictably, as IS NULL predicates don't bind any variables.
    • The generated SQL depended on the possible combinations of bind values, which creates unnecessary hard-parses every time a new unique SQL statement is rendered.
    - +

    Here is an example how to check if a field has a given value, without applying SQL's ternary NULL logic:

    @@ -17970,7 +17970,7 @@ Condition condition1 = BOOK.TITLE.equal(possiblyNull); // jOOQ 3.0 Condition condition2 = BOOK.TITLE.equal(possiblyNull).or(BOOK.TITLE.isNull().and(val(possiblyNull).isNull())); Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    Configuration

    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 @@ -17984,7 +17984,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> In order to resolve confusion that used to arise because of different lifecycle durations, these types are now no longer formally connected through inheritance.

    - +

    ConnectionProvider

    In order to allow for simpler connection / data source management, jOOQ externalised connection handling in a new ConnectionProvider type. The previous two connection modes are maintained backwards-compatibly (JDBC standalone connection mode, pooled DataSource mode). Other connection modes can be injected using: @@ -17994,24 +17994,24 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> - +

    These are some side-effects of the above change

    - +
    • 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. This resolves many class loader issues that were encountered before. It also helps listener implementations control their lifecycles themselves.

    - +

    Data type API

    The data type API has been changed drastically in order to enable some new DataType-related features. These changes include: @@ -18021,16 +18021,16 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]>[SQLDialect]DataType and SQLDataType no longer implement DataType. They're mere constant containers

  • Various minor API changes have been done.
  • - +

    Object renames

    These objects have been moved / renamed:

    - +
    • jOOU: a library used to represent unsigned integer types was moved from org.jooq.util.unsigned to org.jooq.util.types (which already contained INTERVAL data types)
    - +

    Feature removals

    Here are some minor features that have been removed in jOOQ 3.0 @@ -18124,7 +18124,7 @@ Condition condition3 = BOOK.TITLE.isNotDistinctFrom(possiblyNull);]]> -->