diff --git a/jOOQ-website/css/jooq.css b/jOOQ-website/css/jooq.css index 5238837efa..309c7d1b3e 100644 --- a/jOOQ-website/css/jooq.css +++ b/jOOQ-website/css/jooq.css @@ -1,5 +1,5 @@ body { - font-family: Verdana,Geneva,Arial,Helvetica,sans-serif; + font-family: 'Lucida Grande',Helvetica,Arial,sans-serif;; font-weight: normal; text-shadow: 0 1px 0 #FFFFFF; font-size: 15px; @@ -33,19 +33,19 @@ h1, h2, h3, h4, h5, h6 { h1 { font-size: 4em; - text-shadow: 0 1px 1px #666666; + text-shadow: 0 1px 1px #444; padding: 0; margin: 0; } h2 { font-size: 2.5em; - text-shadow: 0 1px 1px #666666; + text-shadow: 0 1px 1px #444; } h3 { font-size: 1.3em; - text-shadow: 0 1px 0 #666666; + text-shadow: 0 1px 0 #444; } pre { @@ -72,7 +72,7 @@ p { p.slogan { padding-left: 2em; - color: #888888; + color: #444; font-family: 'Georgia',Serif; font-style: italic; height: 2.5em; @@ -129,19 +129,50 @@ a:hover { background-color: #FFFFFF; margin: 0 auto; position: relative; - width: 980px; + width: 1050px; - padding-top: 1em; - padding-left: 3em; - padding-right: 3em; border-width: 0; border-style: solid; border-color: #882222; - box-shadow: 0 0 20px #aa6633; + box-shadow: 0 0 30px #aa6633; +} + +#content { + padding-top: 1em; + padding-left: 3em; + padding-right: 3em; + + background: #fadccb; + background: -webkit-gradient(linear, left, right, from(#f6cab9), to(#ffeedd)); + background: -moz-linear-gradient(left, #f6cab9, #ffeedd); + background: gradient(linear, left, right, from(#f6cab9), to(#ffeedd)); + } #navigation { + padding-top: 1em; + padding-left: 3em; + padding-right: 3em; + height: 40px; + background: #444; + background: -webkit-gradient(linear, left top, left bottom, from(#555), to(#333)); + background: -moz-linear-gradient(top, #555, #333); + background: gradient(linear, left top, left bottom, from(#555), to(#333)); +} + +#navigation a, +#navigation a:link, +#navigation a:visited, +#navigation a:hover, +#navigation a:active { + color: #ddcccc; + text-decoration: none; + text-shadow: 0 1px 1px #666666; +} + +#navigation a:hover { + text-decoration: underline; } div.navigation-item-left { diff --git a/jOOQ-website/frame.php b/jOOQ-website/frame.php index 45c8fbfad7..e2f2d725a9 100644 --- a/jOOQ-website/frame.php +++ b/jOOQ-website/frame.php @@ -13,25 +13,6 @@
-
-
- -
-
- -
-
-
- -
-
-
- - - - - -
-

jOOQ Logo
- - ' . $slogan . '

'; - } - - printContent(); - ?> - -
-
+
+
+
+ +
+
+ +
+
+
+ +
+
+
+ + + + + +
+

jOOQ Logo
+ + ' . $slogan . '

'; + } + + printContent(); + ?> + +
+
+
diff --git a/jOOQ-website/img/joox-small.png b/jOOQ-website/img/joox-small.png index 732bd28df3..aa255723e4 100644 Binary files a/jOOQ-website/img/joox-small.png and b/jOOQ-website/img/joox-small.png differ diff --git a/jOOQ-website/img/logo.png b/jOOQ-website/img/logo.png index 469bec4463..3c4dfe1eb8 100644 Binary files a/jOOQ-website/img/logo.png and b/jOOQ-website/img/logo.png differ diff --git a/jOOQ-website/manual/DSL/ALIAS/index.php b/jOOQ-website/manual/DSL/ALIAS/index.php index 13dfce7909..aafb3d88e4 100644 --- a/jOOQ-website/manual/DSL/ALIAS/index.php +++ b/jOOQ-website/manual/DSL/ALIAS/index.php @@ -14,7 +14,7 @@ function printContent() { ?> - +
The jOOQ User Manual : DSL or fluent API : Aliased tables and fieldsprevious : nextThe jOOQ User Manual : DSL or fluent API. Where SQL meets Java : Aliased tables and fieldsprevious : next
- +
The jOOQ User Manual : DSL or fluent API : Arithmetic operationsprevious : nextThe jOOQ User Manual : DSL or fluent API. Where SQL meets Java : Arithmetic operationsprevious : next
- +
The jOOQ User Manual : DSL or fluent API : The CASE clauseprevious : nextThe jOOQ User Manual : DSL or fluent API. Where SQL meets Java : The CASE clauseprevious : next
- +
The jOOQ User Manual : DSL or fluent API : Type castingprevious : nextThe jOOQ User Manual : DSL or fluent API. Where SQL meets Java : Type castingprevious : next
- +
The jOOQ User Manual : DSL or fluent API : Conditionsprevious : nextThe jOOQ User Manual : DSL or fluent API. Where SQL meets Java : Conditionsprevious : next
- +
The jOOQ User Manual : DSL or fluent API : Nested select statements using the EXISTS operatorprevious : nextThe jOOQ User Manual : DSL or fluent API. Where SQL meets Java : Nested select statements using the EXISTS operatorprevious : next
- +
The jOOQ User Manual : DSL or fluent API : Functions, aggregate operators, and window functionsprevious : nextThe jOOQ User Manual : DSL or fluent API. Where SQL meets Java : Functions, aggregate operators, and window functionsprevious : next
- +
The jOOQ User Manual : DSL or fluent API : Nested select statements using the IN operatorprevious : nextThe jOOQ User Manual : DSL or fluent API. Where SQL meets Java : Nested select statements using the IN operatorprevious : next
- +
The jOOQ User Manual : DSL or fluent API : Other types of nested selectsprevious : nextThe jOOQ User Manual : DSL or fluent API. Where SQL meets Java : Other types of nested selectsprevious : next
- +
The jOOQ User Manual : DSL or fluent API : Stored procedures and functionsprevious : nextThe jOOQ User Manual : DSL or fluent API. Where SQL meets Java : Stored procedures and functionsprevious : next
- +
The jOOQ User Manual : DSL or fluent API : Complete SELECT syntaxprevious : nextThe jOOQ User Manual : DSL or fluent API. Where SQL meets Java : Complete SELECT syntaxprevious : next
- +
The jOOQ User Manual : DSL or fluent API : When it's just much easier: Plain SQLprevious : nextThe jOOQ User Manual : DSL or fluent API. Where SQL meets Java : When it's just much easier: Plain SQLprevious : next
- +
The jOOQ User Manual : DSL or fluent API : UNION and other set operationsprevious : nextThe jOOQ User Manual : DSL or fluent API. Where SQL meets Java : UNION and other set operationsprevious : next
- +
The jOOQ User Manual : DSL or fluent APIprevious : nextThe jOOQ User Manual : DSL or fluent API. Where SQL meets Javaprevious : next

Table of contents

  1. diff --git a/jOOQ-website/manual/JOOQ/Query/index.php b/jOOQ-website/manual/JOOQ/Query/index.php index 33a026b1b4..442efb6f52 100644 --- a/jOOQ-website/manual/JOOQ/Query/index.php +++ b/jOOQ-website/manual/JOOQ/Query/index.php @@ -4,20 +4,499 @@ // Please do not edit this content manually require '../../../frame.php'; function printH1() { - print "Query and its subtypes"; + print "The Query and its various subtypes"; } function getSlogan() { - return ""; + return " + The Query type hierarchy is what you use to execute queries. It has the + following subtypes for each kind of operation + "; } function printContent() { global $root; ?> - + -
    The jOOQ User Manual : jOOQ classes and their usage : Query and its subtypesprevious : nextThe jOOQ User Manual : jOOQ classes and their usage : The Query and its various subtypesprevious : next
    + +

    SELECT statements

    +

    + There are essentially two ways of creating SELECT statements in jOOQ. + For historical reasons, you can create + org.jooq.SimpleSelectQuery or + org.jooq.SelectQuery + objects and add additional query clauses, such as + Conditions or + SortFields to it. + Since jOOQ 1.3, there is also the possibility to + create SELECT statements using jOOQ's + DSL API in a much more intuitive + and SQL-like way. +

    +

    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:

    + + + +

    Example: SQL query and DSL query

    + + + + + + + + + + + + + + + + +
    A sample SQL statement...and its equivalent in jOOQ's DSL API
    +
    +-- Select all books by authors born after 1920, named "Paulo" 
    +-- from a catalogue consisting of authors and books:
    +
    +
    +SELECT * 
    +  FROM t_author a 
    +  JOIN t_book b 
    +    ON a.id = b.author_id 
    + WHERE a.year_of_birth > 1920 
    +   AND a.first_name = 'Paulo'
    + ORDER BY b.title
    +
    +
    +// Instanciate your factory using a JDBC connection.
    +Factory create = new Factory(connection, SQLDialect.ORACLE);
    +
    +// Execute the query "on a single line"
    +Result<Record> result = create.select()
    +    .from(T_AUTHOR)
    +    .join(T_BOOK)
    +    .on(ID.equal(AUTHOR_ID))
    +    .where(YEAR_OF_BIRTH.greaterThan(1920)
    +    .and(FIRST_NAME.equal("Paulo")))
    +    .orderBy(TITLE).fetch();
    +
    + +

    + In the above example, some generated artefacts are used for querying. + In this case, T_AUTHOR and T_BOOK are instances of types + TAuthor and + TBook respectively. + Their full qualification would read TAuthor.T_AUTHOR and TBook.T_BOOK, but in many cases, + it's useful to static import elements involved with queries, in order to decrease verbosity. +

    + +

    + Apart from the singleton Table instances TAuthor.T_AUTHOR and + TBook.T_BOOK, these generated classes also contain one static member + for every physical field, such as TAuthor.ID or TBook.TAUTHOR_ID, etc. +

    + + + +

    Example: Non-DSL query

    +

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

    +
    +// Re-use the factory to create a SelectQuery. This example will not make use of static imports...
    +SelectQuery q = create.selectQuery();
    +q.addFrom(TAuthor.T_AUTHOR);
    +
    +// This example shows some "mixed" API usage, where the JOIN is added with the standard API, and the 
    +// Condition is created using the DSL API
    +q.addJoin(TBook.T_BOOK, TAuthor.ID.equal(TBook.AUTHOR_ID));
    +
    +// The AND operator between Conditions is implicit here
    +q.addConditions(TAuthor.YEAR_OF_BIRTH.greaterThan(1920));
    +q.addConditions(TAuthor.FIRST_NAME.equal("Paulo"));
    +q.addOrderBy(TBook.TITLE);
    + +

    Fetching data

    +

    + The org.jooq.Select interface extends + org.jooq.ResultQuery, + which provides a range of methods to fetch data from the database. + Once you have constructed your SELECT query (see examples above), you + may choose to either simply execute() it, or use a variety of convenience + fetchXXX() methods. +

    +

    + See the manual's + section on the ResultQuery + for more details. +

    + + +

    INSERT Statements

    +

    jOOQ supports two modes for INSERT statements. + The INSERT VALUES and the INSERT SELECT syntax

    + +

    Example: SQL query and DSL query

    + + + + + + + + + + + + + + + + +
    A typical INSERT query looks like this...and how it's done with jOOQ
    +
    +INSERT INTO T_AUTHOR 
    +    (ID, FIRST_NAME, LAST_NAME)
    +VALUES 
    +    (100, 'Hermann', 'Hesse'),
    +    (101, 'Alfred', 'Döblin');
    + +
    +
    +create.insertInto(T_AUTHOR, 
    +          TAuthor.ID, TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
    +      .values(100, "Hermann", "Hesse")
    +      .values(101, "Alfred", "Döblin")
    +      .execute();
    +
    + +

    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. Some RDBMS support + inserting several records at the same time. This is also supported in + jOOQ, and simulated using INSERT INTO .. SELECT .. UNION ALL SELECT .. + 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.

    + +

    Example: DSL Query, alternative syntax

    +

    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:

    +
    +create.insertInto(T_AUTHOR)
    +      .set(TAuthor.ID, 100)
    +      .set(TAuthor.FIRST_NAME, "Hermann")
    +      .set(TAuthor.LAST_NAME, "Hesse")
    +      .newRecord()
    +      .set(TAuthor.ID, 101)
    +      .set(TAuthor.FIRST_NAME, "Alfred")
    +      .set(TAuthor.LAST_NAME, "Döblin")
    +      .execute();
    +

    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.

    + +

    Example: ON DUPLICATE KEY UPDATE clause

    +

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

    +
    +// Add a new author called "Koontz" with ID 3.
    +// If that ID is already present, update the author's name
    +create.insertInto(T_AUTHOR, TAuthor.ID, TAuthor.LAST_NAME)
    +      .values(3, "Koontz")
    +      .onDuplicateKeyUpdate()
    +      .set(TAuthor.LAST_NAME, "Koontz")
    +      .execute();
    + +

    Example: INSERT .. RETURNING clause

    +

    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 + getGeneratedKeys() + method. Take this example:

    + +
    +// Add another author, with a generated ID
    +Record<?> record =
    +create.insertInto(T_AUTHOR, TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
    +      .values("Charlotte", "Roche")
    +      .returning(TAuthor.ID)
    +      .fetchOne();
    +
    +System.out.println(record.getValue(TAuthor.ID));
    +
    +// For some RDBMS, this also works when inserting several values
    +Result<?> result =
    +create.insertInto(T_AUTHOR, TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
    +      .values("Johann Wolfgang", "von Goethe")
    +      .values("Friedrich", "Schiller")
    +      // You can request any field. Also trigger-generated values
    +      .returning(TAuthor.ID, TAuthor.CREATION_DATE)
    +      .fetch();
    + +

    Example: Non-DSL Query

    +

    You can always use the more verbose regular syntax of the InsertQuery, if you need more control:

    +
    +// Insert a new author into the T_AUTHOR table
    +InsertQuery<TAuthorRecord> i = create.insertQuery(T_AUTHOR);
    +i.addValue(TAuthor.ID, 100);
    +i.addValue(TAuthor.FIRST_NAME, "Hermann");
    +i.addValue(TAuthor.LAST_NAME, "Hesse");
    +
    +i.newRecord();
    +i.addValue(TAuthor.ID, 101);
    +i.addValue(TAuthor.FIRST_NAME, "Alfred");
    +i.addValue(TAuthor.LAST_NAME, "Döblin");
    +i.execute();
    + +

    Example: INSERT Query combined with SELECT statements

    +

    The InsertQuery.addValue() method is overloaded, such that you can + also provide a Field, potentially containing an expression:

    +
    +// Insert a new author into the T_AUTHOR table
    +InsertQuery<TAuthorRecord> i = create.insertQuery(T_AUTHOR);
    +i.addValue(TAuthor.ID, create.select(TAuthor.ID.max().add(1)).from(T_AUTHOR).asField())
    +i.addValue(TAuthor.FIRST_NAME, "Hermann");
    +i.addValue(TAuthor.LAST_NAME, "Hesse");
    +i.execute();
    +

    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

    + +

    Example: INSERT SELECT syntax support

    +

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

    +
    +Insert i = create.insertInto(T_AUTHOR_ARCHIVE,
    +           create.selectFrom(T_AUTHOR).where(TAuthor.DECEASED.equal(1)));
    +i.execute();
    + + +

    UPDATE Statements

    +

    UPDATE statements are only possible on single tables. Support for + multi-table updates will be implemented in the near future.

    + +

    Example: SQL query and DSL query

    + + + + + + + + + + + + + + + + +
    A typical UPDATE query looks like this...and how it's done with jOOQ
    +
    +
    +UPDATE T_AUTHOR
    +   SET FIRST_NAME = 'Hermann',
    +       LAST_NAME = 'Hesse'
    + WHERE ID = 3;
    + +
    +
    +create.update(T_AUTHOR)
    +      .set(TAuthor.FIRST_NAME, "Hermann")
    +      .set(TAuthor.LAST_NAME, "Hesse")
    +      .where(TAuthor.ID.equal(3))
    +      .execute();
    +
    + +

    Example: Non-DSL Query

    +

    Using the org.jooq.UpdateQuery class, + this is how you could express an UPDATE statement:

    +
    +UpdateQuery<TAuthorRecord> u = create.updateQuery(T_AUTHOR);
    +u.addValue(TAuthor.FIRST_NAME, "Hermann");
    +u.addValue(TAuthor.FIRST_NAME, "Hesse");
    +u.addConditions(TAuthor.ID.equal(3));
    +u.execute();
    + + +

    DELETE Statements

    +

    DELETE statements are only possible on single tables. Support for + multi-table deletes will be implemented in the near future.

    + +

    Example: SQL query and DSL query

    + + + + + + + + + + + + + + + + +
    A typical DELETE query looks like this...and how it's done with jOOQ
    +
    +
    +DELETE T_AUTHOR
    + WHERE ID = 100;
    + +
    +
    +create.delete(T_AUTHOR)
    +      .where(TAuthor.ID.equal(100))
    +      .execute();
    +
    + +

    Example: Non-DSL Query

    +

    Using the org.jooq.DeleteQuery class, + this is how you could express a DELETE statement:

    +
    +DeleteQuery<TAuthorRecord> d = create.deleteQuery(T_AUTHOR);
    +d.addConditions(TAuthor.ID.equal(100));
    +d.execute();
    + + +

    MERGE Statement

    +

    + 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. H2's MERGE variant is currently not supported.) +

    +

    + 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. Those non-standard extensions are currently + not supported. Here is an example: +

    + + + + + + + + + + +
    +
    +-- Check if there is already an author called 'Hitchcock'
    +-- If there is, rename him to John. If there isn't add him.
    +
    +MERGE INTO T_AUTHOR
    +USING (SELECT 1 FROM DUAL)
    +ON (LAST_NAME = 'Hitchcock')
    +WHEN MATCHED THEN UPDATE SET FIRST_NAME = 'John'
    +WHEN NOT MATCHED THEN INSERT (LAST_NAME) VALUES ('Hitchcock')
    + +
    +
    +create.mergeInto(T_AUTHOR)
    +      .using(create().selectOne())
    +      .on(TAuthor.LAST_NAME.equal("Hitchcock"))
    +      .whenMatchedThenUpdate()
    +      .set(TAuthor.FIRST_NAME, "John")
    +      .whenNotMatchedThenInsert(TAuthor.LAST_NAME)
    +      .values("Hitchcock")
    +      .execute();
    +
    + + +

    TRUNCATE Statement

    +

    + The syntax is trivial: +

    + + + + + + + + + +
    +
    TRUNCATE TABLE T_AUTHOR;
    + +
    +
    create.truncate(T_AUTHOR).execute();
    +
    +

    This is not supported by Ingres and SQLite. jOOQ will execute a DELETE FROM + T_AUTHOR statement instead.

    + - diff --git a/jOOQ-website/manual/JOOQ/ResultQuery/index.php b/jOOQ-website/manual/JOOQ/ResultQuery/index.php index c5b33a7fb3..e33b62f17a 100644 --- a/jOOQ-website/manual/JOOQ/ResultQuery/index.php +++ b/jOOQ-website/manual/JOOQ/ResultQuery/index.php @@ -14,7 +14,7 @@ function printContent() { ?> - +
    The jOOQ User Manual : jOOQ classes and their usage : ResultQuery and various ways of fetching dataprevious : nextThe jOOQ User Manual : jOOQ classes and their usage : ResultQuery and various ways of fetching dataprevious : next

    See some details about how to create these queries in the - Query section of the manual + Query section of the manual

    TableFields

    diff --git a/jOOQ-website/manual/JOOQ/UpdatableRecord/index.php b/jOOQ-website/manual/JOOQ/UpdatableRecord/index.php index bd207b97fa..64383fc944 100644 --- a/jOOQ-website/manual/JOOQ/UpdatableRecord/index.php +++ b/jOOQ-website/manual/JOOQ/UpdatableRecord/index.php @@ -7,17 +7,88 @@ function printH1() { print "Updatable Records"; } function getSlogan() { - return ""; + return " + UpdatableRecords are a specific subtype of TableRecord that have + primary key information associated with them. + "; } function printContent() { global $root; ?> - + -
    The jOOQ User Manual : jOOQ classes and their usage : Updatable Recordsprevious : nextThe jOOQ User Manual : jOOQ classes and their usage : Updatable Recordsprevious : next
    + +

    CRUD Operations

    +

    As of jOOQ 1.5, the UpdatableRecord essentially contains three additional + methods CRUD + (Create Read Update Delete) operations:

    +
    +// Store any changes made to this record to the database.
    +// The record executes an INSERT if the PRIMARY KEY is NULL or has been changed. Otherwise, an UPDATE is performed.
    +int store();
    +
    +// Deletes the record from the database.
    +int delete();
    +
    +// Reflects changes made in the database to this Record
    +void refresh();
    +

    An example lifecycle of a book can be implemented as such:

    +
    +// Create a new record and insert it into the database
    +TBookRecord book = create.newRecord(T_BOOK);
    +book.setTitle("My first book");
    +book.store();
    +
    +// Update it with new values
    +book.setPublishedIn(2010);
    +book.store();
    +
    +// Delete it
    +book.delete();
    +

    These operations are very simple utilities. They do not + reflect the functionality offered by Hibernate + or other persistence managers.

    + +

    Performing CRUD on non-updatable records

    +

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

    + +
    +// INSERT or UPDATE the record using the provided keys
    +int storeUsing(TableField<R, ?>... keys)
    +
    +// DELETE a record using the provided keys
    +int deleteUsing(TableField<R, ?>... keys);
    +
    +// Reflects changes made in the database to this Record
    +void refreshUsing(TableField<R, ?>... keys);
    + +

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

    +
    +// Create a new record and insert it into the database
    +TBookRecord book = create.newRecord(T_BOOK);
    +book.setTitle("My first book");
    +book.storeUsing(TBook.ID);
    +
    +// Update it with new values
    +book.setPublishedIn(2010);
    +book.storeUsing(TBook.ID);
    +
    +// Delete it
    +book.deleteUsing(TBook.ID);
    + - diff --git a/jOOQ-website/manual/JOOQ/index.php b/jOOQ-website/manual/JOOQ/index.php index e731cf7987..33f36370be 100644 --- a/jOOQ-website/manual/JOOQ/index.php +++ b/jOOQ-website/manual/JOOQ/index.php @@ -39,7 +39,7 @@ function printContent() {

    This section is about the main jOOQ classes and the global architecture. Most of the time, however, you will be using the - DSL or fluent API + DSL or fluent API. Where SQL meets Java in order to create queries the way you're used to in SQL

    @@ -60,7 +60,7 @@ function printContent() { Updatable Records
  2. -Query and its subtypes +The Query and its various subtypes
  3. ResultQuery and various ways of fetching data diff --git a/jOOQ-website/manual/META/SEQUENCE/index.php b/jOOQ-website/manual/META/SEQUENCE/index.php index 73e317652a..86d8a08f78 100644 --- a/jOOQ-website/manual/META/SEQUENCE/index.php +++ b/jOOQ-website/manual/META/SEQUENCE/index.php @@ -14,7 +14,7 @@ function printContent() { ?> - +
    The jOOQ User Manual : Meta model code generation : Sequencesprevious : nextThe jOOQ User Manual : Meta model code generation : Sequencesprevious : next
    -DSL or fluent API +DSL or fluent API. Where SQL meets Java

    See these chapters to learn about how to use jOOQ in every day's work. The @@ -99,7 +99,7 @@ function printContent() { Updatable Records

  4. -Query and its subtypes +The Query and its various subtypes
  5. ResultQuery and various ways of fetching data @@ -139,7 +139,7 @@ function printContent() {
  • -DSL or fluent API +DSL or fluent API. Where SQL meets Java
    1. Complete SELECT syntax diff --git a/jOOQ-website/src/main/resources/html-pages.xsl b/jOOQ-website/src/main/resources/html-pages.xsl index 6d4fd97421..7337576d06 100644 --- a/jOOQ-website/src/main/resources/html-pages.xsl +++ b/jOOQ-website/src/main/resources/html-pages.xsl @@ -187,6 +187,7 @@ function printContent() { + @@ -196,16 +197,25 @@ function printContent() { + + https://github.com/lukaseder/jOOQ/blob/master/jOOQ-test/src/ + + .java + + + https://github.com/lukaseder/jOOQ/blob/master/jOOQ/src/main/java/ .java + http://download.oracle.com/javase/6/docs/api/ .html + diff --git a/jOOQ-website/src/main/resources/manual.xml b/jOOQ-website/src/main/resources/manual.xml index fe46b2661f..ab1a4f2e59 100644 --- a/jOOQ-website/src/main/resources/manual.xml +++ b/jOOQ-website/src/main/resources/manual.xml @@ -478,10 +478,495 @@ BigDecimal getValueAsBigDecimal(int fieldIndex);
      Updatable Records + + UpdatableRecords are a specific subtype of TableRecord that have + primary key information associated with them. + + +

      CRUD Operations

      +

      As of jOOQ 1.5, the UpdatableRecord essentially contains three additional + methods CRUD + (Create Read Update Delete) operations:

      +
      +// Store any changes made to this record to the database.
      +// The record executes an INSERT if the PRIMARY KEY is NULL or has been changed. Otherwise, an UPDATE is performed.
      +int store();
      +
      +// Deletes the record from the database.
      +int delete();
      +
      +// Reflects changes made in the database to this Record
      +void refresh();
      +

      An example lifecycle of a book can be implemented as such:

      +
      +// Create a new record and insert it into the database
      +TBookRecord book = create.newRecord(T_BOOK);
      +book.setTitle("My first book");
      +book.store();
      +
      +// Update it with new values
      +book.setPublishedIn(2010);
      +book.store();
      +
      +// Delete it
      +book.delete();
      +

      These operations are very simple utilities. They do not + reflect the functionality offered by Hibernate + or other persistence managers.

      + +

      Performing CRUD on non-updatable records

      +

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

      + +
      +// INSERT or UPDATE the record using the provided keys
      +int storeUsing(TableField<R, ?>... keys)
      +
      +// DELETE a record using the provided keys
      +int deleteUsing(TableField<R, ?>... keys);
      +
      +// Reflects changes made in the database to this Record
      +void refreshUsing(TableField<R, ?>... keys);
      + +

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

      +
      +// Create a new record and insert it into the database
      +TBookRecord book = create.newRecord(T_BOOK);
      +book.setTitle("My first book");
      +book.storeUsing(TBook.ID);
      +
      +// Update it with new values
      +book.setPublishedIn(2010);
      +book.storeUsing(TBook.ID);
      +
      +// Delete it
      +book.deleteUsing(TBook.ID);
      +
      + +
      - Query and its subtypes + The Query and its various subtypes + + The Query type hierarchy is what you use to execute queries. It has the + following subtypes for each kind of operation + + +

      SELECT statements

      +

      + There are essentially two ways of creating SELECT statements in jOOQ. + For historical reasons, you can create + or + + objects and add additional query clauses, such as + or + to it. + Since jOOQ 1.3, there is also the possibility to + create SELECT statements using jOOQ's + in a much more intuitive + and SQL-like way. +

      +

      Use the DSL API when:

      +
        +
      • You want your code to look like SQL
      • +
      • You want your IDE to help you with auto-completion (you will not be able to write select .. order by .. where .. join or any of that stuff)
      • +
      +

      Use the regular API when:

      +
        +
      • You want to create your query step-by-step, creating query parts one-by-one
      • +
      • You need to assemble your query from various places, passing the query around, adding new conditions and joins on the way
      • +
      +

      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:

      + +
        +
      • : + This Query subtype stands for a general type of SELECT statement. + It is also the main Select type for the + . When executed, this object + will hold a . + This type is further subtyped for the various uses of a SELECT statement as such:
      • +
      • : + This Query will allow for selecting from single physical Tables only. + It therefore has access to the Table's generic type parameter + <R extends Record> and will provide a matching Result<R>. + This is especially useful if <R> is a subtype of + . + Then you will be able to perform updates on your result set immediately.
      • +
      • : + This Query will allow for selecting a subset of Fields from several + Tables. Because the results of such a query are considered of an anonymous + or ad-hoc type, this Query will bind <R> to the general type Record + itself. The purpose of this Query type is to allow for full SQL support, + including SELECT, JOIN and GROUP BY clauses.
      • +
      + +

      Example: SQL query and DSL query

      + + + + + + + + + +
      A sample SQL statement...and its equivalent in jOOQ's DSL API
      +-- Select all books by authors born after 1920, named "Paulo" 
      +-- from a catalogue consisting of authors and books:
      +
      +
      +SELECT * 
      +  FROM t_author a 
      +  JOIN t_book b 
      +    ON a.id = b.author_id 
      + WHERE a.year_of_birth > 1920 
      +   AND a.first_name = 'Paulo'
      + ORDER BY b.title
      +// Instanciate your factory using a JDBC connection.
      +Factory create = new Factory(connection, SQLDialect.ORACLE);
      +
      +// Execute the query "on a single line"
      +Result<Record> result = create.select()
      +    .from(T_AUTHOR)
      +    .join(T_BOOK)
      +    .on(ID.equal(AUTHOR_ID))
      +    .where(YEAR_OF_BIRTH.greaterThan(1920)
      +    .and(FIRST_NAME.equal("Paulo")))
      +    .orderBy(TITLE).fetch();
      + +

      + In the above example, some generated artefacts are used for querying. + In this case, T_AUTHOR and T_BOOK are instances of types + and + respectively. + Their full qualification would read TAuthor.T_AUTHOR and TBook.T_BOOK, but in many cases, + it's useful to static import elements involved with queries, in order to decrease verbosity. +

      + +

      + Apart from the singleton Table instances TAuthor.T_AUTHOR and + TBook.T_BOOK, these generated classes also contain one static member + for every physical field, such as TAuthor.ID or TBook.TAUTHOR_ID, etc. +

      + +
        +
      • For more information about code generation, check out the manual's section about + .
      • +
      • For more DSL examples, please consider the manual's section about the + .
      • +
      + +

      Example: Non-DSL query

      +

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

      +
      +// Re-use the factory to create a SelectQuery. This example will not make use of static imports...
      +SelectQuery q = create.selectQuery();
      +q.addFrom(TAuthor.T_AUTHOR);
      +
      +// This example shows some "mixed" API usage, where the JOIN is added with the standard API, and the 
      +// Condition is created using the DSL API
      +q.addJoin(TBook.T_BOOK, TAuthor.ID.equal(TBook.AUTHOR_ID));
      +
      +// The AND operator between Conditions is implicit here
      +q.addConditions(TAuthor.YEAR_OF_BIRTH.greaterThan(1920));
      +q.addConditions(TAuthor.FIRST_NAME.equal("Paulo"));
      +q.addOrderBy(TBook.TITLE);
      + +

      Fetching data

      +

      + The interface extends + , + which provides a range of methods to fetch data from the database. + Once you have constructed your SELECT query (see examples above), you + may choose to either simply execute() it, or use a variety of convenience + fetchXXX() methods. +

      +

      + See the manual's + + for more details. +

      + + +

      INSERT Statements

      +

      jOOQ supports two modes for INSERT statements. + The INSERT VALUES and the INSERT SELECT syntax

      + +

      Example: SQL query and DSL query

      + + + + + + + + + +
      A typical INSERT query looks like this...and how it's done with jOOQ
      +INSERT INTO T_AUTHOR 
      +    (ID, FIRST_NAME, LAST_NAME)
      +VALUES 
      +    (100, 'Hermann', 'Hesse'),
      +    (101, 'Alfred', 'Döblin');
      +
      +create.insertInto(T_AUTHOR, 
      +          TAuthor.ID, TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
      +      .values(100, "Hermann", "Hesse")
      +      .values(101, "Alfred", "Döblin")
      +      .execute();
      + +

      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. Some RDBMS support + inserting several records at the same time. This is also supported in + jOOQ, and simulated using INSERT INTO .. SELECT .. UNION ALL SELECT .. + 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.

      + +

      Example: DSL Query, alternative syntax

      +

      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:

      +
      +create.insertInto(T_AUTHOR)
      +      .set(TAuthor.ID, 100)
      +      .set(TAuthor.FIRST_NAME, "Hermann")
      +      .set(TAuthor.LAST_NAME, "Hesse")
      +      .newRecord()
      +      .set(TAuthor.ID, 101)
      +      .set(TAuthor.FIRST_NAME, "Alfred")
      +      .set(TAuthor.LAST_NAME, "Döblin")
      +      .execute();
      +

      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.

      + +

      Example: ON DUPLICATE KEY UPDATE clause

      +

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

      +
      +// Add a new author called "Koontz" with ID 3.
      +// If that ID is already present, update the author's name
      +create.insertInto(T_AUTHOR, TAuthor.ID, TAuthor.LAST_NAME)
      +      .values(3, "Koontz")
      +      .onDuplicateKeyUpdate()
      +      .set(TAuthor.LAST_NAME, "Koontz")
      +      .execute();
      + +

      Example: INSERT .. RETURNING clause

      +

      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 + + method. Take this example:

      + +
      +// Add another author, with a generated ID
      +Record<?> record =
      +create.insertInto(T_AUTHOR, TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
      +      .values("Charlotte", "Roche")
      +      .returning(TAuthor.ID)
      +      .fetchOne();
      +
      +System.out.println(record.getValue(TAuthor.ID));
      +
      +// For some RDBMS, this also works when inserting several values
      +Result<?> result =
      +create.insertInto(T_AUTHOR, TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
      +      .values("Johann Wolfgang", "von Goethe")
      +      .values("Friedrich", "Schiller")
      +      // You can request any field. Also trigger-generated values
      +      .returning(TAuthor.ID, TAuthor.CREATION_DATE)
      +      .fetch();
      + +

      Example: Non-DSL Query

      +

      You can always use the more verbose regular syntax of the InsertQuery, if you need more control:

      +
      +// Insert a new author into the T_AUTHOR table
      +InsertQuery<TAuthorRecord> i = create.insertQuery(T_AUTHOR);
      +i.addValue(TAuthor.ID, 100);
      +i.addValue(TAuthor.FIRST_NAME, "Hermann");
      +i.addValue(TAuthor.LAST_NAME, "Hesse");
      +
      +i.newRecord();
      +i.addValue(TAuthor.ID, 101);
      +i.addValue(TAuthor.FIRST_NAME, "Alfred");
      +i.addValue(TAuthor.LAST_NAME, "Döblin");
      +i.execute();
      + +

      Example: INSERT Query combined with SELECT statements

      +

      The InsertQuery.addValue() method is overloaded, such that you can + also provide a Field, potentially containing an expression:

      +
      +// Insert a new author into the T_AUTHOR table
      +InsertQuery<TAuthorRecord> i = create.insertQuery(T_AUTHOR);
      +i.addValue(TAuthor.ID, create.select(TAuthor.ID.max().add(1)).from(T_AUTHOR).asField())
      +i.addValue(TAuthor.FIRST_NAME, "Hermann");
      +i.addValue(TAuthor.LAST_NAME, "Hesse");
      +i.execute();
      +

      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

      + +

      Example: INSERT SELECT syntax support

      +

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

      +
      +Insert i = create.insertInto(T_AUTHOR_ARCHIVE,
      +           create.selectFrom(T_AUTHOR).where(TAuthor.DECEASED.equal(1)));
      +i.execute();
      + + +

      UPDATE Statements

      +

      UPDATE statements are only possible on single tables. Support for + multi-table updates will be implemented in the near future.

      + +

      Example: SQL query and DSL query

      + + + + + + + + + +
      A typical UPDATE query looks like this...and how it's done with jOOQ
      +
      +UPDATE T_AUTHOR
      +   SET FIRST_NAME = 'Hermann',
      +       LAST_NAME = 'Hesse'
      + WHERE ID = 3;
      +
      +create.update(T_AUTHOR)
      +      .set(TAuthor.FIRST_NAME, "Hermann")
      +      .set(TAuthor.LAST_NAME, "Hesse")
      +      .where(TAuthor.ID.equal(3))
      +      .execute();
      + +

      Example: Non-DSL Query

      +

      Using the class, + this is how you could express an UPDATE statement:

      +
      +UpdateQuery<TAuthorRecord> u = create.updateQuery(T_AUTHOR);
      +u.addValue(TAuthor.FIRST_NAME, "Hermann");
      +u.addValue(TAuthor.FIRST_NAME, "Hesse");
      +u.addConditions(TAuthor.ID.equal(3));
      +u.execute();
      + + +

      DELETE Statements

      +

      DELETE statements are only possible on single tables. Support for + multi-table deletes will be implemented in the near future.

      + +

      Example: SQL query and DSL query

      + + + + + + + + + +
      A typical DELETE query looks like this...and how it's done with jOOQ
      +
      +DELETE T_AUTHOR
      + WHERE ID = 100;
      +
      +create.delete(T_AUTHOR)
      +      .where(TAuthor.ID.equal(100))
      +      .execute();
      + +

      Example: Non-DSL Query

      +

      Using the class, + this is how you could express a DELETE statement:

      +
      +DeleteQuery<TAuthorRecord> d = create.deleteQuery(T_AUTHOR);
      +d.addConditions(TAuthor.ID.equal(100));
      +d.execute();
      + + +

      MERGE Statement

      +

      + 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. H2's MERGE variant is currently not supported.) +

      +

      + 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. Those non-standard extensions are currently + not supported. Here is an example: +

      + + + + + + +
      +-- Check if there is already an author called 'Hitchcock'
      +-- If there is, rename him to John. If there isn't add him.
      +
      +MERGE INTO T_AUTHOR
      +USING (SELECT 1 FROM DUAL)
      +ON (LAST_NAME = 'Hitchcock')
      +WHEN MATCHED THEN UPDATE SET FIRST_NAME = 'John'
      +WHEN NOT MATCHED THEN INSERT (LAST_NAME) VALUES ('Hitchcock')
      +
      +create.mergeInto(T_AUTHOR)
      +      .using(create().selectOne())
      +      .on(TAuthor.LAST_NAME.equal("Hitchcock"))
      +      .whenMatchedThenUpdate()
      +      .set(TAuthor.FIRST_NAME, "John")
      +      .whenNotMatchedThenInsert(TAuthor.LAST_NAME)
      +      .values("Hitchcock")
      +      .execute();
      + + +

      TRUNCATE Statement

      +

      + The syntax is trivial: +

      + + + + + +
      TRUNCATE TABLE T_AUTHOR;
      +
      create.truncate(T_AUTHOR).execute();
      +

      This is not supported by Ingres and SQLite. jOOQ will execute a DELETE FROM + T_AUTHOR statement instead.

      +
      + + +
      ResultQuery and various ways of fetching data
      @@ -520,7 +1005,7 @@ BigDecimal getValueAsBigDecimal(int fieldIndex);
      - DSL or fluent API + DSL or fluent API. Where SQL meets Java
      Complete SELECT syntax