diff --git a/jOOQ-website/src/main/resources/manual-2.5.xml b/jOOQ-website/src/main/resources/manual-2.5.xml index 499c4c8ac6..4b7ef83d6f 100644 --- a/jOOQ-website/src/main/resources/manual-2.5.xml +++ b/jOOQ-website/src/main/resources/manual-2.5.xml @@ -4,5201 +4,648 @@
This manual is divided into four main sections:
-- See these chapters for an overview of the jOOQ internal architecture - and all types that are involved with jOOQ's query creation and - execution. This is the important part for you, also, if you wish to - extend jOOQ -
-- See these chapters to understand how you can use jOOQ as a source code - generator, and what type of artefacts are generated by jOOQ -
-- See these chapters to learn about how to use jOOQ in every day's work. The - jOOQ DSL is the main way to create and execute jOOQ queries almost as - if SQL was embedded in Java directly -
-- Some advanced topics including not-everyday functionality -
-TODO: overview here
jOOQ essentially has two packages:
-
- This section is about the main jOOQ classes and the global
- architecture. Most of the time, however, you will be using the
-
- 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 exposes a lot of interfaces and hides most implementation facts - from client code. The reasons for this are: -
-
- The
If you are planning on using several RDBMS (= SQLDialects) or - several distinct JDBC Connections in your software, this will mean - that you have to create a new Factory every time.
- -
- The jOOQ Factory allows for some optional configuration elements to be used by advanced users.
- The
- 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.1.0.xsd
-
- 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. This will be useful in the future, when access to - schema artefacts will be unified. Currently, this has no use. -
- -- With jOOQ 2.0, static factory methods have been introduced in order to - make your code look more like SQL. Ideally, when working with jOOQ, you - will simply static import all methods from the Factory class: -
-- This will allow to access functions even more fluently: -
- -
- Objects created statically from the Factory do not need a reference to
- any factory, as they can be constructed independently from your Configuration
- (connection, dialect, schema mapping). They will access that information at
- render / bind time. See
-
- The jOOQ Factory expects its underlying
-
- So if you want your queries to run in separate transactions, if you - want to roll back a transaction, if you want to close a Connection and - return it to your container, you will have to take care of that - yourself. jOOQ's Factory will always expect its Connection to be in a - ready state for creating new PreparedStatements. If it is not, you have - to create a new Factory. -
-
- Please keep in mind that many jOOQ objects will reference your Factory
- for their whole lifecycle. This is especially interesting, when dealing
- with
Tables represent any entity in your underlying RDBMS, that holds - data for selection, insertion, updates, and deletion. In other - words, views are also considered tables by jOOQ.
-The formal definition of a
- This means that every table is associated with a subtype of the
-
- Unlike in the
- JPA CriteriaQuery API,
- this generic type
- <R>
- is not given so much importance as far as
- type-safety is concerned.
- SQL itself is highly typesafe. You have
- incredible flexibility of creating anonymous or ad-hoc
- types and
- reusing them from
-
The formal definition of a Field starts with
-
- Fields are generically parameterised with a Java type
- <T>
- that reflects the closest match to the RDMBS's underlying datatype for that
- field. For instance, if you have a VARCHAR2 type Field in Oracle,
- <T>
- would bind to
-
The Field itself is a very broad concept. Other tools, or databases - refer to it as expression or column. When you just want to
- -
- Then 1 is considered a Field or more explicitly, a
-
- More advanced uses become clear quickly, when you do things like -
-
- Where 1 + 1 itself is a Field or more explicitly, an
-
- See some details about how to create these queries in the
-
- A specific type of field is the
-
- TableFields join both <R> and <T> generic parameters into their specification: -
-- This can be used for additional type safety in the future, or by client code. -
-
- The
-
- A similar object is the
-
- The Record itself holds all the data from your selected tuple. If it is
- a
- In some cases, you will not be able to reference the selected Fields - both when you create the SELECT statement and when you fetch data from - Records. Then you might use field names or indexes, as with JDBC. - However, of course, the type information will then be lost as well. If - you know what type you want to get, you can always use the Record's - convenience methods for type conversion, however. Some examples: -
-
- For more information about the type conversions that are supported by
- jOOQ, read the Javadoc on
-
- UpdatableRecords are a specific subtype of TableRecord that have - primary key information associated with them. -
-As of jOOQ 1.5, the UpdatableRecord essentially contains three additional - methods CRUD - (Create Read Update Delete) operations:
-An example lifecycle of a book can be implemented as such:
-These operations are very simple utilities. They do not - reflect the functionality offered by Hibernate - or other persistence managers.
- -- If the jOOQ code-generator cannot detect any PRIMARY KEY, or UNIQUE KEY - on your tables, then the generated artefacts implement TableRecord, - instead of UpdatableRecord. A TableRecord can perform the same CRUD - operations as we have seen before, if you provide it with the necessary - key fields. The API looks like this: -
- -- This is useful if your RDBMS does not support referential constraints (e.g. MySQL's - MyISAM), or if you want to - store records to an unconstrained view. An example lifecycle of a book without - any keys can then be implemented as such: -
-
- There are essentially two ways of creating SELECT statements in jOOQ.
- For historical reasons, you can create
-
Use the DSL API when:
-Use the regular API when:
-In any case, all API's will construct the same underlying - implementation object, and in many cases, you can combine the two - approaches. Let's check out the various SELECT statement types:
- -
- In the above example, some generated artefacts are used for querying.
- In this case, T_AUTHOR and T_BOOK are instances of types
-
- Apart from the singleton Table instances TAuthor.T_AUTHOR and - TBook.T_BOOK, these generated classes also contain one member - for every physical field, such as TAuthor.ID or TBook.TAUTHOR_ID, etc. - Depending on your configuration, those members can be static members - (better for static imports) or instance members (better for aliasing) -
- -- If you choose not to use the DSL API (for instance, because you don't - want to add Query parts in the order SQL expects them), you can use - this syntax: -
-
- The
- See the manual's
-
jOOQ supports two modes for INSERT statements. - The INSERT VALUES and the INSERT SELECT syntax
- -The DSL syntax tries to stay close to actual SQL. In detail,
- however, Java is limited in its possibilities. That's why the
- .values() clause is repeated for every record in multi-record inserts.
- Some RDBMS support
- inserting several records at the same time. This is also supported in
- jOOQ, and simulated using UNION clauses for those RDBMS that don't
- support this syntax.
-
Note: Just like in SQL itself, you can have syntax errors when you - don't have matching numbers of fields/values. Also, you can run into - runtime problems, if your field/value types don't match.
- -MySQL (and some other RDBMS) allow for using an UPDATE-like syntax - for INSERT statements. This is also supported in jOOQ, 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.
- -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 simulated in other RDBMS, where this is - possible. Here is an example how to use the ON DUPLICATE KEY UPDATE - clause:
-The MySQL database also supports an INSERT IGNORE INTO clause. - This is supported by jOOQ using the more convenient SQL - syntax variant of ON DUPLICATE KEY IGNORE, which can be equally - simulated in other databases using a MERGE statement:
-The Postgres database has native support for an INSERT .. RETURNING
- clause. This is a very powerful concept that is simulated for all
- other dialects using JDBC's
-
- Be aware though, that this can lead to race-conditions - in those databases that cannot properly return generated - ID values. -
- -You can always use the more verbose regular syntax of the InsertQuery, if you need more control:
-The InsertQuery.addValue() method is overloaded, such that you can - also provide a Field, potentially containing an expression:
-Note that especially MySQL (and some other RDBMS) has some - limitations regarding that syntax. You may not be able to - select from the same table you're inserting into
- -In some occasions, you may prefer the INSERT SELECT syntax, for instance, when - you copy records from one table to another:
-UPDATE statements are only possible on single tables. Support for - multi-table updates will be implemented in the near future.
- -Using the
DELETE statements are only possible on single tables. Support for - multi-table deletes will be implemented in the near future.
- -Using the
- 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 2.0.1, 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 simulated by jOOQ for all other
- databases that support the SQL standard. For more information
- about the H2 MERGE syntax, see the documentation here:
-
-
- http://www.h2database.com/html/grammar.html#merge
-
- The syntax is trivial: -
- -This is not supported by Ingres and SQLite. jOOQ will execute a DELETE FROM - T_AUTHOR statement instead.
-- Data fetching is one of the great hassles in JDBC and JPA. - With jOOQ, you will be able to specify exactly, what kind of - data you want to fetch from any given query, as well as how - you want to fetch that data. This doesn't just mean distinguishing - between fetching one record at a time, or the whole resultset, - between fetching one column at a time, or the whole resultset. - This also means transforming your result (a list) into a map, - into arrays, into custom types, into JPA-annotated types, into - a call-back, or simply fetching it asynchronously -
-These methods allow for fetching a jOOQ Result or parts of it.
- -These methods transform the result into another form, if org.jooq.Result is not optimal
- -These methods transform the result into a user-defined form, if org.jooq.Result is not optimal
- -- Bind values are used in SQL / JDBC for various reasons. Among the most - obvious ones are: -
-- Bind values are omni-present in jOOQ. Whenever you create a condition, - you're actually also adding a bind value: -
-- The above notation is actually convenient way to explicitly create - a bind value for "Poe". You could also write this, instead: -
-
- Once created, bind values are part of the query's syntax tree (see
-
- The
- The
- NOTE: Should you wish to use jOOQ only as a query builder and execute - queries with another tool, such as Spring Data instead, you can also - use the Factory's renderNamedParams() method, to actually render named - parameter names in generated SQL: -
- -- 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: -
- -
- A
-
Both of these methods are contained in jOOQ's internal API's
-
A simple example can be provided by checking out jOOQ's internal
- representation of a
-
This is how jOOQ implements such a condition:
- -For more complex examples, please refer to the codebase, directly
-
- The only transient element in any jOOQ object is the
-
- Note, this functionality is deprecated with jOOQ 2.1.0.
- Please use the
In simple cases, you can register a ConfigurationProvider in jOOQ's ConfigurationRegistry
-Once you have executed these steps, all subsequent deserialisations - will try to access a Configuration (containing a JDBC Connection) from - your ConfigurationProvider. This may be useful when
-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 two classes are declared public and covered by 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.
-If you don't need integration of rather complex QueryParts into
- jOOQ, then you might be safer using simple
-
- In the previous chapter, we have seen how to use the
-
- Artefacts, such as tables, views, user defined types, sequences, stored - procedures, packages have a corresponding artefact in Java. -
-- There are three binaries available with jOOQ, to be downloaded from - SourceForge - or from Maven central: -
-All of jOOQ's dependencies are "optional", i.e. you can run - jOOQ without any of those libraries. - For instance, jOOQ maintains an "optional" dependency on log4j and slf4j. - This means, that jOOQ tries to find log4j (and /log4j.xml) or slf4j on the - classpath. If they are not present, then java.util.logging.Logger is - used instead. -
-- Other optional dependencies are the JPA API, and the Oracle JDBC driver, - which is needed for Oracle's advanced data types, only -
+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
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 properties 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:
- -See the full example of a pom.xml including the jOOQ-codegen artefact here: - https://github.com/jOOQ/jOOQ/blob/master/jOOQ-codegen-maven-example/pom.xml
- -- 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.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:
- -
- As of jOOQ 1.5, the top-level generated object is the
-
- Currently, it is not possible to link generated artefacts from various
- schemata. If you have a stored function from Schema A, which returns a
- UDT from Schema B, the types cannot be linked. This enhancement is on
- the roadmap, though:
- When you have several schemata that are logically equivalent (i.e. they
- contain identical entities, but the schemata stand for different
- users/customers/clients, etc), there is a solution for that. Check out
- the manual's section on support for
-
The schema can be used to dynamically discover generate database - artefacts. Tables, sequences, and other items are accessible from the - schema. For example:
-
- The most important generated artefacts are
-
- Suppose we have the tables as defined in the
-
If you use the
-
- If you're using jOOQ along with Hibernate / JPA, or if you - want to use your own, custom domain-model instead of jOOQ's - Record type-hierarchy, you can choose to select values into - POJOs. Let's say you defined a POJO for authors: -
+
- The above could be your custom POJO or a POJO generated
- by jooq-codegen (see
-
- Read the javadoc for - Record.into() - for more details. -
- +This is one of the most important reasons why you should consider
- jOOQ. Read also my
- article on dzone
- about why stored procedures become
- more and more important in future versions of RDMBS. In this section
- of the manual, we will learn how jOOQ handles stored procedures in
- code generation. Especially before
-
Let's say you have these stored procedures and functions in your Oracle database
-jOOQ will essentially generate two artefacts for every procedure/function:
-Let's see what these things look like, in Java. The classes (simplified for the example):
+An example invocation of such a stored procedure might look like this:
- -
- The above configuration is a
-
An sample invocation, equivalent to the previous example:
-- jOOQ does not formally distinguish procedures from functions. - jOOQ only knows about routines, which can have return values - and/or OUT parameters. This is the best option to handle the - variety of stored procedure / function support across the - various supported RDBMS. For more details, read on about this - topic, here: -
-- blog.jooq.org/2011/10/17/what-are-procedures-and-functions-after-all/ -
- -- Oracle uses the concept of a PACKAGE to group several - procedures/functions into a sort of namespace. The - SQL standard - talks about "modules", to represent this concept, even if this is - rarely implemented. This is reflected in jOOQ by the use of Java - sub-packages in the source code generation destination package. Every - Oracle package will be reflected by -
-- Apart from this, the generated source code looks exactly like the - one for - standalone procedures/functions. -
- -- Oracle UDT's 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 UDT's see the Manual's section on
-
- In recent years, most RDBMS have started to implement some support for - advanced data types. This support has not been adopted very well by - database users in the Java world, for several reasons: -
-- On the other hand, especially with stored procedures, these data types - are likely to become more and more useful in the future. If you have a - look at Postgres' capabilities of dealing with advanced data types - (ENUMs, - ARRAYs, - UDT's), - this becomes more and more obvious. -
-It is a central strategy for jOOQ, to standardise access to these
- kinds of types (as well as to
-
User Defined Types (UDT) are helpful in major RDMBS with lots - of proprietary functionality. The biggest player is clearly Oracle. - Currently, jOOQ provides UDT support for only two databases:
-Apart from that,
-In Oracle, you would define UDTs like this:
-These types could then be used in tables and/or stored procedures like such:
-
- Standard JDBC UDT support encourages JDBC-driver developers to implement
- interfaces such as
-
Now, when you interact with entities or procedures that hold UDT's, that's very simple as well. Here is an example:
-A similar thing can be achieved when interacting with the example stored procedure:
-- The notion of ARRAY types in RDBMS is not standardised at all. Very - modern databases (especially the Java-based ones) have implemented - ARRAY types exactly as what they are. "ARRAYs of something". In other - words, an ARRAY OF VARCHAR would be something very similar to Java's - notion of String[]. An ARRAY OF ARRAY OF VARCHAR would then be a - String[][] in Java. Some RDMBS, however, enforce stronger typing and - need the explicit creation of types for every ARRAY as well. These are - example String[] ARRAY types in various SQL dialects supported by jOOQ - 1.5.4: -
-Soon to be supported:
-- From jOOQ's perspective, the ARRAY types fit in just like any other - type wherever the - <T> generic type parameter is existent. It integrates well with tables - and stored procedures. -
- -An example usage of ARRAYs is given here for the Postgres dialect
- -When generating source code from the above entities, these artefacts will be created in Java:
-In Oracle, a VARRAY type is something slightly different than in - other RDMBS. It is a type that encapsules the actual ARRAY and creates - a new type from it. While all text[] types are equal and thus - compatible in Postgres, this does not apply for all VARRAY OF VARCHAR2 - types. Hence, it is important to provide access to VARRAY types and - generated objects from those types as well. The example above would - read like this in Oracle:
- -Note that it becomes clear immediately, that a mapping from
- U_STRING_ARRAY to String[] is obvious. But a mapping from String[] to
- U_STRING_ARRAY is not. These are the generated
-
True ENUM types are a rare species in the RDBMS world. Currently, - MySQL and Postgres are the only RDMBS supported by jOOQ, that provide - ENUM types.
- -Some examples:
-The above Postgres ENUM type will be generated as
-Intuitively, the generated classes for the T_BOOK table in Postgres would look like this:
-Note that jOOQ allows you to simulate ENUM types where this makes
- sense in your data model. See the section on
-
Sequences implement the
-
So if you have a sequence like this in Oracle:
-This is what jOOQ will generate:
-Which you can use in a select statement as such:
-Or directly fetch currval() and nextval() from the sequence using the Factory:
-jOOQ ships with its own DSL (or - Domain Specific Language) that - simulates SQL as good as possible in Java. This means, that you can - write SQL statements almost as if Java natively supported that syntax - just like .NET's C# does with LINQ to SQL.
- -Here is an example to show you what that means. When you want to write a query like this in SQL:
-
- You couldn't come much closer to SQL itself in Java, without re-writing the compiler.
- We'll see how the aliasing works later in the section about
-
When you don't just perform CRUD (i.e. SELECT * FROM your_table WHERE ID = ?), - you're usually generating new types using custom projections. With jOOQ, this is - as intuitive, as if using SQL directly. A more or less complete example of the "standard" SQL syntax, plus - some extensions, is provided by a query like this: -
- -So that's daily business. How to do it with jOOQ: When you first create a SELECT statement using the Factory's select() methods
-
- jOOQ will return an "intermediary" type to you, representing the
- SELECT statement about to be created (by the way, check out the
- section on
After adding the table-like structures (mostly just Tables) to
- select from, you may optionally choose to add a JOIN clause, as the
- type returned by jOOQ is the step where you can add JOINs. Again,
- adding these clauses is optional, as the
-
Now, if you do add a JOIN clause, you have to specify the JOIN .. ON
- condition before you can add more clauses. That's not an optional step
- for some JOIN types. This is reflected by the fact that
-
- See the section about
-
- Now we're half way through. As you can
- see above, we're back to the SelectJoinStep. This means, we can
- re-iterate and add another JOIN clause, just like in SQL. Or we go on
- to the next step, adding conditions in the
-
Now the returned type
-
Let's assume we have that method parseDate() creating a
-
and the HAVING clause:
-and the ORDER BY clause. Some RDBMS support NULLS FIRST and NULLS - LAST extensions to the ORDER BY clause. If this is not supported by - the RDBMS, then the behaviour is simulated with an additional CASE - WHEN ... IS NULL THEN 1 ELSE 0 END clause.
-and finally the LIMIT clause. Most dialects have a means of limiting - the number of result records (except Oracle). Some even support having - an OFFSET to the LIMIT clause. Even if your RDBMS does not support the - full LIMIT ... OFFSET ... (or TOP ... START AT ..., or FETCH FIRST ... ROWS ONLY, etc) - clause, jOOQ will simulate the LIMIT clause using nested selects and filtering on - ROWNUM (for Oracle), or on ROW_NUMBER() (for DB2 and SQL - Server):
-In the final step, there are some proprietary extensions available - only in some RDBMS. One of those extensions are the FOR UPDATE - (supported in most RDBMS) and FOR SHARE clauses (supported only in - MySQL and Postgres):
-
- Now the most relevant super-type of the object we have just created is
-
A very similar, but limited API is available, if you want to select from single
- physical tables in order to retrieve TableRecords or even
- UpdatableRecords (see also the manual's section on
-
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:
-
- In the relational data model,
- there are many operations performed on entities, i.e. tables in order to join them together
- before applying predicates, renaming operations and projections. Apart from the convenience
- methods for joining table sources in the
-
- The
In your average application, you will typically have 3-4 SQL queries - that have quite a long list of predicates (and possibly JOINs), such - that you start to lose track over the overall boolean expression that - you're trying to apply.
-In jOOQ, most Conditions can be created and combined almost as
- easily as in SQL itself. The two main participants for creating
- Conditions are the
The above example describes the essence of boolean logic in jOOQ. As - soon as you have a Condition object, you can connect that to other - Conditions, which will then give you a combined condition with exactly - the same properties. There are also convenience methods to create an - EXISTS clause and connect it to an existing condition. In order to - create a new Condition you are going to depart from a Field in most - cases. Here are some important API elements in the Field interface: -
- -As you see in the partially displayed API above, you can compare a
- Field either with other Fields, with constant values (which is a
- shortcut for calling Factory.val(T value)), or with a nested SELECT
- statement. See some more
-
Combining the API of Field and Condition you can express complex predicates like this:
- -Just write:
-A typical example of what you might want to do in SQL is this:
-
- In this example, we are aliasing Tables, calling them a and b.
- The way aliasing works depends on how you generate your meta model
- using jooq-codegen (see the manual's section about
-
Now, if you want to reference any fields from those Tables, you may - not use the original T_BOOK or T_AUTHOR meta-model objects anymore. - Instead, you have to get the fields from the new book and author Table - aliases:
- -- So this is how the above SQL statement would read in jOOQ: -
-There is an interesting, more advanced example of how you can select
- from an aliased nested select in the manual's section about
-
Fields can also be aliased independently from Tables. Most often, - this is done when using functions or aggregate operators. Here is an - example:
-Here is how it's done with jOOQ:
-When you alias Fields like above, you can access those Fields' values using the alias name:
-
- In addition to a list of constant values, the IN operator in
-
Let's say you want to select books by authors born in 1920. Of - course, this is possible with a plain JOIN as well, but let's say we - want to use the IN operator. Then you have two possibilities:
- -The EXISTS operator is rather independent and can stand any place - where there may be a new condition:
-This is reflected by the fact that an EXISTS clause is usually - created directly from the Factory:
- -When you create such a Condition, it can then be connected to any
- other condition using AND, OR operators (see also the manual's section
- on
-
Or in the
Or in the
An example of how to use it is quickly given. Get all authors that haven't written any books:
-If you can ensure that a nested SELECT will only return one Record - with one Field, then you can test for equality. This is how it is done - in SQL:
- -More examples like the above can be guessed from the
-
Often, you need to nest a SELECT statement simply because SQL is - limited in power. For instance, if you want to find out which author - has written the most books, then you cannot do this:
- -Instead, you have to do this (or something similar). For jOOQ, this - is an excellent example, combining various SQL features into a single - statement. Here's how to do it:
- -You'll notice how some verbosity seems inevitable when you combine nested SELECT statements with aliasing.
- -Now SQL is even more powerful than that. You can also have SELECT - statements, wherever you can have Fields. It get's harder and harder - to find good examples, because there is always an easier way to - express the same thing. But why not just count the number of books the - really hard way? :-) But then again, maybe you want to take advantage - of Oracle Scalar Subquery Caching
- -The
-
Hence, this is how you can write a simple UNION with jOOQ:
-In some SQL dialects, you can arbitrarily nest UNIONs to several - levels. Be aware, though, that SQLite, Derby and MySQL have serious - syntax limitations. jOOQ tries to render correct UNION SQL statements, - but unfortunately, you can create situations that will cause syntax - errors in the aforementioned dialects.
- -An example of advanced UNION usage is the following statement in jOOQ:
-This example does not seem surprising, when you have read the
- previous chapters about
-
You can see that jOOQ takes care of many syntax pitfalls, when - you're not used to the various dialects' unique requirements. The - above automatic aliasing was added in order to be compliant with - MySQL's requirements about aliasing nested selects.
- -It is no problem either for you to create SQL statements with several unions. Just write:
-- Strictly speaking, in SQL, you cannot order a subselect that is part - of a UNION operation. You can only order the whole set. In set theory, - or relational algebra, it wouldn't make sense to order subselects - anyway, as a set operation cannot guarantee order correctness. Often, - you still want to do it, because you apply a LIMIT to every subselect. - Let's say, you want to find the employees with the highest salary in - every department in Postgres syntax: -
-There is a subtle difference between the above two queries.
- In SQL, every UNION subselect is in fact a
-
jOOQ allows you to access native functions from your RDBMS. jOOQ - follows two strategies:
-These are just a few functions in the Factory, so you get the idea:
- -Aggregate functions work just like functions, even if they have a - slightly different semantics. Here are some examples from - Factory:
- -A typical example of how to use an aggregate operator is when - generating the next key on insertion of an ID. When you want to - achieve something like this
- -See also the section about
-
Oracle and some other databases support ordered - 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 LISTAGG() (also known as GROUP_CONCAT in other dialects). - The following query groups by authors and concatenates - their books' titles
-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. 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). - - They are accessible from the previously seen AggregateFunction type using - the over() method: -
- -- The full power of your database's vendor-specific extensions can hardly - be obtained outside of the - database itself. Most modern RDBMS support - their own procedural language. With jOOQ, stored procedures are - integrated easily -
- -The main way to interact with your RDBMS's stored procedures and
- functions is by using the generated artefacts. See the manual's
- section about
-
When it comes to DSL, stored functions can be very handy in SQL - statements as well. Every stored function (this also applies to - FUNCTIONS in Oracle PACKAGES) can generate a Field representing a call - to that function. Typically, if you have this type of function in your - database:
- -Then convenience methods like these are generated:
-Let's say, you have a T_PERSON table with persons' names in it, and - you want to know whether there exists an author with precisely that - name, you can reuse the above stored function in a SQL query:
- -The notion of a stored procedure is implemented in most RDBMS by the - fact, that the procedure has no RETURN VALUE (like void in Java), but - it may well have OUT parameters. Since there is not a standard way how - to embed stored procedures in SQL, they cannot be integrated in jOOQ's - DSL either.
-- Your database can do the math for you. Most arithmetic operations are - supported, but also string concatenation can be very efficient if done - already in the database. -
-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: -
-This is not really an arithmetic expression, but it's still an - expression with operators: The string concatenation. jOOQ - provides you with the Field's concat() method:
-The CASE clause is part of the standard SQL syntax. While some RDBMS - also offer an IF clause, or a DECODE function, you can always rely on - the two types of CASE syntax:
- -- In jOOQ, both syntaxes are supported (although, Derby only knows the - first one, which is more general). 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. Please - note that in the above examples, all values were always constants. You - can of course also use Field instead of the various constants. -
-A CASE clause can be used anywhere where you can place a Field. For - instance, you can SELECT the above expression, if you're selecting - from T_AUTHOR:
-Sort indirection is often implemented with a CASE clause of a - SELECT's ORDER BY clause. In SQL, this reads:
- -This will order your authors such that all 'Paulo' come first, then - all 'George' and everyone else last (depending on your RDBMS' handling - of NULL values in sorting). This is a very common task, such that jOOQ - simplifies its use:
-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 (because you created it from a
-
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:
-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 another language (Java in this case), which was - not made for exactly that 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. We have seen many functionalities - where the DSL becomes 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 in these contexts:
-To construct artefacts wrapping plain SQL, you should use any of - these methods from the Factory class:
- -Apart from the general factory methods, plain SQL is useful also 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:
-This section covers some advanced topics and features that don't fit into any other section.
-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 "simulate" 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 in the
-
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, T_LANGUAGE - is a table with 4 rows and at least three columns.
-The general contract (with jOOQ 1.6.2+) is that there must be
-The point of MasterDataTypes in jOOQ is that they behave exactly - like true ENUM types. When the above T_LANGUAGE table is referenced by - T_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 TBookRecord 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 conversion implies that you may want to use a GregorianCalendar for - SQL timestamps, rather than the timestamp type itself. You could then write - a Converter like this: -
- -- Such a Converter can now be used in various places of the jOOQ - API, especially when reading data from the database: -
- -- A more common use-case, however, is to let jOOQ know about custom - types at code generation time. Use the following configuration elements - to specify, that you'd like to use GregorianCalendar for all database - fields that start with DATE_OF_ -
- -- The above configuration will lead to T_AUTHOR.DATE_OF_BIRTH - being generated like this: -
- -
- This means that the bound 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
-
- Read more about advanced code generation configuration in
-
- Java's Enum types can be very useful in SQL too.
- Some databases support enumeration types natively (MySQL, Postgres).
- In other cases, you can use the above custom type configuration
- also to provide jOOQ with Converters for your custom Enum types.
- Instead of implementing
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 T_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 T_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.T_AUTHOR to - something MY_BOOK_WORLD.MY_APP__T_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 you can also hard-wire schema mapping in generated artefacts - at code generation time, e.g. when you have 5 developers with their own - dedicated developer databases, and a common integration database. In the - code generation configuration, you would then write. -
-
- See the manual's section about
-
- The
- 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 - ExecuteListener Javadoc - for more details -
- -- The ExecuteListener API was driven by a feature request by Christopher Deckers, who has - had the courtesy to contribute the jOOQ Console, a sample application interfacing - with jOOQ's ExecuteListeners. The jOOQ Console logs all queries executed by jOOQ and - displays them nicely in a Swing application. With the jOOQ Console's logger, you can: -
-- A short overview of such a debugging session can be seen here: -
-
- - Please note that the jOOQ Console is still experimental. - Any feedback is very welcome on - the jooq-user group -
-- The jOOQ Console can be run in two different modes: -
-
- Both modes will require that you set the
-
- Or when using programmatic settings: -
-- The in-process mode is useful for Swing applications or other, - locally run Java programs accessing the database via jOOQ. - In order to launch the jOOQ Console "in-process", specify the - previously documented settings and launch the Console as follows: -
- -- Only in the in-process mode, you can execute ad-hoc queries directly - from the console, if you provide it with proper DatabaseDescriptor. - These queries are executed from the Editor pane which features: -
-
- - In J2EE or other server/client environments, you may not be able - to run the console in the same process as your application. You - can then run the jOOQ Console in "headless" mode. In addition to - the previously documented settings, you'll have to start a - debugger server in your application process, that the console can - connect to: -
- -- Now start your application along with the debugger server - and launch the console with this command: -
- -- Depending on your distribution, you may have to manually add - rsyntaxtextarea-1.5.0.jar and jOOQ artefacts on your classpath. -
- +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
-If you are closely coupling your application to an Oracle (or CUBRID) database, - you can take advantage of some Oracle-specific features, such as the - CONNECT BY clause, used for hierarchical queries. The formal syntax - definition is as follows:
+This can be done in jOOQ using the .connectBy(Condition) clauses in your SELECT statement:
-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
-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 -
- - -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 importing functionality). You can export any - Result<Record> into any of these formats:
- -Export your results as XML:
-The above query will result in an XML document looking like the following one:
-Export your results as CSV:
-The above query will result in a CSV document looking like the following one:
-Export your results as JSON:
- -The above query will result in a JSON document looking like the following one:
-Export your results as HTML:
-The above query will result in an HTML document looking like the following one:
-Export your results as text:
-The above query will result in a text document looking like the following one:
-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 any of these formats:
+The below CSV data represents two author records that may have been - exported previously, by jOOQ's exporting functionality, and then - modified in Microsoft Excel or any other spreadsheet tool:
+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 will be implemented soon...
-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:
-