This manual is divided into six main sections:
- -- This section will get you started with jOOQ quickly. It contains - simple explanations about what jOOQ is, what jOOQ isn't and how - to set it up for the first time -
-- This section explains all about the jOOQ syntax used for building - queries. It explains the central factories, the supported SQL - statements and various other syntax elements -
-- This section explains how to configure and use the built-in source code - generator -
-- This section will get you through the specifics of what can be done - with jOOQ at runtime, in order to execute queries, perform CRUD - operations, import and export data, and hook into the jOOQ execution - lifecycle for debugging -
-- This section is dedicated to tools that ship with jOOQ, such as the - jOOQ console -
-- This section is a reference for elements in this manual -
-- Java and SQL have come a long way. SQL is an "ancient", yet established and well-understood technology. Java is a legacy too, although its platform JVM allows for many new and contemporary languages built on top of it. Yet, after all these years, libraries dealing with the interface between SQL and Java have come and gone, leaving JPA to be a standard that is accepted only with doubts, short of any surviving options. -
-- So far, there had been only few database abstraction frameworks or libraries, that truly respected SQL as a first class citizen among languages. Most frameworks, including the industry standards JPA, EJB, Hibernate, JDO, Criteria Query, and many others try to hide SQL itself, minimising its scope to things called JPQL, HQL, JDOQL and various other inferior query languages -
-- jOOQ has come to fill this gap. -
- -- Other platforms incorporate ideas such as LINQ (with LINQ-to-SQL), or Scala's SLICK, or also Java's QueryDSL to better integrate querying as a concept into their respective language. By querying, they understand querying of arbitrary targets, such as SQL, XML, Collections and other heterogeneous data stores. jOOQ claims that this is going the wrong way too. -
-- In more advanced querying use-cases (more than simple CRUD and the occasional JOIN), people will want to profit from the expressivity of SQL. Due to the relational nature of SQL, this is quite different from what object-oriented and partially functional languages such as C#, Scala, or Java can offer. -
-- It is very hard to formally express and validate joins and the ad-hoc table expression types they create. It gets even harder when you want support for more advanced table expressions, such as pivot tables, unnested cursors, or just arbitrary projections from derived tables. With a very strong object-oriented typing model, these features will probably stay out of scope. -
-- In essence, the decision of creating an API that looks like SQL or one that looks like C#, Scala, Java is a definite decision in favour of one or the other platform. While it will be easier to evolve SLICK in similar ways as LINQ (or QueryDSL in the Java world), SQL feature scope that clearly communicates its underlying intent will be very hard to add, later on (e.g. how would you model Oracle's partitioned outer join syntax? How would you model ANSI/ISO SQL:1999 grouping sets? How can you support scalar subquery caching? etc...). -
-- jOOQ has come to fill this gap. -
- -- 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! -
-- These chapters contain a quick overview of how to get started with this manual and with jOOQ. While the subsequent chapters contain a lot of reference information, this chapter here just wraps up the essentials. -
-- This section helps you correctly interpret this manual in the context of jOOQ. -
- -- The following are code blocks: -
- -- 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
- See the manual's section about
- For the examples in this manual, the same database will always be referred to. It essentially consists of these entities created using the Oracle dialect -
-- More entities, types (e.g. UDT's, ARRAY types, ENUM types, etc), stored procedures and packages are introduced for specific examples -
-- jOOQ has originally been created as a library for complete abstraction of JDBC and all database interaction. Various best practices that are frequently encountered in pre-existing software products are applied to this library. This includes: -
-
- 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
- ... 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: -
-- The following sections explain about various use cases for using jOOQ in your application. -
-
- 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
- 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. -
-- If you wish to use jOOQ only as a SQL builder, the following sections of the manual will be of interest to you: -
-
- In addition to using jOOQ as a
- 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. -
-- If you wish to use jOOQ only as a SQL builder with code generation, the following sections of the manual will be of interest to you: -
-- 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: -
- -- jOOQ doesn't stop here, though! You can execute any SQL with jOOQ. In other words, you can use any other SQL building tool and run the SQL statements with jOOQ. An example is given here: -
- -- If you wish to use jOOQ as a SQL executor with (or without) code generation, the following sections of the manual will be of interest to you: -
-- This is probably the most complete use-case for jOOQ: Use all of jOOQ's features. Apart from jOOQ's fluent API for query construction, jOOQ can also help you execute everyday CRUD operations. An example is given here: -
- -- If you wish to use all of jOOQ's features, the following sections of the manual will be of interest to you (including all sub-sections): -
-
- jOOQ isn't just a library that helps you
- If you're a power user of your favourite, feature-rich database, jOOQ will help you access all of your database's vendor-specific features, such as OLAP features, stored procedures, user-defined types, vendor-specific SQL, functions, etc. Examples are given throughout this manual. -
-- Don't have time to read the full manual? Here are a couple of tutorials that will get you into the most essential parts of jOOQ as quick as possible. -
-- This manual section is intended for new users, to help them get a running application with jOOQ, quickly. -
-
- If you haven't already downloaded it, download jOOQ:
- http://www.jooq.org/download
-
- Alternatively, you can create a Maven dependency: -
-
- For this example, we'll be using MySQL. If you haven't already downloaded MySQL Connector/J, download it here:
- http://dev.mysql.com/downloads/connector/j/
-
- If you don't have a MySQL instance up and running yet, get XAMPP now! XAMPP is a simple installation bundle for Apache, MySQL, PHP and Perl -
-- 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: -
- -
- In this step, we're going to use jOOQ's command line tools to generate classes that map to the Posts table we just created. More detailed information about how to set up the jOOQ code generator can be found here:
-
- 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: -
- -- Replace the username with whatever user has the appropriate privileges to query the database meta data. You'll also want to look at the other values and replace as necessary. Here are the two interesting properties: -
-
- generator.target.package - set this to the parent package you want to create for the generated classes. The setting of test.generated will cause the test.generated.Posts and test.generated.PostsRecord to be created
-
- 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: -
- -- ... or type this on a UNIX / Linux / Mac system (colons instead of semi-colons): -
- -- There are two things to note: -
- -- 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: -
- -- Let's just write a vanilla main class in the project containing the generated classes: -
- -- This is pretty standard code for establishing a MySQL connection. -
-- Let's add a simple query: -
- -
- First get an instance of Factory so we can write a simple SELECT query. We pass an instance of the MySQL connection to Factory. Note that the factory doesn't close the connection. We'll have to do that ourselves.
-
- We then use jOOQ's DSL to return an instance of Result. We'll be using this result in the next step. -
-- After the line where we retrieve the results, let's iterate over the results and print out the data: -
- -- The full program should now look like this: -
- -
- jOOQ has grown to be a comprehensive SQL library. For more information, please consider the manual:
- http://www.jooq.org/manual/
-
- ... explore the Javadoc:
- http://www.jooq.org/javadoc/latest/
-
- ... or join the news group:
- https://groups.google.com/forum/#!forum/jooq-user
-
- This tutorial is the courtesy of Ikai Lan. See the original source here:
- http://ikaisays.com/2011/11/01/getting-started-with-jooq-a-tutorial/
-
Feel free to contribute a tutorial!
-Feel free to contribute a tutorial!
-Feel free to contribute a tutorial!
-- jOOQ has no dependencies on any third-party libraries. This rule has some exceptions: -
-- In order to build jOOQ, please download the sources from https://github.com/jOOQ/jOOQ and use Maven to build it, preferably in Eclipse. -
-- SQL is a declarative language that is hard to integrate into procedural, object-oriented, functional or any other type of programming languages. jOOQ's philosophy is to give SQL the credit it deserves and integrate SQL itself as an "internal domain specific language" directly into Java. -
-
- With this philosophy in mind, SQL building is the main feature of jOOQ. All other features (such as
- This section explains all about the various syntax elements involved with jOOQ's SQL building capabilities. For a complete overview of all syntax elements, please refer to the manual's section about
- jOOQ exposes a lot of interfaces and hides most implementation facts from client code. The reasons for this are: -
-
- The
- With jOOQ 2.0, static factory methods have been introduced in order to make client code look more like SQL. Ideally, when working with jOOQ, you will simply static import all methods from the Factory class: -
-- Note, that when working with Eclipse, you could also add the Factory to your favourites. This will allow to access functions even more fluently: -
-- As any Configuration object, a Factory can be supplied with these objects: -
-
- As a Configuration object, a Factory can construct
- While jOOQ tries to represent the SQL standard as much as possible, many features are vendor-specific to a given database and to its "SQL dialect". jOOQ models this using the
- The SQL dialect is one of the main attributes of a
- Some parts of the jOOQ API are officially supported only by a given subset of the supported SQL dialects. For instance, the
- jOOQ API methods which are not annotated with the
- The aforementioned Support annotation does not only designate, which databases natively support a feature. It also indicates that a feature is emulated by jOOQ for some databases lacking this feature. An example of this is the
- Nevertheless, the IS DISTINCT FROM predicate is supported in all dialects, as its semantics can be expressed with an equivalent
- 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 -
-- jOOQ has a historic affinity to Oracle's SQL extensions. If something is supported in Oracle SQL, it has a high probability of making it into the jOOQ API -
-
- While you can use jOOQ for
- If you're in a J2EE or Spring context, however, you may wish to use a
- The jOOQ Factory allows for some optional configuration elements to be used by advanced users. The
- For example, if you want to indicate to jOOQ, that it should inline all bind variables, and execute static
- Subsequent sections of the manual contain some more in-depth explanations about these settings: -
-
- Please refer to the jOOQ runtime configuration XSD for more details:
- http://www.jooq.org/xsd/jooq-runtime-2.5.0.xsd
-
- 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: -
-
- When a user from My Book World logs in, you want them to access the MY_BOOK_WORLD schema using classes generated from DEV. This can be achieved with the
- The query executed with a Factory equipped with the above mapping will in fact produce this SQL statement: -
- -- Even if AUTHOR was generated from DEV. -
- -- Your development database may not be restricted to hold only one DEV schema. You may also have a LOG schema and a MASTER schema. Let's say the MASTER schema is shared among all customers, but each customer has their own LOG schema instance. Then you can enhance your RenderMapping like this (e.g. using an XML configuration file): -
- -- Note, you can load the above XML file like this: -
- -- This will map generated classes from DEV to MY_BOOK_WORLD, from LOG to MY_BOOK_WORLD_LOG, but leave the MASTER schema alone. Whenever you want to change your mapping configuration, you will have to create a new Factory -
- - -- Another option to switch schema names is to use a default schema for the Factory's underlying Connection. Many RDBMS support a USE or SET SCHEMA command, which you can call like this: -
- -- Queries generated from the above Factory will produce this kind of SQL statement: -
- -- If you wish not to render any schema name at all, use the following Settings property for this: -
- - -- Not only schemata can be mapped, but also tables. If you are not the owner of the database your application connects to, you might need to install your schema with some sort of prefix to every table. In our examples, this might mean that you will have to map DEV.AUTHOR to something MY_BOOK_WORLD.MY_APP__AUTHOR, where MY_APP__ is a prefix applied to all of your tables. This can be achieved by creating the following mapping: -
- -- The query executed with a Factory equipped with the above mapping will in fact produce this SQL statement: -
- -- 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! -
- -
- Note that the manual's section about
- There are a couple of subclasses for the general Factory. Each SQL dialect has its own dialect-specific factory. For instance, if you're only using the MySQL dialect, you can choose to create a new Factory using any of the following types: -
-- The advantage of using a dialect-specific Factory lies in the fact, that you have access to more proprietary RDMBS functionality. This may include: -
-- Another type of Factory subclasses are each generated schema's factories. If you generate your schema TEST, then you will have access to a TestFactory. By default, such a schema-specific Factory will not render the schema name. -
-
- jOOQ currently supports 6 types of SQL statements. All of these statements are constructed from a Factory instance with an optional
- jOOQ ships with its own DSL (or Domain Specific Language) that emulates SQL in Java. This means, that you can write SQL statements almost as if Java natively supported it, just like .NET's C# does with LINQ to SQL. -
-- Here is an example to illustrate what that means: -
- -
- We'll see how the aliasing works later in the section about
- Many other frameworks have similar APIs with similar feature sets. Yet, what makes jOOQ special is its informal
- Unlike other, simpler frameworks that use "fluent APIs" or "method chaining", jOOQ's BNF-based interface hierarchy will not allow bad query syntax. The following will not compile, for instance: -
-
- 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
- This query is equivalent to the one shown before using the DSL syntax. In fact, internally, the DSL API constructs precisely this QueryObject. Note, that you can always access the SelectQuery object to switch between DSL and non-DSL APIs: -
- -
- Note, that for historic reasons, the DSL API mixes mutable and immutable behaviour with respect to the internal representation of the
- Mutability may be removed in a future version of jOOQ. -
-
- When you don't just perform
- Details about the various clauses of this query will be provided in subsequent sections -
- -
- A very similar, but limited API is available, if you want to select from single tables in order to retrieve
- As you can see, there is no way to further restrict/project the selected fields. This just selects all known TableFields in the supplied Table, and it also binds <R extends Record> to your Table's associated Record. An example of such a Query would then be: -
-- The simple SELECT API is limited in the way that it does not support any of these clauses: -
-
- In most parts of this manual, it is assumed that you do not use the simple SELECT API. For more information about the simple SELECT API, see the manual's section about
- The SELECT clause lets you project your own record types, referencing table fields, functions, arithmetic expressions, etc. The Factory provides several methods for expressing a SELECT clause: -
- -- Some commonly used projections can be easily created using convenience methods: -
- -
- See more details about functions and expressions in the manual's section about
- The DISTINCT keyword can be included in the method name, constructing a SELECT clause -
- -
- The SQL FROM clause allows for specifying any number of
- Read more about aliasing in the manual's section about
- Apart from simple tables, you can pass any arbitrary
- Note, in order to access the DbmsXplan package, you can use the
- In many SQL dialects, FROM is a mandatory clause, in some it isn't. jOOQ allows you to omit the FROM clause, returning just one record. An example: -
- -
- Read more about dual or dummy tables in the manual's section about
- jOOQ supports many different types of standard SQL JOIN operations: -
-
- All of these JOIN methods can be called on
- The two syntaxes will produce the same SQL statement. However, calling "join" on
- Surprisingly, SQL does not allow to formally JOIN on well-known foreign key relationship information. Naturally, when you join BOOK to AUTHOR, you will want to do that based on the BOOK.AUTHOR_ID foreign key to AUTHOR.ID primary key relation. Not being able to do this in SQL leads to a lot of repetitive code, re-writing the same JOIN predicate again and again - especially, when your foreign keys contain more than one column. With jOOQ, when you use
- In case of ambiguity, you can also supply field references for your foreign keys, or the generated foreign key reference to the onKey() method. -
- -- Most often, you will provide jOOQ with JOIN conditions in the JOIN .. ON clause. SQL supports a different means of specifying how two tables are to be joined. This is the JOIN .. USING clause. Instead of a condition, you supply a set of fields whose names are common to both tables to the left and right of a JOIN operation. This can be useful when your database schema has a high degree of relational normalisation. An example: -
- -- In schemas with high degrees of normalisation, you may also choose to use NATURAL JOIN, which takes no JOIN arguments as it joins using all fields that are common to the table expressions to the left and to the right of the JOIN operator. An example: -
- -- Oracle SQL ships with a special syntax available for OUTER JOIN clauses. According to the Oracle documentation about partitioned outer joins this can be used to fill gaps for simplified analytical calculations. jOOQ only supports putting the PARTITION BY clause to the right of the OUTER JOIN clause. The following example will create at least one record per AUTHOR and per existing value in BOOK.PUBLISHED_IN, regardless if an AUTHOR has actually published a book in that year. -
- -
- The WHERE clause can be used for JOIN or filter predicates, in order to restrict the data returned by the
- The above syntax is convenience provided by jOOQ, allowing you to connect the
- You will find more information about creating
- The Oracle database knows a very succinct syntax for creating hierarchical queries: the CONNECT BY clause, which is fully supported by jOOQ, including all related functions and pseudo-columns. A more or less formal definition of this clause is given here: -
-- An example for an iterative query, iterating through values between 1 and 5 is this: -
- -- Here's a more complex example where you can recursively fetch directories in your database, and concatenate them to a path: -
-- The output might then look like this -
- -
- Some of the supported functions and pseudo-columns are these (available from the
- Note that this syntax is also supported in the CUBRID database. -
-
- GROUP BY can be used to create unique groups of data, to form aggregations, to remove duplicates and for other reasons. It will transform your previously defined
- 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 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 are 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: -
- -- This will return an arbitrary title per author. jOOQ supports this syntax, as jOOQ is not doing any checks internally, about the consistence of tables/fields/functions that you provide it. -
- -
- jOOQ supports empty GROUP BY () clauses as well. This will result in
- Some databases support the SQL standard grouping functions and some extensions thereof. See the manual's section about
- The HAVING clause is commonly used to further restrict data resulting from a previously issued
- According to the SQL standard, you may omit the GROUP BY clause and still issue a HAVING clause. This will implicitly GROUP BY (). jOOQ also supports this syntax. The following example selects one record, only if there are at least 4 books in the books table: -
- -- Databases are allowed to return data in any arbitrary order, unless you explicitly declare that order in the ORDER BY clause. In jOOQ, this is straight-forward: -
- -
- Any jOOQ
- The SQL standard allows for specifying integer literals (
- Note, how one() is used as a convenience short-cut for inline(1) -
- -- A few databases support the SQL standard "null ordering" clause in sort specification lists, to define whether NULL values should come first or last in an ordered result. -
- -
- If your database doesn't support this syntax, jOOQ emulates it using a
- Using
- But writing these things can become quite verbose. jOOQ supports a convenient syntax for specifying sort mappings. The same query can be written in jOOQ as such: -
- -- More complex sort indirections can be provided using a Map: -
- -- Of course, you can combine this feature with the previously discussed NULLS FIRST / NULLS LAST feature. So, if in fact these two books are the ones you like least, you can put all NULLS FIRST (all the other books): -
- -
- The SQL standard defines that a "query expression" can be ordered, and that query expressions can contain
- While being extremely useful for every application that does pagination, or just to limit result sets to reasonable sizes, this clause is not yet part of any SQL standard (up until SQL:2008). Hence, there exist a variety of possible implementations in various SQL dialects, concerning this limit clause. jOOQ chose to implement the LIMIT .. OFFSET clause as understood and supported by MySQL, H2, HSQLDB, Postgres, and SQLite. Here is an example of how to apply limits with jOOQ: -
- -
- This will limit the result to 1 books starting with the 2nd book (starting at offset 0!). limit() is supported in all dialects, offset() in all but Sybase ASE, which has no reasonable means to emulate it. This is how jOOQ trivially emulates the above query in various SQL dialects with native OFFSET pagination support:
-
- Things get a little more tricky in those databases that have no native idiom for OFFSET pagination (actual queries may vary):
-
- 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. -
- -- As can be seen in the above example, writing correct SQL can be quite tricky, depending on the SQL dialect. For instance, with SQL Server, you cannot have an ORDER BY clause in a subquery, unless you also have a TOP clause. This is illustrated by the fact that jOOQ renders a TOP 100 PERCENT clause for you. The same applies to the fact that ROW_NUMBER() OVER() needs an ORDER BY windowing clause, even if you don't provide one to the jOOQ query. By default, jOOQ adds ordering by the first column of your projection. -
-- For inter-process synchronisation and other reasons, you may choose to use the SELECT .. FOR UPDATE clause to indicate to the database, that a set of cells or records should be locked by a given transaction for subsequent updates. With jOOQ, this can be achieved as such: -
- -- The above example will produce a record-lock, locking the whole record for updates. Some databases also support cell-locks using FOR UPDATE OF .. -
- -- Oracle goes a bit further and also allows to specify the actual locking behaviour. It features these additional clauses, which are all supported by jOOQ: -
-- With jOOQ, you can use those Oracle extensions as such: -
- -- The SQL standard specifies a FOR UPDATE clause to be applicable for cursors. Most databases interpret this as being applicable for all SELECT statements. An exception to this rule are the CUBRID and SQL Server databases, that do not allow for any FOR UPDATE clause in a regular SQL SELECT statement. jOOQ emulates the FOR UPDATE behaviour, by locking record by record with JDBC. JDBC allows for specifying the flags TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE for any statement, and then using ResultSet.updateXXX() methods to produce a cell-lock / row-lock. Here's a simplified example in JDBC: -
-- The main drawback of this approach is the fact that the database has to maintain a scrollable cursor, whose records are locked one by one. This can cause a major risk of deadlocks or race conditions if the JDBC driver can recover from the unsuccessful locking, if two Java threads execute the following statements: -
- -- So use this technique with care, possibly only ever locking single rows! -
- -- Some databases (MySQL, Postgres) also allow to issue a non-exclusive lock explicitly using a FOR SHARE clause. This is also supported by jOOQ -
- -
- Note, that jOOQ also supports optimistic locking, if you're doing simple CRUD. This is documented in the section's manual about
- 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
- 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. -
- -- 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. -
- -
- As previously mentioned in the manual's section about the
- If you are closely coupling your application to an Oracle (or CUBRID) database, you might need to be able to pass hints of the form /*+HINT*/ with your SQL statements to the Oracle database. For example: -
- -- This can be done in jOOQ using the .hint() clause in your SELECT statement: -
- -- 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 -
-- The INSERT statement is used to insert new records into a database table. 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: -
- - -- 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 -
-- jOOQ tries to stay close to actual SQL. In detail, however, Java's expressiveness is limited. That's why the values() clause is repeated for every record in multi-record inserts. -
-- Some RDBMS do not support inserting several records in a single statement. In those cases, jOOQ emulates multi-record INSERTs using the following SQL: -
- -- MySQL (and some other RDBMS) allow for using a non-SQL-standard, UPDATE-like syntax for INSERT statements. This is also supported in jOOQ (and emulated for all databases), should you prefer that syntax. The above INSERT statement can also be expressed as follows: -
- -- 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. -
- -
- 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
- 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
- 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
- Some databases have poor support for returning generated keys after INSERTs. In those cases, jOOQ might need to issue another
- In some occasions, you may prefer the INSERT SELECT syntax, for instance, when you copy records from one table to another: -
- -- The UPDATE statement is used to modify one or several pre-existing records in a database table. UPDATE statements are only possible on single tables. Support for multi-table updates will be implemented in the near future. An example update query is given here: -
- -- The DELETE statement removes records from a database table. DELETE statements are only possible on single tables. Support for multi-table deletes will be implemented in the near future. An example delete query is given here: -
- -- The MERGE statement is one of the most advanced standardised SQL constructs, which is supported by DB2, HSQLDB, Oracle, SQL Server and Sybase (MySQL has the similar INSERT .. ON DUPLICATE KEY UPDATE construct) -
-- The point of the standard MERGE statement is to take a TARGET table, and merge (INSERT, UPDATE) data from a SOURCE table into it. DB2, Oracle, SQL Server and Sybase also allow for DELETING some data and for adding many additional clauses. With jOOQ {jooq-version}, only Oracle's MERGE extensions are supported. Here is an example: -
- -- 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: -
- -
- 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
-
- The TRUNCATE statement is the only DDL statement supported by jOOQ so far. It is popular in many databases when you want to bypass constraints for table truncation. Databases may behave differently, when a truncated table is referenced by other tables. For instance, they may fail if records from a truncated table are referenced, even with ON DELETE CASCADE clauses in place. Please, consider your database manual to learn more about its TRUNCATE implementation. -
-- The TRUNCATE syntax is trivial: -
- -- TRUNCATE is not supported by Ingres and SQLite. jOOQ will execute a DELETE FROM AUTHOR statement instead. -
-- The following sections explain the various types of table expressions supported by jOOQ -
-
- Most of the times, when thinking about a
- The above example shows how AUTHOR and BOOK tables are joined in a
- See the manual's section about
- The strength of jOOQ's
- 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. -
- -- TODO document this -
-
- The
- SQL and relational algebra distinguish between at least the following JOIN types (upper-case: SQL, lower-case: relational algebra): -
-
- jOOQ supports all of these JOIN types (except semi-join and anti-join) directly on any
- Note that most of jOOQ's JOIN operations give way to a similar DSL API hierarchy as previously seen in the manual's section about the
- A
- 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: -
- -
- The PIVOT clause is available from the
- There is one operation in relational algebra that is not given a lot of attention, because it is rarely used in real-world applications. It is the relational division, the opposite operation of the cross product (or, relational multiplication). The following is an approximate definition of a relational division: -
- -- With jOOQ, you can simplify using relational divisions by using the following syntax: -
- -- The above roughly translates to -
- -- Or in plain text: Find those TEXT values in C whose ID's correspond to all ID's in B. Note that from the above SQL statement, it is immediately clear that proper indexing is of the essence. Be sure to have indexes on all columns referenced from the on(...) and returning(...) clauses. -
- -- For more information about relational division and some nice, real-life examples, see -
- - -
- 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
- 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. -
- -
- The real power of these types become more obvious when you fetch them from
- Note, in order to access the DbmsXplan package, you can use the
- The SQL standard specifies that the
FROM clause (as required by the SQL standard)FROM clause (and still allow a WHERE clause)FROM clause only with a WHERE clause, GROUP BY clause, or HAVING clause- With jOOQ, you don't have to worry about the above distinction of SQL dialects. jOOQ never requires a FROM clause, but renders the necessary "DUAL" table, if needed. The following program shows how jOOQ renders "DUAL" tables -
- -- Note, that some databases (H2, MySQL) can normally do without "dual". However, there exist some corner-cases with complex nested SELECT statements, where this will cause syntax errors (or parser bugs). To stay on the safe side, jOOQ will always render "dual" in those dialects. -
-
- jOOQ allows you to freely create arbitrary column expressions using a fluent expression construction API. Many expressions can be formed as functions from
- In general, it is up to you whether you want to use the "prefix" notation or the "postfix" notation to create new column expressions based on existing ones. The "SQL way" would be to use the "prefix notation", with functions created from the
- Table columns are the most simple implementations of a
- Table columns implement a more specific interface called
- See the manual's section about
- Just like
- Here is how it's done with jOOQ: -
- -- When you alias Fields like above, you can access those Fields' values using the alias name: -
- -- jOOQ's source code generator tries to find the most accurate type mapping between your vendor-specific data types and a matching Java type. For instance, most VARCHAR, CHAR, CLOB types will map to String. Most BINARY, BYTEA, BLOB types will map to byte[]. NUMERIC types will default to java.math.BigDecimal, but can also be any of java.math.BigInteger, Long, Integer, Short, Byte, Double, Float. -
-- 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: -
- -- in jOOQ, you can write something like that: -
- -- 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 -
- -- The complete CAST API in Field consists of these three methods: -
- -
- Your database can do the math for you. Arithmetic operations are implemented just like
- In order to express a SQL query like this one: -
- -- You can write something like this in jOOQ: -
- -- jOOQ also supports the Oracle-style syntax for adding days to a Field<? extends java.util.Date> -
- -- For more advanced datetime arithmetic, use the Factory's timestampDiff() and dateDiff() functions, as well as jOOQ's built-in SQL standard INTERVAL data type support: -
-
- The SQL standard defines the concatenation operator to be an infix operator, similar to the ones we've seen in the chapter about ||. Some other dialects do not support this operator, but expect a concat() function, instead. jOOQ renders the right operator / function, depending on your
- There are a variety of general functions supported by jOOQ As discussed in the chapter about
- This is a list of general functions supported by jOOQ's
- Please refer to the
- Math can be done efficiently in the database before returning results to your Java application. In addition to the
- This is a list of numeric functions supported by jOOQ's
- Please refer to the
- Interestingly, bitwise functions and bitwise arithmetic is not very popular among SQL databases. Most databases only support a few bitwise operations, while others ship with the full set of operators. jOOQ's API includes most bitwise operations as listed below. In order to avoid ambiguities with
- 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/
-
- String formatting can be done efficiently in the database before returning results to your Java application. As discussed in the chapter about
- This is a list of numeric functions supported by jOOQ's
- Please refer to the
- Various databases have some means of searching through columns using regular expressions if the
- Note that the SQL standard specifies that patterns should follow the XQuery standards. In the real world, the POSIX regular expression standard is the most used one, some use Java regular expressions, and only a few ones use Perl regular expressions. jOOQ does not make any assumptions about regular expression syntax. For cross-database compatibility, please read the relevant database manuals carefully, to learn about the appropriate syntax. Please refer to the
- This is a list of date and time functions supported by jOOQ's
- 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
- This is a list of system functions supported by jOOQ's
- Aggregate functions work just like functions, even if they have a slightly different semantics. Here are some example aggregate functions from the
- Here's an example, counting the number of books any author has written: -
- -
- Aggregate functions have strong limitations about when they may be used and when not. For instance, you can use aggregate functions in scalar queries. Typically, this means you only select aggregate functions, no
- Oracle and some other databases support "ordered-set aggregate functions". This means you can provide an ORDER BY clause to an aggregate function, which will be taken into consideration when aggregating. The best example for this is Oracle's LISTAGG() (also known as GROUP_CONCAT in other
- The above query might yield: -
- -
- Oracle allows for restricting aggregate functions using the KEEP() clause, which is supported by jOOQ. In Oracle, some aggregate functions (MIN, MAX, SUM, AVG, COUNT, VARIANCE, or STDDEV) can be restricted by this clause, hence
- jOOQ also supports using your own user-defined aggregate functions. See the manual's section about
- In those databases that support over() on it. See the manual's section about
- Most major RDBMS support the concept of window functions. jOOQ knows of implementations in DB2, Oracle, Postgres, SQL Server, and Sybase SQL Anywhere, and supports most of their specific syntaxes. Note, that H2 and HSQLDB have implemented ROW_NUMBER() functions, without true windowing support.
-
- As previously discussed, any over() method. See the chapter about
- 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:
-
- If possible, however, jOOQ tries to render missing clauses for you, if a given
- Here are some simple examples of window functions with jOOQ: -
- -
- 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 over() method:
-
- In the previous chapter about LISTAGG(). These functions have a window function / analytical function variant, as well. For example:
-
- In the previous chapter about
- User-defined aggregate functions also implement over(). This is supported by Oracle in particular. See the manual's section about
- The SQL standard defines special functions that can be used in the
- 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:
-
- CUBE() is different from ROLLUP() in the way that it doesn't just create N+1 groupings, it creates all 2^N possible combinations between all group fields in the CUBE() function argument list. Let's re-consider our second query from before:
-
- The results would then hold: -
- -
- GROUPING SETS() are the generalised way to create multiple groupings. From our previous examples
-
ROLLUP(AUTHOR_ID, PUBLISHED_IN) corresponds to GROUPING SETS((AUTHOR_ID, PUBLISHED_IN), (AUTHOR_ID), ())CUBE(AUTHOR_ID, PUBLISHED_IN) corresponds to GROUPING SETS((AUTHOR_ID, PUBLISHED_IN), (AUTHOR_ID), (PUBLISHED_IN), ())
- This is nicely explained in the SQL Server manual pages about GROUPING SETS() and other grouping functions:
- http://msdn.microsoft.com/en-us/library/bb510427(v=sql.105)
-
- 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
- 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
- The above function will be made available from a generated
- Note that user-defined functions returning
- Some databases support user-defined aggregate functions, which can then be used along with
- The above OBJECT type is then available to function declarations as such: -
- -
- jOOQ's
- The CASE expression is part of the standard SQL syntax. While some RDBMS also offer an IF expression, or a DECODE function, you can always rely on the two types of CASE syntax: -
- -- In jOOQ, both syntaxes are supported (The second one is emulated in Derby, which only knows the first one). Unfortunately, both case and else are reserved words in Java. jOOQ chose to use decode() from the Oracle DECODE function, and otherwise(), which means the same as else. -
- -
- A CASE expression can be used anywhere where you can place a
- Oracle knows a more succinct, but maybe less readable DECODE() function with a variable number of arguments. This function roughly does the same as the second case expression syntax. jOOQ supports the DECODE() function and emulates it using CASE expressions in all dialects other than Oracle: -
- -
- Sort indirection is often implemented with a CASE clause of a SELECT's ORDER BY clause. See the manual's section about the
- Sequences implement the
- So if you have a sequence like this in Oracle: -
- -
- You can then use your
- Conditions or conditional expressions are widely used in SQL and in the jOOQ API. They can be used in -
-- 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: -
-- It is important to know that SQL differs from many other languages in the way it interprets the NULL boolean value. Most importantly, the following facts are to be remembered: -
-
- For simplified NULL handling, please refer to the section about the
- Note that jOOQ does not model these values as actual
- With jOOQ, most
- There are a few types of conditions, that can be created statically from the
- Conditions can also be connected using
- In SQL, as in most other languages,
- The above example shows that the number of parentheses in Java can quickly explode. Proper indentation may become crucial in making such code readable. In order to understand how jOOQ composes combined conditional expressions, let's assign component expressions first: -
- -
- Here are all boolean operators on the
- In SQL, comparison predicates are formed using common comparison operators: -
-
- 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
- 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 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
- In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using comparison predicates: -
- -
- If the right-hand side of a
- For the example, the right-hand side of the quantified comparison predicates were filled with argument lists. But it is easy to imagine that the source of values results from a
- It is interesting to note that the SQL standard defines the
- Typically, the
- In SQL, you cannot compare NULL with any value using
- Some databases support the DISTINCT predicate, which serves as a convenient, NULL-safe
- For instance, you can compare two fields for distinctness, ignoring the fact that any of the two could be NULL, which would lead to funny results. This is supported by jOOQ as such: -
- -
- If your database does not natively support the DISTINCT predicate, jOOQ emulates it with an equivalent
- The BETWEEN predicate can be seen as syntactic sugar for a pair of
- Note the inclusiveness of range boundaries in the definition of the BETWEEN predicate. Intuitively, this is supported in jOOQ as such: -
- -- 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: -
- -- LIKE predicates are popular for simple wildcard-enabled pattern matching. Supported wildcards in all SQL databases are: -
-
- With jOOQ, the LIKE predicate can be created from any
- 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: -
- -- In the above predicate expressions, the exclamation mark character is passed as the escape character to escape wildcard characters "!_" and "!%", as well as to escape the escape character itself: "!!" -
-- Please refer to your database manual for more details about escaping patterns with 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: -
- -- Note, that jOOQ escapes % and _ characters in value in some of the above predicate implementations. For simplicity, this has been omitted in this manual. -
-
- In SQL, apart from comparing a value against several values, the IN predicate can be used to create semi-joins or anti-joins. jOOQ knows the following methods on the
- A sample IN predicate might look like this: -
- -- 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: -
- -
- A good way to prevent this from happening is to use the
- Slightly less intuitive, yet more powerful than the previously discussed
- An example of an EXISTS predicate can be seen here: -
- -
- 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()
- 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:
- http://blog.jooq.org/2012/07/27/not-in-vs-not-exists-vs-left-join-is-null-mysql/
-
- A DSL is a nice thing to have, it feels "fluent" and "natural", especially if it models a well-known language, such as SQL. But a DSL is always expressed in a host language (Java in this case), which was not made for exactly the same purposes as its hosted DSL. If it were, then jOOQ would be implemented on a compiler-level, similar to LINQ in .NET. But it's not, and so, the DSL is limited by language constraints of its host language. We have seen many functionalities where the DSL becomes a bit verbose. This can be especially true for: -
-- 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! -
-
- jOOQ allows you to embed SQL as a String into any supported
- Plain SQL API methods are usually overloaded in three ways. Let's look at the condition query part constructor:
-
- Please refer to the
- 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: -
- -- There are some important things to keep in mind when using plain SQL: -
-- Bind values are used in SQL / JDBC for various reasons. Among the most obvious ones are: -
-- 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. -
-- 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
- Should you decide to run the above query outside of jOOQ, using your own
- You can also extract specific bind values by index from a query, if you wish to modify their underlying value after creating a query. This can be achieved as such: -
- -
- For more details about jOOQ's internals, see the manual's section about
- Some SQL access abstractions that are built on top of JDBC, or some that bypass JDBC may support named parameters. jOOQ allows you to give names to your parameters as well, although those names are not rendered to SQL strings by default. Here is an example of how to create named parameters using the
- The
- In order to actually render named parameter names in generated SQL, use the
- Sometimes, you may wish to avoid rendering bind variables while still using custom values in SQL. jOOQ refers to that as "inlined" bind values. When bind values are inlined, they render the actual value in SQL rather than a JDBC question mark. Bind value inlining can be achieved in two ways: -
-- In both cases, your inlined bind values will be properly escaped to avoid SQL syntax errors and SQL injection. Some examples: -
- -
- Special care needs to be taken when using
- All methods in the jOOQ API that allow for plain (unescaped, untreated) SQL contain a warning message in their relevant Javadoc, to remind you of the risk of SQL injection in what is otherwise a SQL-injection-safe API. -
-
- A
- Both of these methods are contained in jOOQ's internal API's
- The following sections explain some more details about
- Every
- An overview of the
- The following additional methods are inherited from a common
- A simple example can be provided by checking out jOOQ's internal representation of a (simplified)
- This is how jOOQ renders such a condition: -
- -
- See the manual's sections about
- Every
- An overview of the
- Some additional methods are inherited from a common
- A simple example can be provided by checking out jOOQ's internal representation of a (simplified)
- This is how jOOQ binds values on such a condition: -
-
- See the manual's sections about
- 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: -
- -
- 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
- 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
- If you don't need the integration of rather complex QueryParts into jOOQ, then you might be safer using simple
- The above distinction is best explained using an example: -
- -
- The above technique allows for creating rather complex SQL clauses that are currently not supported by jOOQ, without extending any of the
- The only transient, non-serializable element in any jOOQ object is the
- Another way of attaching QueryParts automatically, or rather providing them with a new
- In a previous section of the manual, we've seen how jOOQ can be used to
- JDBC calls executable objects "
- 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
- 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
- The following sections of this manual will show how jOOQ is wrapping JDBC for SQL execution -
-
- Even if there are
- Some of the most important differences between JDBC and jOOQ are listed here: -
-
- Unlike JDBC, jOOQ has a lot of knowledge about a SQL query's structure and internals (see the manual's section about
- Fetching is something that has been completely neglegted by JDBC and also by various other database abstraction libraries. Fetching is much more than just looping or listing records or mapped objects. There are so many ways you may want to fetch data from a database, it should be considered a first-class feature of any database abstraction API. Just to name a few, here are some of jOOQ's fetching modes: -
-
- The term "fetch" is always reused in jOOQ when you can fetch data from the database. An
- These modes of fetching are also documented in subsequent sections of the manual -
- -
- These means of fetching are also available from
- These means of fetching are also available from
- Note, that apart from the
- jOOQ understands that SQL is much more expressive than Java, when it comes to the declarative typing of
- When fetching data only from a single table, the
- When you use the
- 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: -
- -- It is worth mentioning that Scala is much stronger in inferring types than Java. Yet still, this becomes quickly impracticable as -
-- For these reasons jOOQ does not support generic tuples. -
-
- By default, jOOQ returns an
- Note that most of these convenience methods are available both through
- 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
- Fetching data in records is fine as long as your application is not really layered, or as long as you're still writing code in the DAO layer. But if you have a more advanced application architecture, you may not want to allow for jOOQ artefacts to leak into other layers. You may choose to write POJOs (Plain Old Java Objects) as your primary DTOs (Data Transfer Objects), without any dependencies on jOOQ's
- If you're using jOOQ's
- 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
- Just as with any other JPA implementation, you can put the
- If jOOQ does not find any JPA-annotations, columns are mapped to the "best-matching" constructor, attribute or setter. An example illustrates this: -
- -
- Please refer to the
- jOOQ also allows for fetching data into abstract classes or interfaces, or in other words, "proxyable" types. This means that jOOQ will return a
- Please refer to the
- The above examples show how to fetch data into your own custom POJOs / DTOs. When you have modified the data contained in POJOs, you probably want to store those modifications back to the database. 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
- If you're using jOOQ's
- 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
- Unlike JDBC's
- As a
- Like
- Many databases support returning several result sets, or cursors, from single queries. An example for this is Sybase ASE's sp_help command: -
-- The correct (and verbose) way to do this with JDBC is as follows: -
- -
- As previously discussed in the chapter about
- Using generics, the resulting structure is immediately clear. -
-
- 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
- Note, that instead of letting jOOQ spawn a new thread, you can also provide jOOQ with your own
- When interacting with legacy applications, you may prefer to have jOOQ return a
- Instead of operating on a JDBC ResultSet holding an open resource from your database, you can also let jOOQ's
- The inverse of the above is possible too. Maybe, a legacy part of your application produces JDBC
- Apart from a few extra features (see the manual's section about
- Such a converter can be used in many parts of the jOOQ API. Some examples have been illustrated in the manual's section about
- Here is a some more elaborate example involving a Converter for
- jOOQ ships with a built-in default
- jOOQ also allows for generated source code to reference your own custom converters, in order to permanently replace a
- With JDBC, you have full control over your SQL statements. You can decide yourself, if you want to execute a static
- With jOOQ, this is easier. As a matter of fact, it is plain simple. With jOOQ, you can just set a flag in your
- Not all databases are equal. Some databases show improved performance if you use
- 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. -
- -
- 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
- With JDBC, you can easily execute several statements at once using the addBatch() method. Essentially, there are two modes in JDBC -
- -- In code, this looks like the following snippet: -
-- jOOQ supports executing queries in batch mode as follows: -
- -
- Most databases support sequences of some sort, to provide you with unique values to be used for primary keys and other enumerations. If you're using jOOQ's
- Instead of actually phrasing a select statement, you can also use the
- You can inline sequence references in jOOQ SQL statements. The following are examples of how to do that: -
- -
- For more info about inlining sequence references in SQL statements, please refer to the manual's section about
- Many RDBMS support the concept of "routines", usually calling them procedures and/or functions. These concepts have been around in programming languages for a while, also outside of databases. Famous languages distinguishing procedures from functions are: -
-- The general distinction between (stored) procedures and (stored) functions can be summarised like this: -
- -- In general, it can be said that the field of routines (procedures / functions) is far from being standardised in modern RDBMS even if the SQL:2008 standard specifies things quite well. Every database has its ways and JDBC only provides little abstraction over the great variety of procedures / functions implementations, especially when advanced data types such as cursors / UDT's / arrays are involved. -
-
- To simplify things a little bit, jOOQ handles both procedures and functions the same way, using a more general
- If you're using jOOQ's
- 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: -
- -
- For more details about
- Unlike procedures, functions can be inlined in SQL statements to generate
- 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
- Oracle uses the concept of a PACKAGE to group several procedures/functions into a sort of namespace. The SQL 92 standard talks about "modules", to represent this concept, even if this is rarely implemented as such. This is reflected in jOOQ by the use of Java sub-packages in the
- Apart from this, the generated source code looks exactly like the one for standalone procedures/functions. -
-
- For more details about
- Oracle UDTs can have object-oriented structures including member functions and procedures. With Oracle, you can do things like this: -
- -- These member functions and procedures can simply be mapped to Java methods: -
- -
- For more details about
- If you are using jOOQ for scripting purposes or in a slim, unlayered application server, you might be interested in using jOOQ's exporting functionality (see also the
- The above query will result in an XML document looking like the following one: -
- -
- The same result as an
- See the XSD schema definition here, for a formal definition of the XML export format:
- http://www.jooq.org/xsd/jooq-export-1.6.2.xsd
-
- The above query will result in a CSV document looking like the following one: -
- -- In addition to the standard behaviour, you can also specify a separator character, as well as a special string to represent NULL values (which cannot be represented in standard CSV): -
- -- The above query will result in a JSON document looking like the following one: -
- -- The above query will result in an HTML document looking like the following one -
- -- The above query will result in a text document looking like the following one -
- -
- A simple text representation can also be obtained by calling toString() on a Result object. See also the manual's section about
- If you are using jOOQ for scripting purposes or in a slim, unlayered application server, you might be interested in using jOOQ's importing functionality (see also exporting functionality). You can import data directly into a table from the formats described in the subsequent sections of this manual. -
-
- The below CSV data represents two author records that may have been exported previously, by jOOQ's
- With jOOQ, you can load this data using various parameters from the loader API. A simple load may look like this: -
- -- Here are various other examples: -
- -- Any of the above configuration methods can be combined to achieve the type of load you need. Please refer to the API's Javadoc to learn about more details. Errors that occur during the load are reported by the execute method's result: -
- -This is not yet supported
-- Your database application probably consists of 50% - 80% CRUD, whereas only the remaining 20% - 50% of querying is actual querying. Most often, you will operate on records of tables without using any advanced relational concepts. This is called CRUD for -
-
- 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
- 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
- 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: -
-- For simplicity, the term "primary key" will be used in the sense of such a "main unique key" in this manual. -
-
- If you're using jOOQ's
- See the manual's section about
- Storing a record will perform an
- Some remarks about storing: -
-- Deleting a record will remove it from the database. Here's how you delete records: -
- -
- Refreshing a record from the database means that jOOQ will issue a
- In order to perform a refresh, use the following Java code: -
- -
- CRUD operations can be combined with regular querying, if you select records from single database tables, as explained in the manual's section about
- Many databases support the concept of IDENTITY values, or
- If you're using jOOQ's
- DB2, Derby, HSQLDB, Ingres -
-- These SQL dialects implement the standard very neatly. -
-- H2, MySQL, Postgres, SQL Server, Sybase ASE, Sybase SQL Anywhere -
-- These SQL dialects implement identites, but the DDL syntax doesn’t follow the standard -
-
- 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
- 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. -
-
- jOOQ allows you to perform
- The above changes to jOOQ's behaviour are transparent to the API, the only thing you need to do for it to be activated is to set the Settings flag. Here is an example illustrating optimistic locking: -
- -
- If you're using jOOQ's
- 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
- As before, without the added TIMESTAMP column, optimistic locking is transparent to the API. -
- -- Instead of using TIMESTAMPs, you may also use numeric VERSION fields, containing version numbers that are incremented by jOOQ upon store() calls. -
- -
- Note, for explicit pessimistic locking, please consider the manual's section about the
- 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
- Internally, jOOQ will render all the required SQL statements and execute them as a regular
- If you're using jOOQ's
corresponds to the DAO's related generated POJO type
-// 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 findAll() throws DataAccessException;
- P findById(T id) throws DataAccessException;
- fetch(Field getType();
-}]]>
- Besides these base methods, generated DAO classes implement various useful fetch methods. An incomplete example is given here, for the BOOK table: -
- -- 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: -
- -- This is an eternal and religious debate. Pros and cons have been discussed time and again, and it still is a matter of taste, today. In this case, jOOQ clearly takes a side. jOOQ's exception strategy is simple: -
-- With jOOQ, it's simple. All of jOOQ's exceptions are "system exceptions", hence they are all unchecked. -
- -
- jOOQ uses its own
- DataAccessException is subtyped several times as follows: -
-
- The following section about
- The
- For convenience and better backwards-compatibility, consider extending
- Here is a sample implementation of an ExecuteListener, that is simply counting the number of queries per type that are being executed using jOOQ: -
- -- Now, configure jOOQ's runtime to load your listener -
- -- And log results any time with a snippet like this: -
- -- This may result in the following log output: -
- -
- Please read the
- See also the manual's sections about
- jOOQ logs all SQL queries and fetched result sets to its internal DEBUG logger, which is implemented as an
- With the above configuration, let's fetch some data with jOOQ -
- -- The above query may result in the following log output: -
- -- Essentially, jOOQ will log -
-
- If you wish to use your own logger (e.g. avoiding printing out sensitive data), you can deactivate jOOQ's logger using
- Many users may have switched from higher-level abstractions such as Hibernate to jOOQ, because of Hibernate's hard-to-manage performance, when it comes to large database schemas and complex second-level caching strategies. jOOQ is not a lightweight database abstraction framework, and it comes with its own overhead. Please be sure to consider the following points: -
-- 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. -
-
- While optional, source code generation is one of jOOQ's main assets if you wish to increase developer productivity. jOOQ's code generator takes your database schema and reverse-engineers it into a set of Java classes modelling
- The essential ideas behind source code generation are these: -
-- The following chapters will show how to configure the code generator and how to generate various artefacts. -
-- There are three binaries available with jOOQ, to be downloaded from http://www.jooq.org/download or from Maven central: -
-- You need to tell jOOQ some things about your database connection. Here's an example of how to do it for an Oracle database -
- -
- There are also lots of advanced configuration parameters, which will be treated in the
- http://www.jooq.org/xsd/jooq-codegen-2.5.0.xsd
-
- Code generation works by calling this class with the above property file as argument. -
- -- Be sure that these elements are located on the classpath: -
- -- Note that the property file must be passed as a classpath resource -
- -- Of course, you can also run code generation from your IDE. In Eclipse, set up a project like this. Note that this example uses jOOQ's log4j support by adding log4j.xml and log4j.jar to the project classpath: -
-
- - Once the project is set up correctly with all required artefacts on the classpath, you can configure an Eclipse Run Configuration for org.jooq.util.GenerationTool. -
-
- - With the XML file as an argument -
-
- - And the classpath set up correctly -
-
- - Finally, run the code generation and see your generated artefacts -
-
- - 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: -
- -- Note that when running code generation with ant's <java/> task, you may have to set fork="true": -
- -- Using the official jOOQ-codegen-maven plugin, you can integrate source code generation in your Maven build process: -
- -- Before jOOQ 2.0.4, the code generator was configured using properties files. These files are still supported for source code generation, but their syntax won't be maintained any longer. If you wish to migrate to XML, you can migrate the file using this command on the command line -
- -- Using the migrate flag, jOOQ will read the properties file and output a corresponding XML file on system out -
- -- Be sure, both jooq-{jooq-version}.jar and your generated package (see configuration) are located on your classpath. Once this is done, you can execute SQL statements with your generated classes. -
-
- In the
- The following example shows how you can override the DefaultGeneratorStrategy to render table and column names the way they are defined in the database, rather than switching them to camel case: -
- -- Within the <generator/> element, there are other configuration elements: -
- -- Check out the some of the manual's "advanced" sections to find out more about the advanced configuration parameters. -
-- Also, you can add some optional advanced configuration parameters for the generator: -
- -- For increased convenience at the use-site, jOOQ generates "global" artefacts at the code generation root location, referencing tables, routines, sequences, etc. In detail, these global artefacts include the following: -
-- When referencing global artefacts from your client application, you would typically static import them as such: -
- -
- Every table in your database will generate a
- These flags from the
- Table generation cannot be deactivated -
-
- Every table in your database will generate an
- These flags from the
- Record generation can be deactivated using the records flag -
-- Every table in your database will generate a POJO implementation that looks like this: -
- -
- These flags from the
- POJO generation can be activated using the pojos flag -
-- Every table in your database will generate an interface that looks like this: -
- -
- These flags from the
- Interfaces generation can be activated using the interfaces flag -
-
- Every table in your database will generate a
- DAO generation can be activated using the daos flag -
-
- Every sequence in your database will generate a
- Sequence generation cannot be deactivated -
-
- Every procedure or function (routine) in your database will generate a
- Procedures or functions contained in packages or UDTs are generated in a sub-package that corresponds to the package or UDT name. -
- -- Routine generation cannot be deactivated -
-
- Every UDT in your database will generate a
- Besides the
- UDT generation cannot be deactivated -
-- NOTE: This feature is deprecated in jOOQ 2.5.0 and will be removed as of jOOQ 3.0 -
-- Only MySQL and Postgres databases support true ENUM types natively. Some other RDBMS allow you to map the concept of an ENUM data type to a CHECK constraint, but those constraints can contain arbitrary SQL. With jOOQ, you can "emulate" ENUM types by declaring a table as a "master data table" in the configuration. At code-generation time, this table will be treated specially, and a Java enum type is generated from its data. -
- -- As previously discussed, you can configure master data tables as follows: -
- -- The results of this will be a Java enum that looks similar to this: -
- -- 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 -
-- The point of MasterDataTypes in jOOQ is that they behave exactly like true ENUM types. When the above LANGUAGE table is referenced by BOOK, instead of generating foreign key navigation methods and a LANGUAGE_ID Field<Integer>, a Field<TLanguage> is generated: -
- -- Which can then be used in the BookRecord directly: -
- -- You can use master data types when you're actually mapping master data to a Java enum. When the underlying table changes frequently, those updates will not be reflected by the statically generated code. Also, be aware that it will be difficult to perform actual JOIN operations on the underlying table with jOOQ, once the master data type is generated. -
-
- When using a custom type in jOOQ, you need to let jOOQ know about its associated
- The above configuration will lead to AUTHOR.DATE_OF_BIRTH being generated like this: -
- -
- This means that the bound type of <T> will be GregorianCalendar, wherever you reference DATE_OF_BIRTH. jOOQ will use your custom converter when binding variables and when fetching data from
- We've seen previously in the chapter about
- These chapters hold some information about tools to be used with jOOQ -
-- The jOOQ Console is no longer supported or shipped with jOOQ 3.2+. You may still use the jOOQ 3.1 Console with new versions of jOOQ, at your own risk. -
-- These chapters hold some general jOOQ reference information -
-- Every RDMBS out there has its own little specialties. jOOQ considers those specialties as much as possible, while trying to standardise the behaviour in jOOQ. In order to increase the quality of jOOQ, some 70 unit tests are run for syntax and variable binding verification, as well as some 180 integration tests with an overall of around 1200 queries for any of these databases: -
-- These platforms have been observed to work as well, but are not integration-tested -
-- Any of the following databases might be available in the future -
-- Any of the following databases are being observed for a potential integration -
-- This section will soon contain a feature matrix, documenting what feature is available for which database. -
-- There is always a small mismatch between SQL data types and Java data types. This is for two reasons: -
-- This chapter should document the most important notes about SQL, JDBC and jOOQ data types. -
-
- jOOQ aims for hiding all JDBC details from jOOQ client API. Specifically,
- Clob and Blob are resources (but not fetch() methods. fetchLazy() and fetchStream() might be candidates where Clob and Blob types could make sense as the underlying
- ByteArrayInputStream and ByteArrayOutputStream on the other hand are two different types which cannot be represented as a single Field<T> type. If either would be chosen as the <T> type, we'd get read-only or write-only fields. So for full lazy streaming support, we'd need another 2-way wrapper type, similar to Clob and Blob.
-
- In many cases, streaming binary data isn't really necessary as thebyte[] can be easily kept in memory (and it is done so for further processing anyway, e.g. when working with images), so the extra work might not really be needed. This is particularly true in Oracle, where BLOBs are the only binary types in the absences of a formal (VAR)BINARY type, and CLOBs start at 4000 bytes.
-
- Hence, jOOQ currently doesn't explicitly support JDBC BLOB and CLOB data types. If you use any of these data types in your database, jOOQ will map them to byte[] and String instead. In simple cases (small data), this simplification is sufficient. In more sophisticated cases, you may have to bypass jOOQ, in order to deal with these data types and their respective resources. -
-
- Some databases explicitly support unsigned integer data types. In most normal JDBC-based applications, they would just be mapped to their signed counterparts letting bit-wise shifting and tweaking to the user. jOOQ ships with a set of unsigned
- Each of these wrapper types extends
- jOOQ fills a gap opened by JDBC, which neglects an important SQL data type as defined by the SQL standards: INTERVAL types. SQL knows two different types of intervals: -
-
- 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
- In addition to the
- XML data types are currently not supported -
-- Geospacial data types are currently not supported -
-- Some databases support cursors returned from stored procedures. They are mapped to the following jOOQ data type: -
- -
- In fact, such a cursor will be fetched immediately by jOOQ and wrapped in an
- The SQL standard specifies ARRAY data types, that can be mapped to Java arrays as such: -
- -- The above array type is supported by these SQL dialects: -
-
- Oracle has strongly-typed arrays and table types (as opposed to the previously seen anonymously typed arrays). These arrays are wrapped by
- This chapter will soon contain an overview over jOOQ's API using a pseudo BNF notation. -
-- jOOQ lives in a very challenging ecosystem. The Java to SQL interface is still one of the most important system interfaces. Yet there are still a lot of open questions, best practices and no "true" standard has been established. This situation gave way to a lot of tools, APIs, utilities which essentially tackle the same problem domain as jOOQ. jOOQ has gotten great inspiration from pre-existing tools and this section should give them some credit. Here is a list of inspirational tools in alphabetical order: -
-This manual is divided into six main sections:
+ ++ This section will get you started with jOOQ quickly. It contains + simple explanations about what jOOQ is, what jOOQ isn't and how + to set it up for the first time +
++ This section explains all about the jOOQ syntax used for building + queries through the query DSL and the query model API. It explains + the central factories, the supported SQL statements and various other syntax elements +
++ This section explains how to configure and use the built-in source code + generator +
++ This section will get you through the specifics of what can be done + with jOOQ at runtime, in order to execute queries, perform CRUD + operations, import and export data, and hook into the jOOQ execution + lifecycle for debugging +
++ This section is dedicated to tools that ship with jOOQ, such as the + jOOQ's JDBC mocking feature +
++ This section is a reference for elements in this manual +
++ Java and SQL have come a long way. SQL is an "old", yet established and well-understood technology. Java is a legacy too, although its platform JVM allows for many new and contemporary languages built on top of it. Yet, after all these years, libraries dealing with the interface between SQL and Java have come and gone, leaving JPA to be a standard that is accepted only with doubts, short of any surviving options. +
++ So far, there had been only few database abstraction frameworks or libraries, that truly respected SQL as a first class citizen among languages. Most frameworks, including the industry standards JPA, EJB, Hibernate, JDO, Criteria Query, and many others try to hide SQL itself, minimising its scope to things called JPQL, HQL, JDOQL and various other inferior query languages +
++ jOOQ has come to fill this gap. +
+ ++ Other platforms incorporate ideas such as LINQ (with LINQ-to-SQL), or Scala's SLICK, or also Java's QueryDSL to better integrate querying as a concept into their respective language. By querying, they understand querying of arbitrary targets, such as SQL, XML, Collections and other heterogeneous data stores. jOOQ claims that this is going the wrong way too. +
++ In more advanced querying use-cases (more than simple CRUD and the occasional JOIN), people will want to profit from the expressivity of SQL. Due to the relational nature of SQL, this is quite different from what object-oriented and partially functional languages such as C#, Scala, or Java can offer. +
++ It is very hard to formally express and validate joins and the ad-hoc table expression types they create. It gets even harder when you want support for more advanced table expressions, such as pivot tables, unnested cursors, or just arbitrary projections from derived tables. With a very strong object-oriented typing model, these features will probably stay out of scope. +
++ In essence, the decision of creating an API that looks like SQL or one that looks like C#, Scala, Java is a definite decision in favour of one or the other platform. While it will be easier to evolve SLICK in similar ways as LINQ (or QueryDSL in the Java world), SQL feature scope that clearly communicates its underlying intent will be very hard to add, later on (e.g. how would you model Oracle's partitioned outer join syntax? How would you model ANSI/ISO SQL:1999 grouping sets? How can you support scalar subquery caching? etc...). +
++ jOOQ has come to fill this gap. +
+ ++ So why not just use SQL? +
++ SQL can be written as plain text and passed through the JDBC API. Over the years, people have become wary of this approach for many reasons: +
++ For these many reasons, other frameworks have tried to abstract JDBC away in the past in one way or another. Unfortunately, many have completely abstracted SQL away as well +
++ jOOQ has come to fill this gap. +
+ ++ 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! +
++ This section lists the various licenses that apply to different versions of jOOQ. Prior to version 3.2, jOOQ was shipped for free under the terms of the Apache Software License 2.0. With jOOQ 3.2, jOOQ became dual-licensed: Apache Software License 2.0 (for use with Open Source databases) and commercial (for use with commercial databases). +
+ ++ This manual itself (as well as the www.jooq.org public website) is licensed to you under the terms of the CC BY-SA 4.0 license. +
+ ++ Please contact legal@datageekery.com, should you have any questions regarding licensing. +
++ Other names may be trademarks of their respective owners. +
+ ++ Throughout the manual, the above trademarks are referenced without a formal ® (R) or ™ (TM) symbol. It is believed that referencing third-party trademarks in this manual or on the jOOQ website constitutes "fair use". Please contact us if you think that your trademark(s) are not properly attributed. +
+ ++ The following are authors and contributors of jOOQ or parts of jOOQ in alphabetical order: +
+
+ See the following website for details about contributing to jOOQ:
+ http://www.jooq.org/legal/contributions
+
+ These chapters contain a quick overview of how to get started with this manual and with jOOQ. While the subsequent chapters contain a lot of reference information, this chapter here just wraps up the essentials. +
++ This section helps you correctly interpret this manual in the context of jOOQ. +
+ ++ The following are code blocks: +
+ ++ 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. +
+ +
+ 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:
+
+ jOOQ records (and many other API elements) have a degree N between 1 and {max-row-degree}. The variable degree of an API element is denoted as [N], e.g. Row[N] or Record[N]. The term "degree" is preferred over arity, as "degree" is the term used in the SQL standard, whereas "arity" is used more often in mathematics and relational theory. +
+ +
+ jOOQ allows to override runtime behaviour using
+ jOOQ query examples run against the sample database. See the manual's section about
+ For the examples in this manual, the same database will always be referred to. It essentially consists of these entities created using the Oracle dialect +
++ More entities, types (e.g. UDT's, ARRAY types, ENUM types, etc), stored procedures and packages are introduced for specific examples +
++ In addition to the above, you may assume the following sample data: +
+ ++ jOOQ has originally been created as a library for complete abstraction of JDBC and all database interaction. Various best practices that are frequently encountered in pre-existing software products are applied to this library. This includes: +
+
+ Effectively, jOOQ was originally designed to replace any other database abstraction framework short of the ones handling connection pooling (and more sophisticated
+ ... 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: +
++ The following sections explain about various use cases for using jOOQ in your application. +
+
+ 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
+ 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".
+ If you wish to use jOOQ only as a SQL builder, the following sections of the manual will be of interest to you: +
+
+ In addition to using jOOQ as a
+ 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. +
++ If you wish to use jOOQ only as a SQL builder with code generation, the following sections of the manual will be of interest to you: +
++ 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: +
+ ++ By having jOOQ execute your SQL, the jOOQ query DSL becomes truly embedded SQL. +
+ ++ jOOQ doesn't stop here, though! You can execute any SQL with jOOQ. In other words, you can use any other SQL building tool and run the SQL statements with jOOQ. An example is given here: +
+ ++ If you wish to use jOOQ as a SQL executor with (or without) code generation, the following sections of the manual will be of interest to you: +
++ This is probably the most complete use-case for jOOQ: Use all of jOOQ's features. Apart from jOOQ's fluent API for query construction, jOOQ can also help you execute everyday CRUD operations. An example is given here: +
+ ++ If you wish to use all of jOOQ's features, the following sections of the manual will be of interest to you (including all sub-sections): +
+
+ jOOQ isn't just a library that helps you
+ If you're a power user of your favourite, feature-rich database, jOOQ will help you access all of your database's vendor-specific features, such as OLAP features, stored procedures, user-defined types, vendor-specific SQL, functions, etc. Examples are given throughout this manual. +
++ Don't have time to read the full manual? Here are a couple of tutorials that will get you into the most essential parts of jOOQ as quick as possible. +
++ This manual section is intended for new users, to help them get a running application with jOOQ, quickly. +
+
+ 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: +
+ ++ 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
+ For this example, we'll be using MySQL. If you haven't already downloaded MySQL Connector/J, download it here:
+ http://dev.mysql.com/downloads/connector/j/
+
+ If you don't have a MySQL instance up and running yet, get XAMPP now! XAMPP is a simple installation bundle for Apache, MySQL, PHP and Perl +
++ 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: +
+ +
+ In this step, we're going to use jOOQ's command line tools to generate classes that map to the Author table we just created. More detailed information about how to set up the jOOQ code generator can be found here:
+
+ 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: +
+ ++ Replace the username with whatever user has the appropriate privileges to query the database meta data. You'll also want to look at the other values and replace as necessary. Here are the two interesting properties: +
+
+ generator.target.package - set this to the parent package you want to create for the generated classes. The setting of test.generated will cause the test.generated.Author and test.generated.AuthorRecord to be created
+
+ 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: +
+ ++ ... or type this on a UNIX / Linux / Mac system (colons instead of semi-colons): +
+ +
+ 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: +
+ ++ Let's just write a vanilla main class in the project containing the generated classes: +
+ ++ This is pretty standard code for establishing a MySQL connection. +
++ Let's add a simple query constructed with jOOQ's query DSL: +
+ +
+ First get an instance of DSLContext so we can write a simple SELECT query. We pass an instance of the MySQL connection to DSL. Note that the DSLContext doesn't close the connection. We'll have to do that ourselves.
+
+ We then use jOOQ's query DSL to return an instance of Result. We'll be using this result in the next step. +
++ After the line where we retrieve the results, let's iterate over the results and print out the data: +
+ ++ The full program should now look like this: +
+ +
+ jOOQ has grown to be a comprehensive SQL library. For more information, please consider the documentation:
+ http://www.jooq.org/learn
+
+ ... explore the Javadoc:
+ http://www.jooq.org/javadoc/latest/
+
+ ... or join the news group:
+ https://groups.google.com/forum/#!forum/jooq-user
+
+ This tutorial is the courtesy of Ikai Lan. See the original source here:
+ http://ikaisays.com/2011/11/01/getting-started-with-jooq-a-tutorial/
+
Feel free to contribute a tutorial!
++ jOOQ and Spring are easy to integrate. In this example, we shall integrate: +
+Before you copy the manual examples, consider also these further resources:
++ For this example, we'll create the following Maven dependencies +
+ ++ 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. +
+ ++ The above dependencies are configured together using a Spring Beans configuration: +
+ ++ With the above configuration, you should be ready to run queries pretty quickly. For instance, in an integration-test, you could use Spring to run JUnit: +
+ ++ The following example shows how you can use Spring's TransactionManager to explicitly handle transactions: +
+ +
+ Spring-TX has very powerful means to handle transactions declaratively, using the @Transactional annotation. The BookService that we had defined in the previous Spring configuration can be seen here:
+
+ And here is how we interact with it: +
+
+ jOOQ has its own programmatic transaction API that can be used with Spring transactions by implementing the jOOQ
+ You can try the above example yourself by downloading it from GitHub. +
+
+
When 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.
+
+ 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: +
+ ++ 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: +
+ ++ The following properties are defined in our pom.xml, to be able to reuse them between plugin configurations: +
+ ++ 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: +
+ ++ After the dependencies, let's simply add the Flyway and jOOQ Maven plugins like so. The Flyway plugin: +
+ + +
+ The above Flyway Maven plugin configuration will read and execute all database migration scripts from src/main/resources/db/migration prior to compiling Java source code. While the official Flyway documentation suggests that migrations be done in the compile phase, the jOOQ code generator relies on such migrations having been done prior to code generation.
+
+ After the Flyway plugin, we'll add the jOOQ Maven Plugin. For more details, please refer to the
+ This configuration will now read the FLYWAY_TEST schema and reverse-engineer it into the target/generated-sources/jooq-h2 directory, and within that, into the org.jooq.example.flyway.db.h2 package.
+
+ Now, when we start developing our database. For that, we'll create database increment scripts, which we put into the src/main/resources/db/migration directory, as previously configured for the Flyway plugin. We'll add these files:
+
+ These three scripts model our schema versions 1-3 (note the capital V!). Here are the scripts' contents +
+ ++ The above three scripts are picked up by Flyway and executed in the order of the versions. This can be seen very simply by executing: +
+ ++ And then observing the log output from Flyway... +
+ ++ ... and from jOOQ on the console: +
+ ++ Note that all of the previous steps are executed automatically, every time someone adds new migration scripts to the Maven module. For instance, a team member might have committed a new migration script, you check it out, rebuild and get the latest jOOQ-generated sources for your own development or integration-test database. +
++ Now, that these steps are done, you can proceed writing your database queries. Imagine the following test case +
+ ++ The power of this approach becomes clear once you start performing database modifications this way. Let's assume that the French guy on our team prefers to have things his way: +
+ + ++ They check it in, you check out the new database migration script, run +
+ ++ And then observing the log output: +
+ ++ So far so good, but later on: +
+ ++ When we go back to our Java integration test, we can immediately see that the TITLE column is still being referenced, but it no longer exists: +
+ ++ This tutorial shows very easily how you can build a rock-solid development process using Flyway and jOOQ to prevent SQL-related errors very early in your development lifecycle - immediately at compile time, rather than in production! +
+ ++ Please, visit the Flyway website for more information about Flyway. +
+ + + ++ 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: +
++ For the example, we'll use a PostgreSQL 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:
+
+ To make things a bit more interesting (and secure), we'll also push license key generation into the database, by generating it from a stored function as such: +
+ ++ 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. +
+ +
+ We're going to be setting up the
+ With the above setup, we're now pretty ready to start developing our license service as a JAX-RS service. +
+ +
+ Once we've run the
/license/verify checks if a given licensee has access to version using a license.
+ *
+ * @param request The servlet request from the JAX-RS context.
+ * @param mail The input email address of the licensee.
+ * @param license The license used by the licensee.
+ * @param version The product version being accessed.
+ */
+ @GET
+ @Produces("text/plain")
+ @Path("/verify")
+ public String verify(
+ final @Context HttpServletRequest request,
+ final @QueryParam("mail") String mail,
+ final @QueryParam("license") String license,
+ final @QueryParam("version") String version
+ ) {
+ return run(new CtxRunnable() {
+ @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)
+ .set(LOG_VERIFY.LICENSE, license)
+ .set(LOG_VERIFY.LICENSEE, mail)
+ .set(LOG_VERIFY.REQUEST_IP, request.getRemoteAddr())
+ .set(LOG_VERIFY.MATCH, field(
+ selectCount()
+ .from(LICENSE)
+ .where(LICENSE.LICENSEE.eq(mail))
+ .and(LICENSE.LICENSE_.eq(license))
+ .and(val(v).likeRegex(LICENSE.VERSION))
+ .asField().gt(0)))
+ .set(LOG_VERIFY.VERSION, v)
+ .returning(LOG_VERIFY.MATCH)
+ .fetchOne()
+ .getValue(LOG_VERIFY.MATCH, String.class);
+ }
+ });
+ }
+
+ // [...]
+}]]>
+ The INSERT INTO LOG_VERIFY query is actually rather interesting. In plain SQL, it would look like this:
+
+ Apart from the foregoing, the LicenseService also contains a couple of simple utilities:
+
+ All we need now is to configure Spring... +
+ ++ ... and Jetty ... +
+ ++ ... and we're done! We can now run the server with the following command: +
+ ++ Or if you need a custom port: +
+ ++ You can now use the license server at the following URLs +
+ ++ Let's verify what happened, in the database: +
+ +
+ 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
+
Feel free to contribute a tutorial!
+
+ Java 8 has introduced a great set of enhancements, among which lambda expressions and the new
+ jOOQ's
+ The above example shows how jOOQ's
+ jOOQ's Result containing INFORMATION_SCHEMA meta data to produce DDL statements:
+
+ 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: +
+ + +
+ One of the major improvements of Java 8 is the introduction of JavaFX into the JavaSE. With jOOQ and XYChart.Series or other, related objects:
+
+ As we've seen in the previous
+ In this example, we're going to use Open Data from the world bank to show a comparison of countries GDP and debts: +
+ +
+ Once this data is set up (e.g. in an H2 or PostgreSQL database), we'll run jOOQ's
+ The above example uses basic SQL-92 syntax where the countries are ordered using aggregate information from a
+ When executed, we'll get nice-looking bar charts like these:
+
+
+
+ The complete example can be downloaded and run from GitHub:
+
+ https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-javafx-example
+
+ 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. +
++ As any other library, jOOQ can be easily used in Scala, taking advantage of the many Scala language features such as for example: +
++ But jOOQ also leverages other useful Scala features, such as +
++ 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: +
+ +
+ For more details about jOOQ's Scala integration, please refer to the manual's section about
+ As any other library, jOOQ can be easily used in Groovy, taking advantage of the many Groovy language features such as for example: +
++ A short example jOOQ application in Groovy might look like this: +
+ +
+ Note that while Groovy supports some means of operator overloading, we think that these means should be avoided in a jOOQ integration. For instance, a + b in Groovy maps to a formal a.plus(b) method invocation, and jOOQ provides the required synonyms in its API to help you write such expressions. Nonetheless, Groovy only offers little typesafety, and as such, operator overloading can lead to many runtime issues.
+
+ Another caveat of Groovy 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.
+
+ As any other library, jOOQ can be easily used in Kotlin, taking advantage of the many Kotlin language features such as for example: +
++ A short example jOOQ application in Kotlin might look like this: +
+ +
+ 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:
+
+ 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 users often get excited about jOOQ's intuitive API and would then wish for NoSQL support. +
++ There are a variety of NoSQL databases that implement some sort of proprietary query language. Some of these query languages even look like SQL. Examples are JCR-SQL2, CQL (Cassandra Query Language), Cypher (Neo4j's Query Language), SOQL (Salesforce Query Language) and many more. +
++ Mapping the jOOQ API onto these alternative query languages would be a very poor fit and a leaky abstraction. We believe in the power and expressivity of the SQL standard and its various dialects. Databases that extend this standard too much, or implement it not thoroughly enough are often not suitable targets for jOOQ. It would be better to build a new, dedicated API for just that one particular query language. +
+
+ jOOQ is about SQL, and about SQL alone. Read more about our visions in the
+ Dependencies are a big hassle in modern software. Many libraries depend on other, non-JDK library parts that come in different, incompatible versions, potentially causing trouble in your runtime environment. jOOQ has no external dependencies on any third-party libraries. +
++ However, the above rule has some exceptions: +
++ In order to build jOOQ (Open Source Edition) yourself, please download the sources from https://github.com/jOOQ/jOOQ and use Maven to build jOOQ, preferably in Eclipse. The jOOQ Open Source Edition requires Java 8+ to compile and run. The commercial jOOQ Editions require Java 8+ or Java 6+ to compile and run, depending on the distribution. +
++ Some useful hints to build jOOQ yourself: +
+mvn eclipse:eclipsejooq-parent artefact by using any of these commands:
+ mvn clean package${project.build.directory}mvn clean install~/.m2)mvn clean {goal} -Dmaven.test.skip=true+ jOOQ follows the rules of semantic versioning according to http://semver.org quite strictly. Those rules impose a versioning scheme [X].[Y].[Z] that can be summarised as follows: +
++ 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 +
+
+ However, there are some elements of API evolution that would be considered backwards-incompatible in other APIs, but not in jOOQ. As discussed later on in the section about
+ It becomes obvious that it would be impossible to add new language elements (e.g. new
+ jOOQ's DSL interfaces should not be implemented by client code! Extend only those extension points that are explicitly documented as "extendable" (e.g.
+ 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. +
++ SQL is a declarative language that is hard to integrate into procedural, object-oriented, functional or any other type of programming languages. jOOQ's philosophy is to give SQL the credit it deserves and integrate SQL itself as an "internal domain specific language" directly into Java. +
+
+ With this philosophy in mind, SQL building is the main feature of jOOQ. All other features (such as
+ This section explains all about the various syntax elements involved with jOOQ's SQL building capabilities. For a complete overview of all syntax elements, please refer to the manual's sections about
+ jOOQ exposes a lot of interfaces and hides most implementation facts from client code. The reasons for this are: +
+
+ The
+ With jOOQ 2.0, static factory methods have been introduced in order to make client code look more like SQL. Ideally, when working with jOOQ, you will simply static import all methods from the DSL class: +
+ ++ Note, that when working with Eclipse, you could also add the DSL to your favourites. This will allow to access functions even more fluently: +
++ There are a couple of subclasses for the general query DSL. Each SQL dialect has its own dialect-specific DSL. For instance, if you're only using the MySQL dialect, you can choose to reference the MySQLDSL instead of the standard DSL: +
++ The advantage of referencing a dialect-specific DSL lies in the fact that you have access to more proprietary RDMBS functionality. This may include: +
+
+ DSLContext references a
+ The DSLContext object can be created fluently from the
+ If you do not have a reference to a pre-existing Configuration object (e.g. created from DSL.using() methods will create one for you.
+
+ A Configuration can be supplied with these objects: +
+
+ Wrapping a Configuration object, a DSLContext can construct
+ Note that you do not need to keep a reference to a DSLContext. You may as well inline your local variable, and fluently execute a SQL statement as such: +
+ +
+ While jOOQ tries to represent the SQL standard as much as possible, many features are vendor-specific to a given database and to its "SQL dialect". jOOQ models this using the
+ The SQL dialect is one of the main attributes of a
+ Some parts of the jOOQ API are officially supported only by a given subset of the supported SQL dialects. For instance, the
+ jOOQ API methods which are not annotated with the
+ The aforementioned Support annotation does not only designate, which databases natively support a feature. It also indicates that a feature is emulated by jOOQ for some databases lacking this feature. An example of this is the
+ Nevertheless, the IS DISTINCT FROM predicate is supported by jOOQ in all dialects, as its semantics can be expressed with an equivalent
+ 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 +
++ jOOQ has a historic affinity to Oracle's SQL extensions. If something is supported in Oracle SQL, it has a high probability of making it into the jOOQ API +
+
+ In jOOQ 3.1, the notion of a SQLDialect.family() was introduced, in order to group several similar
+ 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 ROW_NUMBER() OVER() (SQL Server 2008).
+
+ While you can use jOOQ for
+ Note, in this case, jOOQ will internally use a
+ If you're in a J2EE or Spring context, however, you may wish to use a
+ Note, in this case, jOOQ will internally use a
+ 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: +
+ +
+ In advanced use cases of integrating your application with jOOQ, you may want to put custom data into your
+ Here is an example of how to use the custom data API. Let's assume that you have written an INSERT statements, when a given flag is set to true:
+
+ See the manual's section about ExecuteListener.
+
+ Now, the above listener can be added to your Configuration, in order for the listener to work:
+
+ Using the data() methods, you can store and retrieve custom data in your Configurations.
+
+ ExecuteListeners are a useful tool to...
+
+ ExecuteListeners are hooked into your
+ See the manual's section about
+ The jOOQ Configuration allows for some optional configuration elements to be used by advanced users. The
DSL.using()). This will override default settings below+ The most specific settings for a given context will apply. +
+ +
+ If you wish to configure your settings through XML, but explicitly load them for a given Configuration, you can do so as well, using JAXB:
+
+ For example, if you want to indicate to jOOQ, that it should inline all bind variables, and execute static
+ Please refer to the jOOQ runtime configuration XSD for more details:
+ http://www.jooq.org/xsd/jooq-runtime-{runtime-xsd-version}.xsd
+
+ By default, jOOQ fully qualifies all objects with their catalog and schema names, if such qualification is made available by the
+ While the jOOQ code is also implicitly fully qualified (renderCatalog and renderSchema settings are used for this.
+
+ Programmatic configuration +
+ ++ XML configuration +
+ ++ By turning off the rendering of full qualification as can be seen above, it will be possible to use code generated from one schema on an entirely different schema of the same structure, e.g. for multitenancy purposes. +
+ +
+ More sophisticated multitenancy approaches are available through the
+ 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: +
+
+ When a user from My Book World logs in, you want them to access the MY_BOOK_WORLD schema using classes generated from DEV. This can be achieved with the
+ Programmatic configuration +
+ ++ XML configuration +
+ ++ The query executed with a Configuration equipped with the above mapping will in fact produce this SQL statement: +
+ +
+ This works because AUTHOR was generated from the DEV schema, which is mapped to the MY_BOOK_WORLD schema by the above settings.
+
+ Not only schemata can be mapped, but also tables. If you are not the owner of the database your application connects to, you might need to install your schema with some sort of prefix to every table. In our examples, this might mean that you will have to map DEV.AUTHOR to something MY_BOOK_WORLD.MY_APP__AUTHOR, where MY_APP__ is a prefix applied to all of your tables. This can be achieved by creating the following mapping: +
+ ++ Programmatic configuration +
+ ++ XML configuration +
+ ++ The query executed with a Configuration equipped with the above mapping will in fact produce this SQL statement: +
+ ++ 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! +
+ ++ 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: +
+ ++ Programmatic configuration +
+ ++ XML configuration +
+ +
+ The only difference to the constant version is that the input field is replaced by the inputExpression field of type output field is a pattern replacement, not a constant replacement.
+
+ Note that the manual's section about
+ By default, jOOQ will always generate quoted names for all identifiers (even if this manual omits this for readability). For instance: +
+ ++ Quoting has the following effect on identifiers in most (but not all) databases: +
+ +"FROM" is usually possible only when quoted."FIRST NAME" can be achieved only with quoting."name" and "NAME" are different identifiers, whereas name and NAME are not. Please consider your database manual to learn what the proper default case and default case sensitivity is.
+ The renderNameStyle setting allows for overriding the name of all identifiers in jOOQ to a consistent style. Possible options are:
+
QUOTED (the default): This will generate all names in their proper case with quotes around them.AS_IS: This will generate all names in their proper case without quotes.LOWER: This will transform all names to lower case.UPPER: This will transform all names to upper case.+ Programmatic configuration +
+ ++ XML configuration +
+ ++ In all SQL dialects, keywords are case insensitive, and this is also the default in jOOQ, which mostly generates lower-case keywords. +
+ +
+ Users may wish to adapt this and they have these options for the renderKeywordStyle setting:
+
AS_IS (the default): Generate keywords as they are defined in the codebase (mostly lower case).LOWER: Generate keywords in lower case.UPPER: Generate keywords in upper case.+ Programmatic configuration +
+ ++ XML configuration +
+ +
+ Bind values or bind parameters come in different flavours in different SQL databases. JDBC standardises on their syntax by allowing only ? (question mark) characters as placeholders for bind variables. Thus, jOOQ, by default, generates ? placeholders for JDBC consumptions.
+
+ Users who wish to use jOOQ with a different backend than JDBC can specify that all jOOQ ?. These are the current options:
+
INDEXED (the default): Generates indexed parameter placeholders using ?.NAMED: Generates named parameter placeholders, such as :param for parameters that are named explicitly or :1 for unnamed, indexed parameters.NAMED_OR_INLINED: Generates named parameter placeholders for parameters that are named explicitly and inlines all unnamed parameters.INLINED: Inlines all parameters.+ An example: +
+ ++ Programmatic configuration +
+ ++ XML configuration +
+ +
+ The following setting
+ JDBC knows two types of statements: +
+ +
+ The statementType setting allows for overriding the default of using prepared statements internally. There are two possible options for this setting:
+
PREPARED_STATEMENT (the default): Use prepared statements.STATIC_STATEMENT: Use static statements. This enforces the paramType == INLINED. See + Programmatic configuration +
+ ++ XML configuration +
+ +
+ The executeLogging setting turns off the default
+ Programmatic configuration +
+ ++ XML configuration +
+ +
+ There are two settings governing the behaviour of the jOOQ
executeWithOptimisticLocking: This allows for turning off the feature entirely.executeWithOptimisticLockingExcludeUnversioned: This allows for turning off the feature for + Programmatic configuration +
+ ++ XML configuration +
+ +
+ For more details, please refer to the
+ By default, all records fetched through jOOQ are "attached" to the
+ In some cases (e.g. when serialising records), it may be desirable not to attach the Configuration that created a record to the record. This can be achieved with the attachRecords setting:
+
+ Programmatic configuration +
+ ++ XML configuration +
+ ++ In most database design guidelines, primary key values are expected to never change - an assumption that is essential to a normalised database. +
+ +
+ As always, there are exceptions to these rules, and users may wish to allow for updatable primary key values in the
+ The above store call depends on the value of the updatablePrimaryKeys flag:
+
false (the default): Since immutability of primary keys is assumed, the store call will create a new record (a copy) with the new primary key value.true: Since mutablity of primary keys is allowed, the store call will change the primary key value from 1 to 2.+ Programmatic configuration +
+ ++ XML configuration +
+ +
+ All operations of the Configuration by default for improved mapping and reflection speed. Users who prefer to override this cache, or work with
+ Programmatic configuration +
+ ++ XML configuration +
+ +
+ Apart from JDBC exceptions, there is also the possibility to handle
+ Users who do not wish to get these notifications (e.g. for performance reasons), may turn off fetching of warnings through the fetchWarnings setting:
+
+ Programmatic configuration +
+ ++ XML configuration +
+ +
+ When using the
+ The identity value is not the only value that is generated by default. Specifically, there may be triggers that are used for auditing or other reasons, which generate LAST_UPDATE or LAST_UPDATE_BY values in a record. Users who wish to also automatically fetch these values after all store(), insert(), or update() calls may do so by specifying the returnAllOnUpdatableRecord setting. This setting depends on the availability of UPDATE .. RETURNING, and DELETE .. RETURNING statements, which are not available from all databases.
+
+ Programmatic configuration +
+ ++ XML configuration +
+ +
+ The @Table and @Column annotations). Looking up these annotations costs a slight extra overhead (mostly taken care of through mapJPAAnnotations setting:
+
+ Programmatic configuration +
+ ++ XML configuration +
+ +
+ JDBC statements feature a couple of flags that influence the execution of such a statement. Each of these flags can be configured through jOOQ's
queryTimeout: Corresponds to maxRows: Corresponds to fetchSize: Corresponds to + All of these flags are JDBC-only features with no direct effect on jOOQ. jOOQ only passes them through to the underlying statement. +
+ ++ Programmatic configuration +
+ ++ XML configuration +
+ ++ Databases that feature a cursor cache / statement cache (e.g. Oracle, SQL Server, DB2, etc.) are highly optimised for prepared statement re-use. When a client sends a prepared statement to the server, the server will go to the cache and look up whether there already exists a previously calculated execution plan for the statement (i.e. the SQL string). This is called a "soft-parse" (in Oracle). If not, the execution plan is calculated on the fly. This is called a "hard-parse" (in Oracle). +
+ +
+ Preventing hard-parses is extremely important in high throughput OLTP systems where queries are usually not very complex but are run millions of times in a short amount of time. Using bind variables, this is usually not a problem, with the exception of the
+ This problem may not be obvious to Java / jOOQ developers, as they are always produced from the same jOOQ statement: +
+ +
+ Depending on the possible sizes of the collection, it may be worth exploring using arrays or temporary tables as a workaround, or to reuse the original query that produced the set of IDs in the first place (through a semi-join). But sometimes, this is not possible. In this case, users can opt in to a third workaround: enabling the inListPadding setting. If enabled, jOOQ will "pad" the IN list to a length that is a power of two. So, the original queries would look like this instead:
+
+ This technique will drastically reduce the number of possible SQL strings without impairing too much the usual cases where the IN list is small. When padding, the last bind variable will simply be repeated many times.
+
+ Usually, there is a better way - use this as a last resort! +
+ ++ Programmatic configuration +
+ ++ XML configuration +
+ ++ Some databases (mainly MySQL and MariaDB) unfortunately chose to go an alternative, non-SQL-standard route when escaping string literals. Here's an example of how to escape a string containing apostrophes in different dialects: +
+ +
+ As most databases don't support backslash escaping (and MySQL also allows for turning it off!), jOOQ by default also doesn't support it when
+ This feature is turned on by default and for historic reasons for MySQL and MariaDB. +
+ +DEFAULT (the - surprise! - default): Turns the feature ON for MySQL and MariaDB and OFF for all other dialectsON: Turn the feature on.OFF: Turn the feature off.+ Programmatic configuration +
+ ++ XML configuration +
+ ++ This setting is useful mostly for the Oracle database, which implements a feature called scalar subquery caching, which is a good tool to avoid the expensive PL/SQL-to-SQL context switch when predicates make use of stored function calls. +
+ ++ With this setting in place, all stored function calls embedded in SQL statements will be wrapped in a scalar subquery: +
+ +
+ If our table contains thousands of books, but only a dozen of LANGUAGE_ID values, then with scalar subquery caching, we can avoid most of the function calls and cache the result per LANGUAGE_ID.
+
+ Programmatic configuration +
+ ++ XML configuration +
+ +
+ jOOQ currently supports 5 types of SQL statements. All of these statements are constructed from a DSLContext instance with an optional
+ jOOQ ships with its own DSL (or Domain Specific Language) that emulates SQL in Java. This means, that you can write SQL statements almost as if Java natively supported it, just like .NET's C# does with LINQ to SQL. +
++ Here is an example to illustrate what that means: +
+ +
+ We'll see how the aliasing works later in the section about
+ Many other frameworks have similar APIs with similar feature sets. Yet, what makes jOOQ special is its informal
+ Unlike other, simpler frameworks that use "fluent APIs" or "method chaining", jOOQ's BNF-based interface hierarchy will not allow bad query syntax. The following will not compile, for instance: +
+
+ 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
+ This query is equivalent to the one shown before using the DSL syntax. In fact, internally, the DSL API constructs precisely this SelectQuery object. Note, that you can always access the SelectQuery object to switch between DSL and model APIs: +
+ +
+ Note, that for historic reasons, the DSL API mixes mutable and immutable behaviour with respect to the internal representation of the
+ On the other hand, beware that you can always extract and modify QueryPart.
+
+ The SQL:1999 standard specifies the WITH clause to be an optional clause for the
+ When using common table expressions with jOOQ, there are essentially two approaches: +
+
+ The following example makes use of WITH clause or a FROM clause of a
+ The above expression can be assigned to a variable in Java and then be used to create a full
+ Note that the
+ If you're just operating on
+ The various SQL dialects do not agree on the use of RECURSIVE when writing recursive common table expressions. When using jOOQ, always use the RECURSIVE keyword, if needed.
+
+ When you don't just perform
+ Details about the various clauses of this query will be provided in subsequent sections. +
+ +
+ A very similar, but limited API is available, if you want to select from single tables in order to retrieve SELECT statement with the DSL or DSLContext types:
+
+ As you can see, there is no way to further restrict/project the selected fields. This just selects all known TableFields in the supplied Table, and it also binds <R extends Record> to your Table's associated Record. An example of such a Query would then be: +
++ The "reduced" SELECT API is limited in the way that it skips DSL access to any of these clauses: +
+
+ In most parts of this manual, it is assumed that you do not use the "reduced" SELECT API. For more information about the simple SELECT API, see the manual's section about
+ The SELECT clause lets you project your own record types, referencing table fields, functions, arithmetic expressions, etc. The DSL type provides several methods for expressing a SELECT clause: +
+ ++ Some commonly used projections can be easily created using convenience methods: +
+ +
+ See more details about functions and expressions in the manual's section about
+ The DISTINCT keyword can be included in the method name, constructing a SELECT clause +
+ ++ jOOQ does not explicitly support the asterisk operator in projections. However, you can omit the projection as in these examples: +
+ +
+ Since jOOQ 3.0, SELECT (and SELECT DISTINCT) API in both DSL and DSLContext. An extract from the DSL type:
+
+ Since the generic R type is bound to some SELECT statement can be assigned typesafely:
+
+ For more information about typesafe record types with degree up to {max-row-degree}, see the manual's section about
+ The SQL FROM clause allows for specifying any number of
+ Read more about aliasing in the manual's section about
+ Apart from simple tables, you can pass any arbitrary
+ Note, in order to access the DbmsXplan package, you can use the
+ In many SQL dialects, FROM is a mandatory clause, in some it isn't. jOOQ allows you to omit the FROM clause, returning just one record. An example: +
+ +
+ Read more about dual or dummy tables in the manual's section about
+ jOOQ supports many different types of standard and non-standard SQL JOIN operations: +
++ Besides, jOOQ also supports +
+ +
+ All of these JOIN methods can be called on
+ The two syntaxes will produce the same SQL statement. However, calling "join" on
+ Surprisingly, the SQL standard does not allow to formally JOIN on well-known foreign key relationship information. Naturally, when you join BOOK to AUTHOR, you will want to do that based on the BOOK.AUTHOR_ID foreign key to AUTHOR.ID primary key relation. Not being able to do this in SQL leads to a lot of repetitive code, re-writing the same JOIN predicate again and again - especially, when your foreign keys contain more than one column. With jOOQ, when you use
+ In case of ambiguity, you can also supply field references for your foreign keys, or the generated foreign key reference to the onKey() method. +
+
+ Note that formal support for the Sybase JOIN ON KEY syntax is on the roadmap.
+
+ Most often, you will provide jOOQ with JOIN conditions in the JOIN .. ON clause. SQL supports a different means of specifying how two tables are to be joined. This is the JOIN .. USING clause. Instead of a condition, you supply a set of fields whose names are common to both tables to the left and right of a JOIN operation. This can be useful when your database schema has a high degree of relational normalisation. An example: +
+ ++ In schemas with high degrees of normalisation, you may also choose to use NATURAL JOIN, which takes no JOIN arguments as it joins using all fields that are common to the table expressions to the left and to the right of the JOIN operator. An example: +
+ ++ Oracle SQL ships with a special syntax available for OUTER JOIN clauses. According to the Oracle documentation about partitioned outer joins this can be used to fill gaps for simplified analytical calculations. jOOQ only supports putting the PARTITION BY clause to the right of the OUTER JOIN clause. The following example will create at least one record per AUTHOR and per existing value in BOOK.PUBLISHED_IN, regardless if an AUTHOR has actually published a book in that year. +
+ +
+ 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.
+
+ Here's how SEMI JOIN translates to EXISTS.
+
+ And here's how ANTI JOIN translates to NOT EXISTS
+
+ 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
+ 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
+ The WHERE clause can be used for JOIN or filter predicates, in order to restrict the data returned by the
+ The above syntax is convenience provided by jOOQ, allowing you to connect the
+ You will find more information about creating
+ The Oracle database knows a very succinct syntax for creating hierarchical queries: the CONNECT BY clause, which is fully supported by jOOQ, including all related functions and pseudo-columns. A more or less formal definition of this clause is given here: +
++ An example for an iterative query, iterating through values between 1 and 5 is this: +
+ ++ Here's a more complex example where you can recursively fetch directories in your database, and concatenate them to a path: +
++ The output might then look like this +
+ +
+ Some of the supported functions and pseudo-columns are these (available from the
+ 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. +
+ +
+ The Oracle database allows for specifying a SIBLINGS keyword in the
+ GROUP BY can be used to create unique groups of data, to form aggregations, to remove duplicates and for other reasons. It will transform your previously defined
+ The above example counts all books per author. +
+
+ 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 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: +
+ ++ This will return an arbitrary title per author. jOOQ supports this syntax, as jOOQ is not doing any checks internally, about the consistence of tables/fields/functions that you provide it. +
+ +
+ jOOQ supports empty GROUP BY () clause as well. This will result in
+ Some databases support the SQL standard grouping functions and some extensions thereof. See the manual's section about
+ The HAVING clause is commonly used to further restrict data resulting from a previously issued
+ According to the SQL standard, you may omit the GROUP BY clause and still issue a HAVING clause. This will implicitly GROUP BY (). jOOQ also supports this syntax. The following example selects one record, only if there are at least 4 books in the books table: +
+ +
+ 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
+ Note that in order to create such a window definition, we need to first create a
+ Even if only PostgreSQL and Sybase SQL Anywhere natively support this great feature, jOOQ can emulate it by expanding any window() method - if the database supports window functions at all.
+
+ Some more information about WINDOW clause can be found on our blog: http://blog.jooq.org/2013/11/03/probably-the-coolest-sql-feature-window-functions/
+
+ Databases are allowed to return data in any arbitrary order, unless you explicitly declare that order in the ORDER BY clause. In jOOQ, this is straight-forward: +
+ +
+ Any jOOQ
+ The SQL standard allows for specifying integer literals (
+ Note, how one() is used as a convenience short-cut for inline(1)
+
+ A few databases support the SQL standard "null ordering" clause in sort specification lists, to define whether NULL values should come first or last in an ordered result.
+
+ If your database doesn't support this syntax, jOOQ emulates it using a
+ Using
+ But writing these things can become quite verbose. jOOQ supports a convenient syntax for specifying sort mappings. The same query can be written in jOOQ as such: +
+ ++ More complex sort indirections can be provided using a Map: +
+ ++ Of course, you can combine this feature with the previously discussed NULLS FIRST / NULLS LAST feature. So, if in fact these two books are the ones you like least, you can put all NULLS FIRST (all the other books): +
+ +
+ The SQL standard defines that a "query expression" can be ordered, and that query expressions can contain
+ jOOQ also supports Oracle's SIBLINGS keyword to be used with ORDER BY clauses for
+ While being extremely useful for every application that does pagination, or just to limit result sets to reasonable sizes, this clause is not yet part of any SQL standard (up until SQL:2008). Hence, there exist a variety of possible implementations in various SQL dialects, concerning this limit clause. jOOQ chose to implement the LIMIT .. OFFSET clause as understood and supported by MySQL, H2, HSQLDB, Postgres, and SQLite. Here is an example of how to apply limits with jOOQ: +
+ +
+ This will limit the result to 1 books starting with the 2nd book (starting at offset 0!). limit() is supported in all dialects, offset() in all but Sybase ASE, which has no reasonable means to emulate it. This is how jOOQ trivially emulates the above query in various SQL dialects with native OFFSET pagination support:
+
+ Things get a little more tricky in those databases that have no native idiom for OFFSET pagination (actual queries may vary):
+
+ 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. +
+ ++ As can be seen in the above example, writing correct SQL can be quite tricky, depending on the SQL dialect. For instance, with SQL Server, you cannot have an ORDER BY clause in a subquery, unless you also have a TOP clause. This is illustrated by the fact that jOOQ renders a TOP 100 PERCENT clause for you. The same applies to the fact that ROW_NUMBER() OVER() needs an ORDER BY windowing clause, even if you don't provide one to the jOOQ query. By default, jOOQ adds ordering by the first column of your projection. +
+
+ The previous chapter talked about
+ By default, most users will use the semantics of the ONLY keyword, meaning a LIMIT 5 expression (or FETCH NEXT 5 ROWS ONLY expression) will result in at most 5 rows. The alternative clause WITH TIES will return at most 5 rows, except if the 5th row and the 6th row (and so on) are "tied" according to the ORDER BY clause, meaning that the ORDER BY clause does not deterministically produce a 5th or 6th row. For example, let's look at our book table:
+
+ Resulting in: +
+ +
+ We're now getting two rows because both rows "tied" when ordering them by ACTOR_ID. The database cannot really pick the next 1 row, so they're both returned. If we omit the WITH TIES clause, then only a random one of the rows would be returned.
+
+ Not all databases support WITH TIES. Oracle 12c supports the clause as specified in the SQL standard, and SQL Server knows TOP n WITH TIES without OFFSET support.
+
+ One of the previous chapters talked about LIMIT .. OFFSET, or OFFSET .. FETCH or some other vendor-specific variant of the same. This can lead to significant performance issues when reaching a high page number, as all unneeded records need to be skipped by the database.
+
+ A much faster and more stable way to perform pagination is the so-called keyset pagination method also called seek method. jOOQ supports a synthetic seek() clause, that can be used to perform keyset pagination. Imagine we have these data:
+
+ 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:
+
OFFSET where you would expect+ 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: +
++ Further information about offset pagination vs. keyset pagination performance can be found on our partner page: +
+ +
+
+ + For inter-process synchronisation and other reasons, you may choose to use the SELECT .. FOR UPDATE clause to indicate to the database, that a set of cells or records should be locked by a given transaction for subsequent updates. With jOOQ, this can be achieved as such: +
+ ++ The above example will produce a record-lock, locking the whole record for updates. Some databases also support cell-locks using FOR UPDATE OF .. +
+ ++ Oracle goes a bit further and also allows to specify the actual locking behaviour. It features these additional clauses, which are all supported by jOOQ: +
+FOR UPDATE NOWAIT: This is the default behaviour. If the lock cannot be acquired, the query fails immediatelyFOR UPDATE WAIT n: Try to wait for [n] seconds for the lock acquisition. The query will fail only afterwardsFOR UPDATE SKIP LOCKED: This peculiar syntax will skip all locked records. This is particularly useful when implementing queue tables with multiple consumers+ With jOOQ, you can use those Oracle extensions as such: +
+ +
+ The SQL standard specifies a FOR UPDATE clause to be applicable for cursors. Most databases interpret this as being applicable for all SELECT statements. An exception to this rule are the CUBRID and SQL Server databases, that do not allow for any FOR UPDATE clause in a regular SQL SELECT statement. jOOQ emulates the FOR UPDATE behaviour, by locking record by record with JDBC. JDBC allows for specifying the flags TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE for any statement, and then using ResultSet.updateXXX() methods to produce a cell-lock / row-lock. Here's a simplified example in JDBC:
+
+ The main drawback of this approach is the fact that the database has to maintain a scrollable cursor, whose records are locked one by one. This can cause a major risk of deadlocks or race conditions if the JDBC driver can recover from the unsuccessful locking, if two Java threads execute the following statements: +
+ ++ So use this technique with care, possibly only ever locking single rows! +
+ +FOR SHARE clause
+ Some databases (MySQL, Postgres) also allow to issue a non-exclusive lock explicitly using a FOR SHARE clause. This is also supported by jOOQ
+
+ Note, that jOOQ also supports optimistic locking, if you're doing simple CRUD. This is documented in the section's manual about
+ 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
+ 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.
+
+ 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+.
+
+ As previously mentioned in the manual's section about the
+ In case your database doesn't support ordered UNION subselects, the subselects are nested in derived tables:
+
+ 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
+ If you are closely coupling your application to an Oracle (or CUBRID) database, you might need to be able to pass hints of the form /*+HINT*/ with your SQL statements to the Oracle database. For example:
+
+ This can be done in jOOQ using the .hint() clause in your SELECT statement:
+
+ 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:
+
+ 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!".
+
+ The logical order of SELECT clauses, however, does not correspond to the syntax. In fact, the logical order is this:
+
SELECT DISTINCT statement, data is further reduced to remove duplicatesUNION-connected subqueries. Unless this is a UNION ALL clause, data is further reduced to remove duplicates+ The SQL Server documentation also explains this, with slightly different clauses: +
+ +FROMONJOINWHEREGROUP BYWITH CUBE or WITH ROLLUPHAVINGSELECTDISTINCTORDER BYTOP+ As can be seen, databases have to logically reorder a SQL statement in order to determine the best execution plan. +
+ +
+ 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: +
++ A SLICK example: +
+ +
+ While this looks like a good idea at first, it only complicates translation to more advanced SQL statements while impairing readability for those users that are used to writing SQL. jOOQ is designed to look just like SQL. This is specifically true for SLICK, which not only changed the SELECT clause order, but also heavily "integrated" SQL clauses with the Scala language.
+
+ For these reasons, the jOOQ DSL API is modelled in SQL's lexical order. +
+
+ The 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.
+
+ 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:
+
+ Note that for explicit degrees up to {max-row-degree}, the VALUES() constructor provides additional typesafety. The following example illustrates this:
+
+ 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 +
++ jOOQ tries to stay close to actual SQL. In detail, however, Java's expressiveness is limited. That's why the values() clause is repeated for every record in multi-record inserts. +
++ Some RDBMS do not support inserting several records in a single statement. In those cases, jOOQ emulates multi-record INSERTs using the following SQL: +
+ +
+ 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:
+
+ This can make a lot of sense in situations where you want to "reserve" a row in the database for an subsequent
+ The DEFAULT VALUES clause is not supported in all databases, but jOOQ can emulate it using the equivalent statement:
+
+ The DEFAULT keyword (or
+ MySQL (and some other RDBMS) allow for using a non-SQL-standard, UPDATE-like syntax for INSERT statements. This is also supported in jOOQ (and emulated for all databases), should you prefer that syntax. The above INSERT statement can also be expressed as follows: +
+ ++ 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. +
++ In some occasions, you may prefer the INSERT SELECT syntax, for instance, when you copy records from one table to another: +
+ +
+ 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
+ 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: +
+ +
+ 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 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: +
+ +
+ 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
+ Some databases have poor support for returning generated keys after INSERTs. In those cases, jOOQ might need to issue another
+ The UPDATE statement is used to modify one or several pre-existing records in a database table. UPDATE statements are only possible on single tables. Support for multi-table updates will be implemented in the near future. An example update query is given here: +
+ +
+ Most databases allow for using scalar subselects in UPDATE statements in one way or another. jOOQ models this through a set(Field<T>, Select<? extends Record1<T>>) method in the UPDATE DSL API:
+
+ jOOQ supports formal
+ This can be particularly useful when using subselects: +
+ ++ The above row value expressions usages are completely typesafe. +
+ +
+ The Firebird and Postgres databases support a RETURNING clause on their UPDATE statements, similar as the RETURNING clause in
+ 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 DELETE statement removes records from a database table. DELETE statements are only possible on single tables. Support for multi-table deletes will be implemented in the near future. An example delete query is given here: +
+ ++ The MERGE statement is one of the most advanced standardised SQL constructs, which is supported by DB2, HSQLDB, Oracle, SQL Server and Sybase (MySQL has the similar INSERT .. ON DUPLICATE KEY UPDATE construct) +
++ The point of the standard MERGE statement is to take a TARGET table, and merge (INSERT, UPDATE) data from a SOURCE table into it. DB2, Oracle, SQL Server and Sybase also allow for DELETING some data and for adding many additional clauses. With jOOQ {jooq-version}, only Oracle's MERGE extensions are supported. Here is an example: +
+ ++ 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: +
+ +
+ 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
+
+ Much like 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.
+
+ jOOQ's DDL support is currently still very limited. In the long run, jOOQ will support the most important statement types for frequent informal database migrations, though. Note that jOOQ will not aim to replace existing database migration frameworks. At Data Geekery, we usually recommend using Flyway for migrations. See also the
+ jOOQ currently supports the following ALTER statements (SQL examples in PostgreSQL syntax):
+
+ These statements alter the table itself: +
+ ++ These statements alter / add / drop columns and their types: +
+ ++ These statements alter / add / drop constraints: +
+ +
+ jOOQ currently supports the following CREATE statements (SQL examples in PostgreSQL syntax):
+
+ jOOQ currently supports the following DROP statements (SQL examples in PostgreSQL syntax):
+
+ Even if the TRUNCATE statement mainly modifies data, it is generally considered to be a DDL statement. It is popular in many databases when you want to bypass constraints for table truncation. Databases may behave differently, when a truncated table is referenced by other tables. For instance, they may fail if records from a truncated table are referenced, even with ON DELETE CASCADE clauses in place. Please, consider your database manual to learn more about its TRUNCATE implementation.
+
+ The TRUNCATE syntax is trivial:
+
+ TRUNCATE is not supported by Ingres and SQLite. jOOQ will execute a DELETE FROM AUTHOR statement instead.
+
+ When using jOOQ's
+ 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:
+
+ 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. +
+
+ Most databases know some sort of namespace to group objects like
+ 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: +
+ +
+ By default, the Settings.renderCatalog flag is turned on. In case a database supports querying multiple catalogs, jOOQ will generate fully qualified object names, including catalog name. For more information about this setting, see
+ jOOQ's
+ 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
+ The following sections explain the various types of table expressions supported by jOOQ +
+
+ Most of the times, when thinking about a
+ The above example shows how AUTHOR and BOOK tables are joined in a
+ See the manual's section about
+ The strength of jOOQ's
+ 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.
+
+ 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:
+
+ 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): +
+ +
+ This feature is useful in various use-cases where column names are not known in advance (but the table's degree is!). An example for this are
+ Only few databases really support such a syntax, but fortunately, jOOQ can emulate it easily using UNION ALL and an empty dummy record specifying the new column names. The two statements are equivalent:
+
+ In jOOQ, you would simply specify a varargs list of column aliases as such: +
+ +
+ The
+ SQL and relational algebra distinguish between at least the following JOIN types (upper-case: SQL, lower-case: relational algebra): +
+
+ jOOQ supports all of these JOIN types (including semi-join and anti-join) directly on any
+ Most of the above JOIN types are overloaded also to accommodate
+ Note that most of jOOQ's JOIN operations give way to a similar DSL API hierarchy as previously seen in the manual's section about the
+ 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 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
+ 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: +
+ +
+ The PIVOT clause is available from the
+ There is one operation in relational algebra that is not given a lot of attention, because it is rarely used in real-world applications. It is the relational division, the opposite operation of the cross product (or, relational multiplication). The following is an approximate definition of a relational division: +
+ ++ With jOOQ, you can simplify using relational divisions by using the following syntax: +
+ ++ The above roughly translates to +
+ ++ Or in plain text: Find those TEXT values in C whose ID's correspond to all ID's in B. Note that from the above SQL statement, it is immediately clear that proper indexing is of the essence. Be sure to have indexes on all columns referenced from the on(...) and returning(...) clauses. +
+ ++ For more information about relational division and some nice, real-life examples, see +
+ + +
+ 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
+ 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. +
+ +
+ The real power of these types become more obvious when you fetch them from
+ Note, in order to access the DbmsXplan package, you can use the
+ Some databases support functions that can produce tables for use in arbitrary (ID, TITLE) columns containing either all the books or just one book by ID:
+
+ The jOOQ code generator will now produce a
+ The SQL standard specifies that the
FROM clause (as required by the SQL standard)FROM clause (and still allow a WHERE clause)FROM clause only with a WHERE clause, GROUP BY clause, or HAVING clause
+ With jOOQ, you don't have to worry about the above distinction of SQL dialects. jOOQ never requires a FROM clause, but renders the necessary "DUAL" table, if needed. The following program shows how jOOQ renders "DUAL" tables
+
+ Note, that some databases (H2, MySQL) can normally do without "DUAL". However, there exist some corner-cases with complex nested SELECT statements, where this will cause syntax errors (or parser bugs). To stay on the safe side, jOOQ will always render "dual" in those dialects.
+
+ 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
+ jOOQ allows you to freely create arbitrary column expressions using a fluent expression construction API. Many expressions can be formed as functions from
+ In general, it is up to you whether you want to use the "prefix" notation or the "postfix" notation to create new column expressions based on existing ones. The "SQL way" would be to use the "prefix notation", with functions created from the
+ Table columns are the most simple implementations of a
+ Table columns implement a more specific interface called <R extends Record> record type.
+
+ See the manual's section about
+ Just like
+ Here is how it's done with jOOQ: +
+ ++ When you alias Fields like above, you can access those Fields' values using the alias name: +
+ +
+ jOOQ's source code generator tries to find the most accurate type mapping between your vendor-specific data types and a matching Java type. For instance, most VARCHAR, CHAR, CLOB types will map to String. Most BINARY, BYTEA, BLOB types will map to byte[]. NUMERIC types will default to
+ 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:
+
+ in jOOQ, you can write something like that: +
+ +
+ 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
+
+ The complete CAST API in
+ A slightly different use case than
+ 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. +
+
+ Your database can do the math for you. Arithmetic operations are implemented just like
+ In order to express a SQL query like this one: +
+ ++ You can write something like this in jOOQ: +
+ +
+ jOOQ does not know any operator precedence (see also
+ jOOQ also supports the Oracle-style syntax for adding days to a Field<? extends java.util.Date> +
+ +
+ For more advanced datetime arithmetic, use the DSL's timestampDiff() and dateDiff() functions, as well as jOOQ's built-in SQL standard INTERVAL data type support:
+
INTERVAL YEAR TO MONTH: INTERVAL DAY TO SECOND:
+ The SQL standard defines the concatenation operator to be an infix operator, similar to the ones we've seen in the chapter about ||. Some other dialects do not support this operator, but expect a concat() function, instead. jOOQ renders the right operator / function, depending on your
+ There are a variety of general functions supported by jOOQ As discussed in the chapter about
+ This is a list of general functions supported by jOOQ's
COALESCE: Get the first non-null value in a list of arguments.NULLIF: Return NULL if both arguments are equal, or the first argument, otherwise.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
+ Math can be done efficiently in the database before returning results to your Java application. In addition to the
+ 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.ASIN: Get the arc sine of a value.ATAN: Get the arc tangent of a value.ATAN2: Get the atan2 function of two values.CEIL: Get the smalles integer value larger than a given numeric value.COS: Get the cosine of a value.COSH: Get the hyperbolic cosine of a value.COT: Get the cotangent of a value.COTH: Get the hyperbolic cotangent of a value.DEG: Transform radians into degrees.EXP: Calculate e^value.FLOOR: Get the largest integer value smaller than a given numeric value.GREATEST: Finds the greatest among all argument values (can also be used with non-numeric values).LEAST: Finds the least among all argument values (can also be used with non-numeric values).LN: Get the natural logarithm of a value.LOG: Get the logarithm of a value given a base.POWER: Calculate value^exponent.RAD: Transform degrees into radians.RAND: Get a random number.ROUND: Rounds a value to the nearest integer.SIGN: Get the sign of a value (-1, 0, 1).SIN: Get the sine of a value.SINH: Get the hyperbolic sine of a value.SQRT: Calculate the square root of a value.TAN: Get the tangent of a value.TANH: Get the hyperbolic tangent of a value.TRUNC: Truncate the decimals off a given value.
+ Please refer to the
+ Interestingly, bitwise functions and bitwise arithmetic is not very popular among SQL databases. Most databases only support a few bitwise operations, while others ship with the full set of operators. jOOQ's API includes most bitwise operations as listed below. In order to avoid ambiguities with
BIT_COUNT: Count the number of bits set to 1 in a numberBIT_AND: Set only those bits that are set in two numbersBIT_OR: Set all bits that are set in at least one numberBIT_NAND: Set only those bits that are set in two numbers, and inverse the resultBIT_NOR: Set all bits that are set in at least one number, and inverse the resultBIT_NOT: Inverse the bits in a numberBIT_XOR: Set all bits that are set in at exactly one numberBIT_XNOR: Set all bits that are set in at exactly one number, and inverse the resultSHL: Shift bits to the leftSHR: Shift bits to the right
+ 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/
+
+ String formatting can be done efficiently in the database before returning results to your Java application. As discussed in the chapter about
+ 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.CHAR_LENGTH: Get the length of a string in characters.CONCAT: Concatenate several strings.ESCAPE: Escape a string for use with the LENGTH: Get the length of a string.LOWER: Get a string in lower case letters.LPAD: Pad a string on the left side.LTRIM: Trim a string on the left side.OCTET_LENGTH: Get the length of a string in octets.POSITION: Find a string within another string.REPEAT: Repeat a string a given number of times.REPLACE: Replace a string within another string.RPAD: Pad a string on the right side.RTRIM: Trim a string on the right side.SUBSTRING: Get a substring of a string.TRIM: Trim a string on both sides.UPPER: Get a string in upper case letters.
+ Please refer to the
REGEXP, REGEXP_LIKE, etc.
+ Various databases have some means of searching through columns using regular expressions if the REGEX_LIKE operator. Being an operator (and not a function), you should use the corresponding method on
+ Note that the SQL standard specifies that patterns should follow the XQuery standards. In the real world, the POSIX regular expression standard is the most used one, some use Java regular expressions, and only a few ones use Perl regular expressions. jOOQ does not make any assumptions about regular expression syntax. For cross-database compatibility, please read the relevant database manuals carefully, to learn about the appropriate syntax. Please refer to the
+ Most databases allow for specifying a COLLATION which allows for re-defining the ordering of string values. By default, ASCII, ISO, or Unicode encodings are applied to character data, and ordering is applied according to the respective encoding.
+
+ Sometimes, however, certain queries like to ignore parts of the encoding by treating upper-case and lower-case characters alike, such that ABC = abc, or such that ABC, jkl, XyZ are an ordered list of strings (case-insensitively).
+
+ For these ad-hoc ordering use-cases, most people resort to using LOWER() or UPPER() as follows:
+
+ 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.CURRENT_TIMESTAMP: Get current date as a TIMESTAMP object.DATE_ADD: Add a number of days or an interval to a date.DATE_DIFF: Get the difference in days between two dates.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.
+ 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
+ This is a list of system functions supported by jOOQ's
CURRENT_USER: Get current user.
+ Aggregate functions work just like functions, even if they have a slightly different semantics. Here are some example aggregate functions from the
+ Here's an example, counting the number of books any author has written: +
+ +
+ Aggregate functions have strong limitations about when they may be used and when not. For instance, you can use aggregate functions in scalar queries. Typically, this means you only select aggregate functions, no
+ Oracle and some other databases support "ordered-set aggregate functions". This means you can provide an ORDER BY clause to an aggregate function, which will be taken into consideration when aggregating. The best example for this is Oracle's LISTAGG() (also known as GROUP_CONCAT in other
+ The above query might yield: +
+ +
+ Oracle allows for restricting aggregate functions using the KEEP() clause, which is supported by jOOQ. In Oracle, some aggregate functions (MIN, MAX, SUM, AVG, COUNT, VARIANCE, or STDDEV) can be restricted by this clause, hence
+ jOOQ also supports using your own user-defined aggregate functions. See the manual's section about
+ In those databases that support over() on it. See the manual's section about
+ Most major RDBMS support the concept of window functions. jOOQ knows of implementations in DB2, Oracle, Postgres, SQL Server, and Sybase SQL Anywhere, and supports most of their specific syntaxes. Note, that H2 and HSQLDB have implemented ROW_NUMBER() functions, without true windowing support.
+
+ As previously discussed, any over() method. See the chapter about
+ 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:
+
+ If possible, however, jOOQ tries to render missing clauses for you, if a given
+ Here are some simple examples of window functions with jOOQ: +
+ +
+ 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 over() method:
+
+ In the previous chapter about LISTAGG(). These functions have a window function / analytical function variant, as well. For example:
+
FIRST and LAST aggregate functions
+ In the previous chapter about FIRST and LAST aggregate functions". These functions have a window function / analytical function variant, as well. For example:
+
+ User-defined aggregate functions also implement over(). This is supported by Oracle in particular. See the manual's section about
+ The SQL standard defines special functions that can be used in the ROLLUP() for instance:
+
+ 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:
+
+ CUBE() is different from ROLLUP() in the way that it doesn't just create N+1 groupings, it creates all 2^N possible combinations between all group fields in the CUBE() function argument list. Let's re-consider our second query from before:
+
+ The results would then hold: +
+ +
+ GROUPING SETS() are the generalised way to create multiple groupings. From our previous examples
+
ROLLUP(AUTHOR_ID, PUBLISHED_IN) corresponds to GROUPING SETS((AUTHOR_ID, PUBLISHED_IN), (AUTHOR_ID), ())CUBE(AUTHOR_ID, PUBLISHED_IN) corresponds to GROUPING SETS((AUTHOR_ID, PUBLISHED_IN), (AUTHOR_ID), (PUBLISHED_IN), ())
+ This is nicely explained in the SQL Server manual pages about GROUPING SETS() and other grouping functions:
+ http://msdn.microsoft.com/en-us/library/bb510427(v=sql.105)
+
+ 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
+ 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
+ The above function will be made available from a generated
+ Note that user-defined functions returning
+ Some databases support user-defined aggregate functions, which can then be used along with OBJECT type (the example was taken from the Oracle 11g documentation):
+
+ The above OBJECT type is then available to function declarations as such:
+
+ jOOQ's SECOND_MAX() aggregate function with jOOQ:
+
+ The CASE expression is part of the standard SQL syntax. While some RDBMS also offer an IF expression, or a DECODE function, you can always rely on the two types of CASE syntax:
+
+ In jOOQ, both syntaxes are supported (The second one is emulated in Derby, which only knows the first one). Unfortunately, both case and else are reserved words in Java. jOOQ chose to use decode() from the Oracle DECODE function, or choose(), and otherwise(), which means the same as else.
+
+ A CASE expression can be used anywhere where you can place a SELECT the above expression, if you're selecting from AUTHOR:
+
+ Oracle knows a more succinct, but maybe less readable DECODE() function with a variable number of arguments. This function roughly does the same as the second case expression syntax. jOOQ supports the DECODE() function and emulates it using CASE expressions in all dialects other than Oracle:
+
+ Sort indirection is often implemented with a CASE clause of a SELECT's ORDER BY clause. See the manual's section about the
+ Sequences implement the
+ So if you have a sequence like this in Oracle: +
+ +
+ You can then use your
+ According to the SQL standard, row value expressions can have a degree of more than one. This is commonly used in 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
+ Row value expressions are incompatible with most other
+ See the relevant sections for more details about how to use row value expressions in predicates. +
+ +
+ The
+ 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. +
++ Conditions or conditional expressions are widely used in SQL and in the jOOQ API. They can be used in +
+JOIN .. ON clause, to be precise) of a + 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: +
+1 or TRUE0 or FALSENULL or UNKNOWN
+ It is important to know that SQL differs from many other languages in the way it interprets the NULL boolean value. Most importantly, the following facts are to be remembered:
+
[ANY] = NULL yields NULL (not FALSE)[ANY] != NULL yields NULL (not TRUE)NULL = NULL yields NULL (not TRUE)NULL != NULL yields NULL (not FALSE)
+ For simplified NULL handling, please refer to the section about the
+ Note that jOOQ does not model these values as actual
+ With jOOQ, most
+ There are a few types of conditions, that can be created statically from the
TRUE and FALSE conditional expressions
+ Conditions can also be connected using
+ In SQL, as in most other languages, AND and OR binary operators, as well as the NOT unary operator, to form new conditional expressions. In jOOQ, this is modelled as such:
+
+ The above example shows that the number of parentheses in Java can quickly explode. Proper indentation may become crucial in making such code readable. In order to understand how jOOQ composes combined conditional expressions, let's assign component expressions first: +
+ +
+ Here are all boolean operators on the
+ In SQL, comparison predicates are formed using common comparison operators: +
+
+ 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
+ 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.
+
+ In addition to the above, jOOQ provides a few convenience methods for common operations performed on strings using comparison predicates: +
+ +
+ As previously mentioned in the manual's section about AND, OR, and NOT. The following expressions are equivalent:
+
+ In SQL, the two expressions wouldn't be the same, as SQL natively knows operator precedence. +
+ +
+ All variants of the
+ jOOQ supports all of the above row value expression comparison predicates, both with
+ If the right-hand side of a ALL, ANY, or SOME. Note that the SQL standard defines ANY and SOME to be equivalent. jOOQ settled for the more intuitive ANY and doesn't support SOME. Here are some examples, supported by jOOQ:
+
+ For the example, the right-hand side of the quantified comparison predicates were filled with argument lists. But it is easy to imagine that the source of values results from a
+ It is interesting to note that the SQL standard defines the ANY-quantified predicate. The following two expressions are equivalent:
+
+ Typically, the
+ In SQL, you cannot compare NULL with any value using NULL again, which is neither TRUE nor FALSE (see also the manual's section about NULL, use the NULL predicate as such:
+
+ The SQL NULL predicate also works well for NOT() operator! Here are some examples:
+
+ The SQL standard contains a nice truth table for the above rules: +
+ +
+ In jOOQ, you would simply use the isNull() and isNotNull() methods on row value expressions. Again, as with the NULL predicate is emulated by jOOQ, if your database does not natively support it:
+
+ Some databases support the DISTINCT predicate, which serves as a convenient, NULL-safe DISTINCT predicate, the following truth table can be assumed:
+
[ANY] IS DISTINCT FROM NULL yields TRUE[ANY] IS NOT DISTINCT FROM NULL yields FALSENULL IS DISTINCT FROM NULL yields FALSENULL IS NOT DISTINCT FROM NULL yields TRUE
+ For instance, you can compare two fields for distinctness, ignoring the fact that any of the two could be NULL, which would lead to funny results. This is supported by jOOQ as such:
+
+ If your database does not natively support the DISTINCT predicate, jOOQ emulates it with an equivalent
+ ... or better, if the INTERSECT set operation is supported:
+
+ The BETWEEN predicate can be seen as syntactic sugar for a pair of
+ Note the inclusiveness of range boundaries in the definition of the BETWEEN predicate. Intuitively, this is supported in jOOQ as such:
+
+ 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: +
+ +
+ The SQL BETWEEN predicate also works well for
+ 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 predicates are popular for simple wildcard-enabled pattern matching. Supported wildcards in all SQL databases are:
+
+ With jOOQ, the LIKE predicate can be created from any
+ 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:
+
+ In the above predicate expressions, the exclamation mark character is passed as the escape character to escape wildcard characters "!_" and "!%", as well as to escape the escape character itself: "!!"
+
+ Please refer to your database manual for more details about escaping patterns with 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:
+
+ Note, that jOOQ escapes % and _ characters in value in some of the above predicate implementations. For simplicity, this has been omitted in this manual.
+
+ In SQL, apart from comparing a value against several values, the IN predicate can be used to create semi-joins or anti-joins. jOOQ knows the following methods on the IN predicates:
+
+ A sample IN predicate might look like this:
+
+ 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:
+
+ A good way to prevent this from happening is to use the NULL-value insensitive. See the manual's section about
+ The SQL IN predicate also works well for
+ jOOQ supports the IN predicate with row value expressions.An example is given here:
+
+ 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.
+
+ Slightly less intuitive, yet more powerful than the previously discussed EXISTS predicate, that can be used to form semi-joins or anti-joins. With jOOQ, the EXISTS predicate can be formed in various ways:
+
+ An example of an EXISTS predicate can be seen here:
+
+ 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()
+ 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:
+ http://blog.jooq.org/2012/07/27/not-in-vs-not-exists-vs-left-join-is-null-mysql/
+
+ When comparing dates, the SQL standard allows for using a special OVERLAPS predicate, which checks whether two date ranges overlap each other. The following can be said:
+
+ jOOQ supports the OVERLAPS predicate on
+ This allows for expressing the above predicates as such: +
+ +
+ Unlike the standard (or any database implementing the standard), jOOQ also supports the OVERLAPS predicate for comparing arbitrary (1, 3) OVERLAPS (2, 4) will yield true in jOOQ. This is emulated as such
+
+ A popular approach to querying database tables is called Query by Example, meaning that an "example" of a result record is provided instead of a formal query: +
+ ++ The translation from an example record to a query is fairly straight-forward: +
+ +
+ jOOQ knows a simple API called
+ The latter API call makes use of the convenience API
+ In most cases,
+ 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: +
+ ++ Each individual expression, and collection of expressions can be seen as an independent entity that can be +
+ +
+ Dynamic construction is particularly useful in the case of the
+ 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
+ A DSL is a nice thing to have, it feels "fluent" and "natural", especially if it models a well-known language, such as SQL. But a DSL is always expressed in a host language (Java in this case), which was not made for exactly the same purposes as its hosted DSL. If it were, then jOOQ would be implemented on a compiler-level, similar to LINQ in .NET. But it's not, and so, the DSL is limited by language constraints of its host language. We have seen many functionalities where the DSL becomes a bit verbose. This can be especially true for: +
++ 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! +
+
+ jOOQ allows you to embed SQL as a String into any supported
+ Plain SQL API methods are usually overloaded in three ways. Let's look at the condition query part constructor:
+
+ Both the bind value and the query part argument overloads make use of jOOQ's
+ Please refer to the
+ 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:
+
+ There are some important things to keep in mind when using plain SQL: +
+
+ The
+ Such a plain SQL template always consists of two things: +
+ +
+ The SQL string may reference the arguments by 0-based indexing. Each argument may be referenced several times. For instance, SQLite's emulation of the REPEAT(string, count) function may look like this:
+
+ For convenience, there is also a
+ When processing these plain SQL templates, a mini parser is run that handles things like +
+ ++ The above are recognised by the templating engine and contents inside of them are ignored when replacing numbered placeholders and/or bind variables. For instance: +
+ ++ The above query does not contain any numbered placeholders nor bind variables, because the tokens that would otherwise be searched for are contained inside of comments, string literals, or quoted names. +
+
+ A full-fledged SQL parser is available from
+ Historically, jOOQ implements an internal domain-specific language in Java, which generates SQL (an external domain-specific language) for use with JDBC. The jOOQ API is built from two parts: The
+ With this parser, the whole set of jOOQ functionality will now also be made available to anyone who is not using jOOQ directly, including JDBC and/or JPA users, e.g. through the
+ The possibilities are endless, including standardised, SQL string based database migrations that work on any SQLDialect that is supported by jOOQ.
+
+ This parser API allows for parsing an arbitrary SQL string fragment into a variety of jOOQ API elements: +
+ ++ The parser is able to parse any unspecified dialect to produce a jOOQ representation of the SQL expression, for instance: +
+ +
+ The above SQL query is valid standard SQL and runs out of the box on PostgreSQL and SQL Server, among others. The jOOQ ResultQuery that is generated from this SQL string, however, will also work on any other database, as jOOQ can emulate the two interesting SQL features being used here:
+
+ The query might be rendered as follows on the H2 database, which supports VALUES(), but not derived column lists:
+
+ Or like this on Oracle, which supports neither feature: +
+ ++ The existing implementation of the SQL parser is a hand-written, recursive descent parser. There are great advantages of this approach over formal grammar-based, generated parsers (e.g. by using ANTLR). These advantages are, among others: +
+ ++ Nevertheless, there is a grammar available for documentation purposes and it is included in the manual here: +
+ ++ (The layout of the grammar and the grammar itself is still work in progress) +
+ + {parser-grammar} + ++ The diagrams have been created with the neat RRDiagram library by Christopher Deckers. +
+
+ Various SQL objects
+ For the above reasons, jOOQ by default quotes all names in generated SQL to be sure they match what is really contained in your database. This means that the following names will be rendered +
+ +
+ Note that you can influence jOOQ's name rendering behaviour through
+ Custom, qualified or unqualified names can be created very easily using the
+ Such names can be used as standalone
+ More details about how to use names / identifiers to construct such expressions can be found in the relevant sections of the manual. +
++ Bind values are used in SQL / JDBC for various reasons. Among the most obvious ones are: +
++ 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. +
++ 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
+ Should you decide to run the above query outside of jOOQ, using your own
+ You can also extract specific bind values by index from a query, if you wish to modify their underlying value after creating a query. This can be achieved as such: +
+ +
+ For more details about jOOQ's internals, see the manual's section about
+ Some SQL access abstractions that are built on top of JDBC, or some that bypass JDBC may support named parameters. jOOQ allows you to give names to your parameters as well, although those names are not rendered to SQL strings by default. Here is an example of how to create named parameters using the
+ The
+ In order to actually render named parameter names in generated SQL, use the
+ Sometimes, you may wish to avoid rendering bind variables while still using custom values in SQL. jOOQ refers to that as "inlined" bind values. When bind values are inlined, they render the actual value in SQL rather than a JDBC question mark. Bind value inlining can be achieved in two ways: +
++ In both cases, your inlined bind values will be properly escaped to avoid SQL syntax errors and SQL injection. Some examples: +
+ ++ 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 (
+ 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
+ All methods in the jOOQ API that allow for plain (unescaped, untreated) SQL contain a warning message in their relevant Javadoc, to remind you of the risk of SQL injection in what is otherwise a SQL-injection-safe API. +
+
+ A
+ Both of these methods are contained in jOOQ's internal API's
+ The following sections explain some more details about
+ Every
+ An overview of the
+ The following additional methods are inherited from a common
+ A simple example can be provided by checking out jOOQ's internal representation of a (simplified) AUTHOR.ID = BOOK.AUTHOR_ID condition here:
+
+ This is how jOOQ renders such a condition (simplified example): +
+ +
+ See the manual's sections about
+ As mentioned in the previous chapter about
+ And then, use the above DSLContext to render pretty-printed SQL: +
+ +
+ The section about
+ Every
+ An overview of the
+ Some additional methods are inherited from a common
+ A simple example can be provided by checking out jOOQ's internal representation of a (simplified) AUTHOR.ID = BOOK.AUTHOR_ID condition here:
+
+ This is how jOOQ binds values on such a condition: +
+
+ See the manual's sections about
+ jOOQ supports all the standard SQL data types out of the box, i.e. the types contained in
+ The simplest use-case of injecting custom data types is by using Converter can convert from a database type <T> to a user-defined type <U> and vice versa. You'll be implementing this SPI:
+
+ If, for instance, you want to use Java 8's DATE and TIMESTAMP, you write a converter like this:
+
+ This converter can now be used in a variety of jOOQ API, most importanly to create a new data type: +
+ +
+ And data types, in turn, can be used with any
+ While converters are very useful for simple use-cases,
+ Below is full fledged example implementation that uses Google Gson to model JSON documents in Java +
+ +
+ 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:
+
+ 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: +
+ +
+ 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
+ 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
+ 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():
+
+ The above CustomField implementation can be exposed from your own custom DSL class:
+
+ If you don't need the integration of rather complex QueryParts into jOOQ, then you might be safer using simple
+ 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. +
+ ++ 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: +
+ +-- in all databases (or #) in MySQL) are rendered without modification. Any bind variable or QueryPart placeholders in such comments are ignored./* and ending with */ in all databases) are rendered without modification. Any bind variable or QueryPart placeholders in such comments are ignored.' in all databases, where all databases support escaping of the quote character by duplication as such: '', or in MySQL by escaping as such: \' (if " in most databases, with ` in MySQL, or with [ and ] in T-SQL databases) are rendered without modification. Any bind variable or QueryPart placeholders in such comments are ignored.{fn ...}, {d ...}, {t ...}, {ts ...}) is rendered without modification. Any bind variable or QueryPart placeholders in such comments are ignored.? or :name for named bind variables) are replaced by the matching bind value in case inlining is activated, e.g. through {number}) are replaced by the matching QueryPart.{identifier}) are treated like keywords and rendered in the correct case according to
+ 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
+ The only transient, non-serializable element in any jOOQ object is the
+ Another way of attaching QueryParts automatically, or rather providing them with a new
+ With jOOQ 3.2's
+ 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
+ But textual or binary bind values can get quite long, quickly filling your log files with irrelevant information. It would be good to be able to abbreviate such long values (and possibly add a remark to the logged statement). Instead of patching jOOQ's internals, we can just transform the SQL statements in the logger implementation, cleanly separating concerns. This can be done with the following VisitListener:
+
+ If maxLength were set to 5, the above listener would produce the following log output: +
+ +
+ The above VisitListener is in place since jOOQ 3.3 in the
+ jOOQ-Scala is a maven module used for leveraging some advanced Scala features for those users that wish to use jOOQ with Scala. +
+ +
+ The most obvious Scala feature to use in jOOQ are implicit defs for implicit conversions in order to enhance the
+ 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: +
+ ++ This feature is still being experimented with. With Scala Macros, it might be possible to inline a true SQL dialect into the Scala syntax, backed by the jOOQ API. Stay tuned! +
+
+ In a previous section of the manual, we've seen how jOOQ can be used to
+ JDBC calls executable objects "
+ 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
+ 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
+ The following sections of this manual will show how jOOQ is wrapping JDBC for SQL execution +
+ +
+ 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
+ Even if there are
+ Some of the most important differences between JDBC and jOOQ are listed here: +
+
+ Unlike JDBC, jOOQ has a lot of knowledge about a SQL query's structure and internals (see the manual's section about
+ Fetching is something that has been completely neglegted by JDBC and also by various other database abstraction libraries. Fetching is much more than just looping or listing records or mapped objects. There are so many ways you may want to fetch data from a database, it should be considered a first-class feature of any database abstraction API. Just to name a few, here are some of jOOQ's fetching modes: +
+
+ The term "fetch" is always reused in jOOQ when you can fetch data from the database. An
+ These modes of fetching are also documented in subsequent sections of the manual +
+ +
+ These means of fetching are also available from
+ These means of fetching are also available from
+ Note, that apart from the
+ jOOQ understands that SQL is much more expressive than Java, when it comes to the declarative typing of
+ Yet, still, sometimes you wish to use strongly typed records, when you know that you're selecting only from a single table: +
+ +
+ When fetching data only from a single table, the
+ When you use the
+ 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. +
+
+ In both of the above cases, you can map your
+ jOOQ's
+ 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. +
+
+ By default, jOOQ returns an
+ Note that most of these convenience methods are available both through
+ 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
+ See also the manual's section about the
+ 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
+ Your custom RecordMapper types can be used automatically through jOOQ's
+ See also the manual's section about the
+ Fetching data in records is fine as long as your application is not really layered, or as long as you're still writing code in the DAO layer. But if you have a more advanced application architecture, you may not want to allow for jOOQ artefacts to leak into other layers. You may choose to write POJOs (Plain Old Java Objects) as your primary DTOs (Data Transfer Objects), without any dependencies on jOOQ's
+ If you're using jOOQ's
+ 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
+ Just as with any other JPA implementation, you can put the
+ If jOOQ does not find any JPA-annotations, columns are mapped to the "best-matching" constructor, attribute or setter. An example illustrates this: +
+ +
+ Please refer to the
+ 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: +
+ +
+ Please refer to the
+ jOOQ also allows for fetching data into abstract classes or interfaces, or in other words, "proxyable" types. This means that jOOQ will return a
+ Please refer to the
+ The above examples show how to fetch data into your own custom POJOs / DTOs. When you have modified the data contained in POJOs, you probably want to store those modifications back to the database. 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
+ If you're using jOOQ's
+ 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
+ In the previous sections we have seen how to create RecordMapper every time you need one. For this, you can provide jOOQ's
+ 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. +
+ ++ 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: +
+ +
+ Unlike JDBC's
+ As a
+ Like
+ jOOQ 3.7+ supports Java 8, and with Java 8, it supports Stream API. Much like Stream keeps an internal reference to a JDBC Stream has to be treated like a resource. Here's an example of using such a stream:
+
+ A more sophisticated example would be using streams to transform the results and add business logic to it. For instance, to generate a DDL script with CREATE TABLE statements from the INFORMATION_SCHEMA of an H2 database:
+
+ The above combination of SQL and functional programming will produce the following output: +
+ ++ Many databases support returning several result sets, or cursors, from single queries. An example for this is Sybase ASE's sp_help command: +
++ The correct (and verbose) way to do this with JDBC is as follows: +
+ +
+ As previously discussed in the chapter about
+ The returned List<Result<Record>> type for backwards-compatibility reasons, but it also allows to access individual update counts that may have been returned by the database in between result sets.
+
+ Java 8 has introduced the new
+ 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
+ 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
+ Note, that instead of letting jOOQ spawn a new thread, you can also provide jOOQ with your own
+ When interacting with legacy applications, you may prefer to have jOOQ return a
+ Instead of operating on a JDBC ResultSet holding an open resource from your database, you can also let jOOQ's
+ The inverse of the above is possible too. Maybe, a legacy part of your application produces JDBC
+ You can also tighten the interaction with jOOQ's data type system and
+ If supplied, the additional information is used to override the information obtained from the
+ Apart from a few extra features (
+ Such a converter can be used in many parts of the jOOQ API. Some examples have been illustrated in the manual's section about
+ Here is a some more elaborate example involving a Converter for
+ jOOQ ships with a built-in default
+ jOOQ also allows for generated source code to reference your own custom converters, in order to permanently replace a
+ SQL result tables are not optimal in terms of used memory as they are not designed to represent hierarchical data as produced by JOIN operations. Specifically, FOREIGN KEY values may repeat themselves unnecessarily:
+
+ Now, if you have millions of records with only few distinct values for AUTHOR_ID, you may not want to hold references to distinct (but equal)
+ You can specify as many fields as you want for interning. The above has the following effect: +
+ +
+ Future versions of jOOQ will implement interning of data for non-String data types by collecting values in
+ Note, that jOOQ will not use interned data for identity comparisons: string1 == string2. Interning is used only to reduce the memory footprint of
+ With JDBC, you have full control over your SQL statements. You can decide yourself, if you want to execute a static
+ With jOOQ, this is easier. As a matter of fact, it is plain simple. With jOOQ, you can just set a flag in your
+ Not all databases are equal. Some databases show improved performance if you use
+ 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. +
+ +
+ 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 previously discussed in the chapter about
+ With JDBC, you can easily reuse a
+ 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. +
+ ++ 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: +
+ +
+ The above example shows how a query can be executed twice against the same underlying PreparedStatement. Notice how the Query must now be treated like a resource, i.e. it must be managed in a try-with-resources statement, or
+ 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: +
+ ++ 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 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.
+
+ With JDBC, you can easily execute several statements at once using the addBatch() method. Essentially, there are two modes in JDBC +
+ ++ In code, this looks like the following snippet: +
++ 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.
+
+ Most databases support sequences of some sort, to provide you with unique values to be used for primary keys and other enumerations. If you're using jOOQ's
+ Instead of actually phrasing a select statement, you can also use the
+ You can inline sequence references in jOOQ SQL statements. The following are examples of how to do that: +
+ +
+ For more info about inlining sequence references in SQL statements, please refer to the manual's section about
+ Many RDBMS support the concept of "routines", usually calling them procedures and/or functions. These concepts have been around in programming languages for a while, also outside of databases. Famous languages distinguishing procedures from functions are: +
++ The general distinction between (stored) procedures and (stored) functions can be summarised like this: +
+ ++ In general, it can be said that the field of routines (procedures / functions) is far from being standardised in modern RDBMS even if the SQL:2008 standard specifies things quite well. Every database has its ways and JDBC only provides little abstraction over the great variety of procedures / functions implementations, especially when advanced data types such as cursors / UDT's / arrays are involved. +
+
+ To simplify things a little bit, jOOQ handles both procedures and functions the same way, using a more general
+ If you're using jOOQ's
+ 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: +
+ +
+ For more details about
+ Unlike procedures, functions can be inlined in SQL statements to generate
+ 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
+ Oracle uses the concept of a PACKAGE to group several procedures/functions into a sort of namespace. The SQL 92 standard talks about "modules", to represent this concept, even if this is rarely implemented as such. This is reflected in jOOQ by the use of Java sub-packages in the
+ Apart from this, the generated source code looks exactly like the one for standalone procedures/functions. +
+
+ For more details about
+ Oracle UDTs can have object-oriented structures including member functions and procedures. With Oracle, you can do things like this: +
+ ++ These member functions and procedures can simply be mapped to Java methods: +
+ +
+ For more details about
+ If you are using jOOQ for scripting purposes or in a slim, unlayered application server, you might be interested in using jOOQ's exporting functionality (see also the
+ The above query will result in an XML document looking like the following one: +
+ +
+ The same result as an
+ See the XSD schema definition here, for a formal definition of the XML export format:
+ http://www.jooq.org/xsd/jooq-export-{export-xsd-version}.xsd
+
+ The above query will result in a CSV document looking like the following one: +
+ ++ In addition to the standard behaviour, you can also specify a separator character, as well as a special string to represent NULL values (which cannot be represented in standard CSV): +
+ ++ The above query will result in a JSON document looking like the following one: +
+ ++ Note: This format has been modified in jOOQ 2.6.0 and 3.7.0 +
++ The above query will result in an HTML document looking like the following one +
+ ++ The above query will result in a text document looking like the following one +
+ +
+ A simple text representation can also be obtained by calling toString() on a Result object. See also the manual's section about
+ If you are using jOOQ for scripting purposes or in a slim, unlayered application server, you might be interested in using jOOQ's importing functionality (see also exporting functionality). You can import data directly into a table from the formats described in the subsequent sections of this manual. +
+
+ The below CSV data represents two author records that may have been exported previously, by jOOQ's
+ With jOOQ, you can load this data using various parameters from the loader API. A simple load may look like this: +
+ ++ Here are various other examples: +
+ ++ Any of the above configuration methods can be combined to achieve the type of load you need. Please refer to the API's Javadoc to learn about more details. Errors that occur during the load are reported by the execute method's result: +
+ +
+ The below JSON data represents two author records that may have been exported previously, by jOOQ's
+ With jOOQ, you can load this data using various parameters from the loader API. A simple load may look like this: +
+ +
+ No other, JSON-specific options are currently available. For additional Loader API options, please refer to the manual's section about
+ A common use-case for importing records via jOOQ's Loader API is when data needs to be transferred between databases. For instance, when fetching the following data from database 1:
+
+ Now, this result should be imported back into a database 2: +
+ +
+ No other, Record-specific options are currently available. For additional Loader API options, please refer to the manual's section about
+ A common use-case for importing arrays via jOOQ's Loader API is when data is fetched into memory from some data source, or even ad-hoc data, which needs to be imported into a database.
+
+ No other, Array-specific options are currently available. For additional Loader API options, please refer to the manual's section about
This is not yet supported
++ Your database application probably consists of 50% - 80% CRUD, whereas only the remaining 20% - 50% of querying is actual querying. Most often, you will operate on records of tables without using any advanced relational concepts. This is called CRUD for +
+
+ 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
+ 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
+ If you're using jOOQ's
+ See the manual's section about
+ Storing a record will perform an
+ Some remarks about storing: +
++ Deleting a record will remove it from the database. Here's how you delete records: +
+ +
+ Refreshing a record from the database means that jOOQ will issue a
+ In order to perform a refresh, use the following Java code: +
+ +
+ CRUD operations can be combined with regular querying, if you select records from single database tables, as explained in the manual's section about selectFrom() method from the
+ All of jOOQ's
null, if the record was never in the databaseRecord API.
+ The purpose of the above information is for jOOQ's
+ Many databases support the concept of IDENTITY values, or
+ If you're using jOOQ's
+ DB2, Derby, HSQLDB, Ingres +
++ These SQL dialects implement the standard very neatly. +
++ H2, MySQL, Postgres, SQL Server, Sybase ASE, Sybase SQL Anywhere +
++ These SQL dialects implement identites, but the DDL syntax doesn’t follow the standard +
+
+ 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
+ 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. +
+
+ jOOQ allows you to perform
+ The above changes to jOOQ's behaviour are transparent to the API, the only thing you need to do for it to be activated is to set the Settings flag. Here is an example illustrating optimistic locking: +
+ +
+ If you're using jOOQ's
+ 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
+ As before, without the added TIMESTAMP column, optimistic locking is transparent to the API. +
+ ++ Instead of using TIMESTAMPs, you may also use numeric VERSION fields, containing version numbers that are incremented by jOOQ upon store() calls. +
+ +
+ Note, for explicit pessimistic locking, please consider the manual's section about the
+ 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
+ Internally, jOOQ will render all the required SQL statements and execute them as a regular
+ When performing CRUD, you may want to be able to centrally register one or several listener objects that receive notification every time CRUD is performed on an
+ An example of such a RecordListener is given here:
+
+ Now, configure jOOQ's runtime to load your listener +
+ +
+ For a full documentation of what RecordListener can do, please consider the RecordListener instances can be registered with a
+ If you're using jOOQ's
corresponds to the DAO's related generated POJO type
+// 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 findAll() throws DataAccessException;
+ P findById(T id) throws DataAccessException;
+ fetch(Field getType();
+}]]>
+ Besides these base methods, generated DAO classes implement various useful fetch methods. An incomplete example is given here, for the BOOK table: +
+ ++ 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: +
+ ++ There are essentially four ways how you can handle transactions in Java / SQL: +
+COMMIT, ROLLBACK and other statements directly in your database.+ While jOOQ does not aim to replace any of the above, it offers a simple API (and a corresponding SPI) to provide you with jOOQ-style programmatic fluency to express your transactions. Below are some Java examples showing how to implement (nested) transactions with jOOQ. For these examples, we're using Java 8 syntax. Java 8 is not a requirement, though. +
+ ++ Note how the lambda expression receives a new, derived configuration that should be used within the local scope: +
+ +
+ While some TransactionProvider implementations that require your transactional code to use the new, locally scoped Configuration, instead.
+
+ Transactional code is wrapped in jOOQ's
+ Such transactional code can be passed to
+ Any uncaught checked or unchecked exception thrown from your transactional code will rollback the transaction to the beginning of the block. This behaviour will allow for nesting transactions, if your configured
+ By default, jOOQ ships with the DataSourceTransactionManager can be seen here:
+
+ More information about how to use jOOQ with Spring can be found in the
+ This is an eternal and religious debate. Pros and cons have been discussed time and again, and it still is a matter of taste, today. In this case, jOOQ clearly takes a side. jOOQ's exception strategy is simple: +
++ With jOOQ, it's simple. All of jOOQ's exceptions are "system exceptions", hence they are all unchecked. +
+ +
+ jOOQ uses its own
+ DataAccessException is subtyped several times as follows: +
+
+ The following section about
+ The
+ For convenience and better backwards-compatibility, consider extending
+ Here is a sample implementation of an ExecuteListener, that is simply counting the number of queries per type that are being executed using jOOQ: +
+ ++ Now, configure jOOQ's runtime to load your listener +
+ ++ And log results any time with a snippet like this: +
+ ++ This may result in the following log output: +
+ +
+ Please read the
+ The following depicts an example of a custom ExecuteListener, which pretty-prints all queries being executed by jOOQ to stdout: +
+ +
+ See also the manual's sections about
+ 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:
+
+ You might want to replace the above implementation with a more efficient and more reliable one, of course. +
+
+ Since jOOQ 3.0, a simple wrapping API has been added to wrap JDBC's rather awkward
+ As previously discussed in the
+ A parsing connection is a JDBC
+ Running the above statement will yield: +
+ +
+ jOOQ logs all SQL queries and fetched result sets to its internal DEBUG logger, which is implemented as an
+ With the above configuration, let's fetch some data with jOOQ +
+ ++ The above query may result in the following log output: +
+ ++ Essentially, jOOQ will log +
+
+ If you wish to use your own logger (e.g. avoiding printing out sensitive data), you can deactivate jOOQ's logger using
+ Many users may have switched from higher-level abstractions such as Hibernate to jOOQ, because of Hibernate's difficult-to-manage performance, when it comes to large database schemas and complex second-level caching strategies. However, jOOQ itself is not a lightweight database abstraction framework, and it comes with its own overhead. Please be sure to consider the following points: +
++ 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. +
++ Just because you can, doesn't mean you must. In 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. +
+ ++ A lot of people are using Spring's useful org.springframework.jdbc.core.JdbcTemplate in their projects to simplify common JDBC interaction patterns, such as: +
+ +
+ When adding jOOQ to a project that is using JdbcTemplate extensively, a pragmatic first step is to use jOOQ as a SQL builder and pass the query string and bind variables to JdbcTemplate for execution. For instance, you may have the following class to store authors and their number of books in our stores:
+
+ You can then write the following code +
+ ++ This approach helps you gradually migrate from using JdbcTemplate to a jOOQ-only execution model. +
++ 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: +
+ +
+ If your query doesn't really map to JPA entities, you can fetch ordinary, untyped Object[] representations for your database records by using the following utility method:
+
+ Note, if you're using
+ This way, you can construct complex, type safe queries using the jOOQ API and have your
+ 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 (
+ Note, if you're using
+ With the above simple API, we're ready to write complex jOOQ queries and map their results to JPA entities: +
+ +
+ While JPA specifies how the mapping should be implemented (e.g. using JPABook and JPAAuthor entities (
+ In order to do so, we'll need to specify the
+ Note how we need to map between: +
++ With the above boilerplate in place, we can now fetch entities using jOOQ and JPA: +
+ +
+ Note, if you're using
+ Now that we have everything setup, we can use the above API to run a jOOQ query to fetch JPA entities like this: +
+ ++ The entities are now ready to be modified and persisted again. +
+ ++ Caveats: +
+List - there is a potential for ClassCastExceptionObject[], with the individual entities listed in the array, which need explicit casting
+ While optional, source code generation is one of jOOQ's main assets if you wish to increase developer productivity. jOOQ's code generator takes your database schema and reverse-engineers it into a set of Java classes modelling
+ The essential ideas behind source code generation are these: +
++ The following chapters will show how to configure the code generator and how to generate various artefacts. +
++ There are three binaries available with jOOQ, to be downloaded from http://www.jooq.org/download or from Maven central: +
++ You need to tell jOOQ some things about your database connection. Here's an example of how to do it for an Oracle database +
+ +
+ There are also lots of advanced configuration parameters, which will be treated in the
+ http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd
+
+ Code generation works by calling this class with the above property file as argument. +
+ ++ Be sure that these elements are located on the classpath: +
+ ++ Note that the property file must be passed as a classpath resource +
+ ++ Of course, you can also run code generation from your IDE. In Eclipse, set up a project like this. Note that: +
+
+ + Once the project is set up correctly with all required artefacts on the classpath, you can configure an Eclipse Run Configuration for org.jooq.util.GenerationTool. +
+
+ + With the XML file as an argument +
+
+ + And the classpath set up correctly +
+
+ + Finally, run the code generation and see your generated artefacts +
+
+ + Using the official jOOQ-codegen-maven plugin, you can integrate source code generation in your Maven build process: +
+ +
+ See a more complete example of a Maven pom.xml File in the
+ Be sure, both jooq-{jooq-version}.jar and your generated package (see configuration) are located on your classpath. Once this is done, you can execute SQL statements with your generated classes. +
+
+ In the
+ This optional top level configuration element simply allows for overriding the log level of anything that has been specified by the runtime, e.g. in log4j or slf4j and is helpful for per-code-generation log configuration. For example, in order to mute everything that is less than WARN level, write: +
+ ++ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ ++ Available log levels are +
+ +TRACEDEBUGINFOWARNERRORFATAL+ This optional top level configuration element allows for configuring a JDBC connection. By default, the jOOQ code generator requires an active JDBC connection to reverse engineer your database schema. For example, if you want to connect to a MySQL database, write this: +
+ ++ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ +
+ 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.
+
+ Gradle configuration +
+ +
+ JDBC drivers allow for passing
+ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ +
+ 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
+ There are some exceptions, where the JDBC connection does not need to be configured, for instance when using the
+ This mandatory top level configuration element wraps all the remaining configuration elements related to code generation, including the overridable code generator class. +
+ ++ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ +
+ The <name/> element allows for specifying a user-defined generator implementation. This is mostly useful when generating
+ jOOQ by default applies standard Java naming schemes: PascalCase for classes, camelCase for members, methods, variables, parameters, UPPER_CASE_WITH_UNDERSCORES for constants and other literals. This may not be the desired default for your database, e.g. when you strongly rely on case-sensitive naming and if you wish to be able to search for names both in your Java code and in your database code (scripts, views, stored procedures) uniformly. For that purpose, you can override the <strategy/> element with your own implementation, either:
+
+ For more details, please refer to the relevant sections, above. +
+ ++ This element wraps all the configuration elements that are used for the jooq-meta module, which reads the configured database meta data. In its simplest form, it can be left empty, when meaningful defaults will apply. +
+ +
+ The two main elements in the <database/> element are <name/> and <properties>, which specify the class to implement the database meta data source, and an optional list of key/value parameters:
+
+ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ +
+ The default <name/> if no name is supplied will be derived from the JDBC connection. If you want to specifically specify your SQL dialect's database name, any of these values will be supported by jOOQ, out of the box:
+
org.jooq.util.ase.ASEDatabaseorg.jooq.util.cubrid.CUBRIDDatabaseorg.jooq.util.db2.DB2Databaseorg.jooq.util.derby.DerbyDatabaseorg.jooq.util.firebird.FirebirdDatabaseorg.jooq.util.h2.H2Databaseorg.jooq.util.hana.HanaDatabseorg.jooq.util.hsqldb.HSQLDBDatabaseorg.jooq.util.informix.InformixDatabaseorg.jooq.util.ingres.IngresDatabaseorg.jooq.util.mariadb.MariaDBDatabaseorg.jooq.util.mysql.MySQLDatabaseorg.jooq.util.oracle.OracleDatabaseorg.jooq.util.postgres.PostgresDatabaseorg.jooq.util.redshift.RedshiftDatabaseorg.jooq.util.sqlite.SQLiteDatabaesorg.jooq.util.sqlserver.SQLServerDatabaseorg.jooq.util.sybase.SybaseDatabaseorg.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
+ Last, but not least, you can of course implement your own by implementing org.jooq.util.Database from the jooq-meta module.
+
+ A lot of configuration elements rely on regular expressions. The most prominent examples are the useful 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: +
+ ++ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ +
+ All the flags available from
+ 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):
+
+ Excludes match before includes, meaning that something that has been excluded cannot be included again. Remember, these expressions are "|", not with commas, etc. For example:
+
+ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ +
+ A special, additional option allows for specifying whether the above two regular expressions should also match table columns. The following example will hide an INVISIBLE_COL in any table (and also tables called this way, of course):
+
+ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ ++ Sometimes, you want to generate only tables. Or only routines. Or you want to exclude them from being generated. Whatever the use-case, there's a way to do this with the following, additional includes flags: +
+ ++ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ ++ By default, all these flags are set to true. +
+
+ jOOQ's
+ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ +
+ Note again that these expressions are
+ jOOQ's code generator recognises identity columns if they are reported as such by the database. Some databases do not support "real" identity columns, but allow for emulating them, e.g. through triggers and sequences (e.g. Oracle prior to 12c). If a column is a known "identity" without formally being one, users can specify a regular expression that matches all columns (one column per table), which will be treated as if they were formal identities. For example: +
+ ++ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ +
+ Note again that these expressions are
+ jOOQ's code generator recognises primary keys that are declared and reported as such by the database. But some databases don't report all keys, or some tables don't have them enabled, or sometimes, a view is a 1:1 representation of an underlying table, but it doesn't expose the key information. In these cases, this regular expression can match all columns that users wish to "pretend" are part of such a primary key. If a composite synthetic primary key is desired, the regular expression should match all columns of that table that are part of the primary key. For example, a composite synthetic primary key consists of (COLUMN1, COLUMN2) in table SCHEMA.TABLE:
+
+ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ ++ If the regular expression matches column in a table that already has an existing primary key, that existing primary key will be replaced by the synthetic one. It will still be reported as a unique key, though. +
+ +
+ Note again that these expressions are
+ In some legacy contexts, there might not be any primary key, only a bunch of unique keys, defined in a table. jOOQ cannot pick one of those as the "primary key", and the table won't be generated as a
+ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ +
+ If several keys match, a warning is emitted and the first one encountered will be used. This flag will also replace
+ Note again that these expressions are
+ The Oracle database doesn't know a SQL standard DATE type (YYYY-MM-DD). It's vendor-specific DATE type is really a TIMESTAMP(0), i.e. a TIMESTAMP with zero fractional seconds precision (YYYY-MM-DD HH24:MI:SS). For historic reasons, many legacy Oracle databases do not use the TIMESTAMP data type, but the DATE data type for timestamps, in case of which client applications also need to treat these columns as timestamps.
+
+ If upgrading the schema to proper TIMESTAMP usage isn't an option, and neither is using DATE type from the Oracle type system (at least as far as the jOOQ code generator is concerned), and pretend all such columns are really TIMESTAMP typed. This is how to activate the flag:
+
+ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ +
+ This flag will apply before any other data type related flags are applied, including
+ 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. +
+ ++ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ ++ 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
+ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ ++ These configuration elements combine two features in one: +
+ ++ There are two ways to operate "input" and "output" catalogs and schemas configurations: "top level" and "nested". Note that catalogs are only supported in very few databases, so usually, users will only use the "input" and "output" schema feature. +
+ ++ This mode is preferrable for small projects or quick tutorials, where only a single catalog and a/or a single schema need to be generated. In this case, the following "top level" configuration elements can be applied: +
+ ++ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ ++ This mode is preferrable for larger projects where several catalogs and/or schemas need to be included. The following examples show different possible configurations: +
+ ++ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ +
+ Wherever you can place an inputCatalog or inputSchema element (top level or nested), you can also put a matching mapping instruction, if you wish to profit from the
+ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ +
+ For more information about the catalog and schema mapping feature,
+ For continuous integration reasons, users often like to version their database schemas, e.g. with tools like
+ For this reason, jOOQ allows for implementing a simple code generation SPI which tells jOOQ what the user-defined version of any given catalog or schema is. +
+ ++ There are three possible ways to implement this SPI: +
+ +org.jooq.util.CatalogVersionProvider or org.jooq.util.SchemaVersionProvider respectively for programmatic version providing.SELECT statement returning one row with one column containing the version string. The SELECT statement may contain a named variable called :catalog_name or :schema_name respectively.
+ These schema versions will be generated into the javax.annotation.Generated annotation on generated artefacts.
+
+ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ ++ By default, the jOOQ code generator maintains the following ordering of objects: +
+ +
+ Sometimes, it may be desireable to override this default ordering to a custom ordering. In particular, the default ordering may be case-sensitive, when case-insensitive ordering is really more desireable at times. Users may define an order provider by specifying a fully qualified class on the code generator's class path, which must implement
+ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ ++ This order provider may then look as follows: +
+ ++ While changing the order of "top level types" (like tables) is irrelevant to the jOOQ runtime, there may be some side-effects to changing the order of table columns, user-defined type attributes, routine parameters, as the database might expect the exact same order as is defined in the database. In order to only change the ordering for tables, the following order provider can be implemented instead: +
+ ++ The code generator allows users to override column data types in three different ways: +
+ ++ All of this can be done using forced types. +
+ ++ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ +
+ Both user type mappings work the same way, regardless if you're using a
+ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ +
+ For more information about using converters,
+ Just switch the converter configuration to a binding configuration. +
+ ++ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ +
+ For more information about using converters,
+ jOOQ supports table valued functions in many databases, including Oracle, PostgreSQL, SQL Server. By default, table valued functions are treated as: +
+ +
+ The <tableValuedFunctions/> flag is thus set to false by default on Oracle, and true otherwise. Here's how to explicitly change this behaviour:
+
+ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ +
+ 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. +
+ ++ 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: +
+ ++ Load the above using standard JAXB API: +
+ ++ ... and then, modify parts of your configuration programmatically, for instance the JDBC user / password: +
++ 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. +
+ ++ The following example shows how you can override the DefaultGeneratorStrategy to render table and column names the way they are defined in the database, rather than switching them to camel case: +
+ ++ This is an example showing which generator strategy method will be called in what place when generating tables. For improved readability, full qualification is omitted: +
+ ++ This is an example showing which generator strategy method will be called in what place when generating records. For improved readability, full qualification is omitted: +
+ ++ This is an example showing which generator strategy method will be called in what place when generating pojos. For improved readability, full qualification is omitted: +
+ +
+ By default, jOOQ's generator strategy will convert your database's UNDER_SCORE_NAMES to PascalCaseNames as this is a more common idiom in the Java ecosystem. If, however, you want to retain the names and the casing exactly as it is defined in your database, you can use the org.jooq.util.KeepNamesGeneratorStrategy, which will retain all names exactly as they are.
+
+ More examples can be found here: +
+ +
+ In the <matchers/> element as such:
+
org.jooq.util.Definition.getName()), then by qualified name (org.jooq.util.Definition.getQualifiedName()).+ The above example used references to "MatcherRule", which is an XSD type that looks like this: +
+ +
+ The following example shows a matcher strategy that adds a "T_" prefix to all table classes and to table identifiers:
+
+ The following example shows a matcher strategy that renames BOOK table identifiers (or table identifiers containing BOOK) into BROCHURE (or tables containing BROCHURE): +
+ ++ For more information about each XML tag, please refer to the http://www.jooq.org/xsd/jooq-codegen-{codegen-xsd-version}.xsd XSD file. +
+Power users might choose to re-implement large parts of the org.jooq.util.JavaGenerator class. If you only want to add some custom code sections, however, you can extend the JavaGenerator and override only parts of it.
+ The above example simply adds a class footer to toString() implementation.
+
+ Any of the below methods can be overridden: +
+ +
+ When you override any of the above, do note that according to
+ For increased convenience at the use-site, jOOQ generates "global" artefacts at the code generation root location, referencing tables, routines, sequences, etc. In detail, these global artefacts include the following: +
++ When referencing global artefacts from your client application, you would typically static import them as such: +
+ +
+ Every table in your database will generate a
+ These flags from the
+ Routine generation can be deactivated using the tables flag +
+
+ Every table in your database will generate an
+ These flags from the
+ Record generation can be deactivated using the records flag +
++ Every table in your database will generate a POJO implementation that looks like this: +
+ +
+ These flags from the
+ POJO generation can be activated using the pojos flag +
++ Every table in your database will generate an interface that looks like this: +
+ +
+ These flags from the
+ Interface generation can be activated using the interfaces flag +
+
+ Every table in your database will generate a
+ DAO generation can be activated using the daos flag +
+
+ Every sequence in your database will generate a
+ Routine generation can be deactivated using the sequences flag +
+
+ Every procedure or function (routine) in your database will generate a
+ Procedures or functions contained in packages or UDTs are generated in a sub-package that corresponds to the package or UDT name. +
+ ++ Routine generation can be deactivated using the routines flag +
+
+ Every UDT in your database will generate a
+ Besides the
+ Routine generation can be deactivated using the udts flag +
+
+ Sometimes, the actual database data type does not match the SQL data type that you would like to use in Java. This is often the case for ill-supported SQL data types, such as BOOLEAN or UUID. jOOQ's code generator allows you to apply simple data type rewriting. The following configuration will rewrite IS_VALID columns in all tables to be of type BOOLEAN.
+
+ You must provide at least either an <expressions/> or a <types/> element, or both.
+
+ See the section about
+ When using a custom type in jOOQ, you need to let jOOQ know about its associated
+ 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.
+
+ The simple configuration is most useful in most situations as it can do only by specifying <forcedTypes/>:
+
+ +
+ +
+ 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:
+
+ See also the section about
+ The above configuration will lead to AUTHOR.DATE_OF_BIRTH being generated like this: +
+ +
+ This means that the bound type of <T> will be GregorianCalendar, wherever you reference DATE_OF_BIRTH. jOOQ will use your custom converter when binding variables and when fetching data from
+ The previous section discussed the case where your custom data type is mapped onto a standard JDBC type as contained in
+ The above <customType/> and <forcedType/>):
+
+ See also the section about
+ The above configuration will lead to AUTHOR.CUSTOM_DATA_JSON being generated like this: +
+ +
+ We've seen previously in the chapter about
+ The following configuration applies mapping only for schemata, not for catalogs. The <schemata/> element is a standalone element that can be put in the code generator's <database/> configuration element:
+
+ The following configuration applies mapping for catalogs and their schemata. The <catalogs/> element is a standalone element that can be put in the code generator's <database/> configuration element:
+
+ 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
+ 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: +
+ +<globalObjectReferences/>+ When using jOOQ's code generation capabilities, you will need to make a strategic decision about whether you consider your generated code as +
++ In this section we'll see that both approaches have their merits and that none of them is clearly better. +
+ ++ When you consider generated code as part of your code base, you will want to: +
++ This approach is particularly useful when your Java developers are not in full control of or do not have full access to your database schema, or if you have many developers that work simultaneously on the same database schema, which changes all the time. It is also useful to be able to track side-effects of database changes, as your checked-in database schema can be considered when you want to analyse the history of your schema. +
++ With this approach, you can also keep track of the change of behaviour in the jOOQ code generator, e.g. when upgrading jOOQ, or when modifying the code generation configuration. +
++ The drawback of this approach is that it is more error-prone as the actual schema may go out of sync with the generated schema. +
+ ++ When you consider generated code to be derived artefacts, you will want to: +
++ This approach is particularly useful when you have a smaller database schema that is under full control by your Java developers, who want to profit from the increased quality of being able to regenerate all derived artefacts in every step of your build. +
++ The drawback of this approach is that the build may break in perfectly acceptable situations, when parts of your database are temporarily unavailable. +
+ ++ In some situations, you may want to choose a pragmatic combination, where you put only some parts of the generated code under version control. For instance, jOOQ-meta's generated sources are put under version control as few contributors will be able to run the jOOQ-meta code generator against all supported databases. +
++ Many jOOQ users use jOOQ as a complementary SQL API in applications that mostly use JPA for their database interactions, e.g. to perform reporting, batch processing, analytics, etc. +
++ 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: +
+ +
+ Now, instead of connecting the jOOQ code generator to a database that holds a representation of the above schema, you can use jOOQ's JPADatabase and feed that to the code generator. The JPADatabase uses Hibernate internally, to generate an in-memory H2 database from your entities, and reverse-engineers that again back to jOOQ classes.
+
+ The easiest way forward is to use Maven in order to include the jooq-meta-extensions library (which then includes the H2 and Hibernate dependencies)
+
+ With that dependency in place, you can now specify the JPADatabase in your code generator configuration:
+
+ The above will generate all jOOQ artefacts for your AUTHOR and BOOK tables.
+
+ The JPADatabase will use Spring to look up your annotated entities from the classpath. This means that you have to create several modules with a dependency graph that looks like this:
+
+ You cannot put your JPA entities in the same module as the one that runs the jOOQ code generator. +
++ By default, jOOQ's code generator takes live database connections as a database meta data source. In many project setups, this might not be optimal, as the live database is not always available. +
+
+ One way to circumvent this issue is by providing jOOQ with a database meta definition file in XML format and by passing this XML file to jOOQ's XMLDatabase.
+
+ The XMLDatabase can read a standardised XML file that implements the http://www.jooq.org/xsd/jooq-meta-{meta-xsd-version}.xsd schema. Essentially, this schema is an XML representation of the SQL standard INFORMATION_SCHEMA, as implemented by databases like H2, HSQLDB, MySQL, PostgreSQL, or SQL Server.
+
+ An example schema definition containing simple schema, table, column definitions can be seen below: +
+ ++ Constraints can be defined with the following elements: +
+ +
+ The above file can be made available to the code generator configuration by using the XMLDatabase as follows:
+
+ 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:
+
+ This XML configuration can now be checked in and versioned, and modified independently from your live database schema. +
+
+ In many cases, the schema is defined in the form of a SQL script, which can be used with
+ If you have a complete schema definition in a single file, or perhaps a set of incremental files that can reproduce your schema in any SQL dialect, then the DDLDatabase might be the right choice for you. It uses the
+ For example, the following database.sql script (the
+ While the script uses pretty standard SQL constructs, you may well use some vendor-specific extensions, and even
+ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ +
+ By default the code generator produces Java files for use with the jOOQ API as documented throughout this manual. In some cases, however, it may be desireable to generate other meta data formats, such as an XML document. This can be done with the XMLGenerator.
+
+ The format produced by the XMLGenerator is the same as the one consumed by the INFORMATION_SCHEMA, as implemented by databases like H2, HSQLDB, MySQL, PostgreSQL, or SQL Server.
+
+ In order to use the XMLGenerator, simply place the following class reference into your code generation configuration:
+
+ XML configuration (standalone and Maven) +
+ ++ Programmatic configuration +
+ ++ Gradle configuration +
+ ++ This configuration does not interfere with most of the remaining code generation configuration, e.g. you can still specify the JDBC connection or the generation output target as usual. +
+
+ There is no substantial difference between running the code generator with Maven or in standalone mode. Both modes use the exact same <configuration/> element. The Maven plugin configuration adds some additional boilerplate around that:
+
+ There are, however, some additional, Maven-specific flags that can be specified with the jooq-codegen-maven plugin only:
+
+ When running code generation with ant's <java/> task, you may have to set fork="true": +
+ +
+ Sometimes, ant can be useful to work around a limitation (misunderstanding?) of the Maven build. Just as with the above standalone ant usage example, the jOOQ code generator can be called from the maven-antrun-plugin:
+
+ 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. +
+ ++ 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: +
+ ++ These chapters hold some information about tools to be used with jOOQ +
++ 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.
+
+ 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: +
+
+ Optionally, you may even want to implement interfaces, such as
+ 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
+ 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:
+
+ The above are the execution modes supported by jOOQ. Whether you're using any of jOOQ's various fetching modes (e.g.
+ Now, here's how to implement MockDataProvider:
+
+ Essentially, the
+ You should return as many MockResult objects as there were query executions (in ResultSet, however, you can construct a "friendlier" Result in order to create the necessary JDBC
+ See the
+ 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. +
+ ++ jOOQ has two annotations that are very interesting for the Checker Framework to type check, namely: +
+ +
+ 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.
+
+ A detailed blog post shows how this works in depth. By adding a simple dependency to your Maven build: +
+ ++ ... you can now include one of the two checkers: +
+ +
+ The SQLDialect checker reads all of the
+ Configure this compiler plugin: +
+ ++ ... annotate your packages, e.g. +
+ ++ 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. +
+ ++ This checker is much simpler. Just add the following compiler plugin to deactivate plain SQL usage by default: +
+ +
+ 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
+ The Checker Framework does add some significant overhead in terms of compilation speed, and its IDE tooling is not yet at a level where such checks can be fed into IDEs for real user feedback, but the framework does work pretty well if you integrate it in your CI, nightly builds, etc. +
++ Together with Gudu Software, we have created an Open Source SQL 2 jOOQ parser that takes native SQL statements as input and generates jOOQ code as output. +
++ 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! +
+ ++ See it in action: +
+ ++ If all goes well, the above program yields: +
+ ++ SQL 2 jOOQ is a joint venture by Gudu Software Limited and Data Geekery GmbH. We will ship, test and maintain this awesome new addition with our own deliverables. So far, SQL 2 jOOQ supports the MySQL and PostgreSQL dialects and it is in an alpha stadium. Please, community, provide as much feedback as possible to make this great tool rock even more! +
+ ++ 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. +
++ The jOOQ Console is no longer supported or shipped with jOOQ 3.2+. You may still use the jOOQ 3.1 Console with new versions of jOOQ, at your own risk. +
++ These chapters hold some general jOOQ reference information +
++ Every RDMBS out there has its own little specialties. jOOQ considers those specialties as much as possible, while trying to standardise the behaviour in jOOQ. In order to increase the quality of jOOQ, some 70 unit tests are run for syntax and variable binding verification, as well as some 400 integration tests with an overall of around 4000 queries for any of these databases: +
++ For an up-to-date list of currently supported RDBMS and minimal versions, please refer to http://www.jooq.org/legal/licensing/#databases. +
++ There is always a small mismatch between SQL data types and Java data types. This is for two reasons: +
++ This chapter should document the most important notes about SQL, JDBC and jOOQ data types. +
+
+ jOOQ aims for hiding all JDBC details from jOOQ client API. Specifically,
+ Clob and Blob are resources (but not fetch() methods. fetchLazy() and fetchStream() might be candidates where Clob and Blob types could make sense as the underlying
+ ByteArrayInputStream and ByteArrayOutputStream on the other hand are two different types which cannot be represented as a single Field<T> type. If either would be chosen as the <T> type, we'd get read-only or write-only fields. So for full lazy streaming support, we'd need another 2-way wrapper type, similar to Clob and Blob.
+
+ In many cases, streaming binary data isn't really necessary as thebyte[] can be easily kept in memory (and it is done so for further processing anyway, e.g. when working with images), so the extra work might not really be needed. This is particularly true in Oracle, where BLOBs are the only binary types in the absences of a formal (VAR)BINARY type, and CLOBs start at 4000 bytes.
+
+ Hence, jOOQ currently doesn't explicitly support JDBC BLOB and CLOB data types. If you use any of these data types in your database, jOOQ will map them to byte[] and String instead. In simple cases (small data), this simplification is sufficient. In more sophisticated cases, you may have to bypass jOOQ, in order to deal with these data types and their respective resources. +
+
+ Some databases explicitly support unsigned integer data types. In most normal JDBC-based applications, they would just be mapped to their signed counterparts letting bit-wise shifting and tweaking to the user. jOOQ ships with a set of unsigned
+ Each of these wrapper types extends
+ jOOQ fills a gap opened by JDBC, which neglects an important SQL data type as defined by the SQL standards: INTERVAL types. SQL knows two different types of intervals: +
+
+ 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
+ In addition to the
+ XML data types are currently not supported +
++ Geospacial data types are currently not supported +
++ Some databases support cursors returned from stored procedures. They are mapped to the following jOOQ data type: +
+ +
+ In fact, such a cursor will be fetched immediately by jOOQ and wrapped in an
+ The SQL standard specifies ARRAY data types, that can be mapped to Java arrays as such: +
+ ++ The above array type is supported by these SQL dialects: +
+
+ Oracle has strongly-typed arrays and table types (as opposed to the previously seen anonymously typed arrays). These arrays are wrapped by
+ 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
+ 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.
+
+ The best way to work around this issue is to implement a CAST expression for every bind variable:
+
+ Historic versions of jOOQ used to support a <dateAsTimestamp/> flag, which can be used with the out-of-the-box
+ For more information, please refer to
+ 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 syntax does not always need keywords to form expressions. The clause takes various argument assignments:
+
+ The above example also shows missing operator overloading capabilities, where "=" is replaced by "," in jOOQ. Another example are
+ In this case, ROW is an actual (optional) SQL keyword, implemented by at least PostgreSQL.
+
+ 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: +
+ ++ Future versions of jOOQ may use all-uppercased method names in addition to the camel-cased ones (to prevent collisions with Java keywords): +
+ ++ Some SQL keywords aren't really necessary. They are just part of a keyword-rich language, the way Java developers aren't used to anymore. These keywords date from times when languages such as ADA, BASIC, COBOL, FORTRAN, PASCAL were more verbose: +
+BEGIN .. ENDREPEAT .. UNTILIF .. THEN .. ELSE .. END IF+ jOOQ omits some of those keywords when it is too tedious to write them in Java. +
+ +
+ 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.
+
+ 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. +
+ +
+ The parentheses used for the WITHIN GROUP (..) and OVER (..) clauses are required in SQL but do not seem to add any immediate value. In some cases, jOOQ omits them, although the above might be optionally re-phrased in the future to form a more SQLesque experience:
+
+ Some SQL keywords map onto Java Language Keywords if they're mapped using camel-casing. These keywords currently include: +
+CASEELSEFOR+ jOOQ replaces those keywords by "synonyms": +
+ ++ There is more future collision potential with: +
+BOOLEANCHARDEFAULTDOUBLEENUMFLOATIFINTLONGPACKAGE+ Most SQL operators have to be mapped to descriptive method names in Java, as Java does not allow operator overloading: +
+ +
+ For those users using
+ 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: +
+ +
+ Common table expressions define a "derived column list", just like t.a from t.
+
+ This chapter will soon contain an overview over jOOQ's API using a pseudo BNF notation. +
++ jOOQ is running some of your most mission-critical logic: the interface layer between your Java / Scala application and the database. You have probably chosen jOOQ for any of the following reasons: +
++ 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 are performed against dummy JDBC interfaces using http://jmock.org/. These tests verify that various
+ 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. +
++ For libraries like jOOQ, integration tests are much more expressive than unit tests, as there are so many subtle differences in SQL dialects. Simple mocks just don't give as much feedback as an actual database instance. +
++ 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. +
+ ++ 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. +
+ ++ 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. +
+ ++ As a general rule of thumb throughout the jOOQ code, everything is kept DRY. Some examples: +
++ Keeping things DRY leads to longer stack traces, but in turn, also increases the relevance of highly reusable code-blocks. Chances that some parts of the jOOQ code base slips by integration test coverage decrease significantly. +
++ 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. +
+ +
+ Support for
+ Here are some affected API parts: +
+DSL.select(...) now implement Select<Record[N]>, not Select<Record>IN predicates and comparison predicates taking subselects changed incompatiblyINSERT and MERGE statements now take typesafe VALUES() clauses+ Some hints related to row value expressions: +
+ ++ In order to support type-safe row value expressions and type-safe Record[N] types, SelectQuery is now generic: SelectQuery<R> +
+ ++ The duplication of the SELECT API is no longer useful, now that SelectQuery and SelectXXXStep are generic. +
+ ++ The pre-existing Factory class has been split into two parts: +
+ ++ The FactoryOperations interface has been renamed to DSLContext. An example: +
+ ++ Field.equalAny(...) and similar methods have been removed in favour of Field.eq(any(...)). This greatly simplified the Field API. An example: +
+ +
+ 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 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:
+
+ Beware! Previously, Field.eq(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: +
+ ++ Here is an example how to check if a field has a given value, without applying SQL's ternary NULL logic: +
+ +
+ 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
+
DSLContext is only a DSL entry point for constructing "attached" QueryPartsExecuteContext has a well-defined lifecycle, tied to that of a single query executionRenderContext has a well-defined lifecycle, tied to that of a single rendering operationBindContext has a well-defined lifecycle, tied to that of a single variable binding operation+ In order to resolve confusion that used to arise because of different lifecycle durations, these types are now no longer formally connected through inheritance. +
+ ++ 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: +
+ ++ These are some side-effects of the above change +
+ ++ 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. +
+ ++ The data type API has been changed drastically in order to enable some new DataType-related features. These changes include: +
+ ++ These objects have been moved / renamed: +
+ +org.jooq.util.unsigned to org.jooq.util.types (which already contained INTERVAL data types)+ Here are some minor features that have been removed in jOOQ 3.0 +
+ +Table.getPrimaryKey() != null check.USE statement support has been removed from jOOQ. Its behaviour was ill-defined, while it didn't work the same way (or didn't work at all) in some databases.+ jOOQ lives in a very challenging ecosystem. The Java to SQL interface is still one of the most important system interfaces. Yet there are still a lot of open questions, best practices and no "true" standard has been established. This situation gave way to a lot of tools, APIs, utilities which essentially tackle the same problem domain as jOOQ. jOOQ has gotten great inspiration from pre-existing tools and this section should give them some credit. Here is a list of inspirational tools in alphabetical order: +
+