diff --git a/jOOQ-website/src/main/resources/html-util.xsl b/jOOQ-website/src/main/resources/html-util.xsl index b3dc7b8e5b..b6f0b0db71 100644 --- a/jOOQ-website/src/main/resources/html-util.xsl +++ b/jOOQ-website/src/main/resources/html-util.xsl @@ -74,6 +74,13 @@ + + http://docs.oracle.com/javaee/6/api/ + + .html + + + http://download.oracle.com/javase/6/docs/api/ diff --git a/jOOQ-website/src/main/resources/manual-2.5.xml b/jOOQ-website/src/main/resources/manual-2.5.xml index 742c1bebb2..08543a86b9 100644 --- a/jOOQ-website/src/main/resources/manual-2.5.xml +++ b/jOOQ-website/src/main/resources/manual-2.5.xml @@ -1261,7 +1261,7 @@ create.select(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, count())
  • - In most parts of this manual, it is assumed that you do not use the simple SELECT API. + In most parts of this manual, it is assumed that you do not use the simple SELECT API. For more information about the simple SELECT API, see the manual's section about .

    @@ -4486,22 +4486,315 @@ ResultSet fetchResultSet();]]>
    Record vs. TableRecord - + +

    SQL is more expressive than Java

    +

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

    + +

    Fetching strongly or weakly typed records

    +

    + When fetching data only from a single table, the type is known to jOOQ if you use jOOQ's to generate for your database tables. In order to fetch such strongly typed records, you will have to use the : +

    + + + +

    + When you use the method, jOOQ will return the record type supplied with the argument table. Beware though, that you will no longer be able to use any clause that modifies the type of your . This includes: +

    +
      +
    • +
    • +
    • +
    • +
    + +

    Scala's tuple classes

    +

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

    + + extends Tuple { + T1 get1(); void set1(T1 t1); +} + +// Tuple with arity 2 +public interface Tuple2 extends Tuple { + T1 get1(); void set1(T1 t1); + T2 get2(); void set2(T2 t2); +} + +// Tuple with arity 3 +public interface Tuple3 extends Tuple { + T1 get1(); void set1(T1 t1); + T2 get2(); void set2(T2 t2); + T3 get3(); void set3(T3 t3); +} + +// Fictional sample application with Java: +for (Tuple> tuple : create + .select(BOOK.ID, BOOK.TITLE, BOOK.PUBLICATION_DATE) + .from(BOOK) + .orderBy(BOOK.ID) + .fetch()) { + + Integer id = tuple.get1(); + String title = tuple.get2(); + Date publicationDate = tuple.get3(); +} + +// Fictional sample application with Scala: +for (tuple <- create + select (BOOK.ID, BOOK.TITLE, BOOK.PUBLICATION_DATE) + from BOOK + orderBy BOOK.ID + fetch) { + + val id = tuple._1; // Type is Int + val title = tuple._2; // Type is String + val publicationDate = tuple._3; // Type is Date +}]]> + +

    + It is worth mentioning that Scala is much stronger in inferring types than Java. Yet still, this becomes quickly impracticable as +

    +
      +
    • We will run out of pre-defined tuple types for large arities
    • +
    • Tuples are not as expressive as records (named tuples)
    • +
    • With Java's weak type inference (no val/var keywords), tuples quickly become very verbose in Java
    • +
    +

    + For these reasons jOOQ does not support generic tuples. +

    +
    Arrays, Maps and Lists - + +

    Convenience fetch methods to fetch arrays, maps, and lists

    +

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

    + + titles1 = create.select().from(BOOK).fetch().getValues(BOOK.TITLE); +List titles2 = create.select().from(BOOK).fetch(BOOK.TITLE); +String[] titles3 = create.select().from(BOOK).fetchArray(BOOK.TITLE); + +// Fetching only book IDs, converted to Long +List ids1 = create.select().from(BOOK).fetch().getValues(BOOK.ID, Long.class); +List ids2 = create.select().from(BOOK).fetch(BOOK.ID, Long.class); +Long[] ids3 = create.select().from(BOOK).fetchArray(BOOK.ID, Long.class); + +// Fetching book IDs and mapping each ID to their records or titles +Map map1 = create.selectFrom(BOOK).fetch().intoMap(BOOK.ID); +Map map2 = create.selectFrom(BOOK).fetchMap(BOOK.ID); +Map map3 = create.selectFrom(BOOK).fetch().intoMap(BOOK.ID, BOOK.TITLE); +Map map4 = create.selectFrom(BOOK).fetchMap(BOOK.ID, BOOK.TITLE); + +// Group by AUTHOR_ID and list all books written by any author: +Map> group1 = create.selectFrom(BOOK).fetch().intoGroups(BOOK.AUTHOR_ID); +Map> group2 = create.selectFrom(BOOK).fetchGroups(BOOK.AUTHOR_ID); +Map> group3 = create.selectFrom(BOOK).fetch().intoGroups(BOOK.AUTHOR_ID, BOOK.TITLE); +Map> group4 = create.selectFrom(BOOK).fetchGroups(BOOK.AUTHOR_ID, BOOK.TITLE);]]> + +

    + Note that most of these convenience methods are available both through and , some are even available through as well. +

    +
    RecordHandler - + +

    Write callbacks to receive records as input

    +

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

    + +() { + @Override + public void next(BookRecord book) { + Util.doThingsWithBook(book); + } + }); + +// Or more concisely +create.selectFrom(BOOK) + .orderBy(BOOK.ID) + .fetchInto(new RecordHandler() {...}); + +// Or even more concisely with Java 8's lambda expressions: +create.selectFrom(BOOK) + .orderBy(BOOK.ID) + .fetchInto(book -> { Util.doThingsWithBook(book); }; ); +]]> +
    POJOs - + +

    Using POJOs or keeping your DTOs clear of jOOQ dependencies

    +

    + Fetching data in records is fine as long as your application is not really layered, or as long as you're still writing code in the DAO layer. But if you have a more advanced application architecture, you may not want to allow for jOOQ artefacts to leak into other layers. You may choose to write POJOs (Plain Old Java Objects) as your primary DTOs (Data Transfer Objects), without any dependencies on jOOQ's types, which may even potentially hold a reference to a , and thus a JDBC . Like Hibernate/JPA, jOOQ allows you to operate with POJOs. Unlike Hibernate/JPA, jOOQ does not "attach" those POJOs or create proxies with any magic in them. +

    +

    + If you're using jOOQ's , you can configure it to for you, but you're not required to use those generated POJOs. You can use your own. +

    + +

    Using JPA-annotated POJOs

    +

    + jOOQ tries to find JPA annotations on your POJO types. If it finds any, they are used as the primary source for mapping meta-information. Only the annotation is used and understood by jOOQ. An example: +

    + + myBooks = create.select().from(BOOK).fetch().into(MyBook.class); +List myBooks = create.select().from(BOOK).fetchInto(MyBook.class);]]> + +

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

    + +

    Using simple POJOs

    +

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

    + + myBooks = create.select().from(BOOK).fetch().into(MyBook1.class); +List myBooks = create.select().from(BOOK).fetchInto(MyBook1.class); + +// An "immutable" POJO class +public class MyBook2 { + public final int id; + public final String title; + + public MyBook2(int id, String title) { + this.id = id; + this.title = title; + } +} + +// With "immutable" POJO classes, there must be an exact match between projected fields and available constructors: +MyBook2 myBook = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchAny().into(MyBook2.class); +List myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetch().into(MyBook2.class); +List myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchInto(MyBook2.class);]]> + +

    + Please refer to the Javadoc for more details. +

    + +

    Using proxyable types

    +

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

    + + myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetch().into(MyBook3.class); +List myBooks = create.select(BOOK.ID, BOOK.TITLE).from(BOOK).fetchInto(MyBook3.class);]]> + +

    + Please refer to the Javadoc for more details. +

    + +

    Loading POJOs back into Records to store them

    +

    + The above examples show how to fetch data into your own custom POJOs / DTOs. When you have modified the data contained in POJOs, you probably want to store those modifications back to the database. An example of this is given here: +

    + + + +

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

    + +

    Interaction with DAOs

    +

    + If you're using jOOQ's , you can configure it to for you. Those DAOs operate on . An example of using such a DAO is given here: +

    + + + +

    More complex data structures

    +

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

    +
    @@ -5967,6 +6260,26 @@ public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {
    +
    + Generated records + +
    + +
    + Generated POJOs + +
    + +
    + Generated Interfaces + +
    + +
    + Generated POJOs + +
    +
    Generated sequences @@ -6173,6 +6486,7 @@ public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {
  • Hibernate: The de-facto standard (JPA) with its useful table-to-POJO mapping features have influenced jOOQ's facilities
  • JaQu: H2's own fluent API for querying databases
  • JPA: The de-facto standard in the javax.persistence packages, supplied by Oracle. Its annotations are useful to jOOQ as well.
  • +
  • OneWebSQL: A commercial SQL abstraction API with support for DAO source code generation, which was integrated also in jOOQ
  • QueryDSL: A "LINQ-port" to Java. It has a similar fluent API, a similar code-generation facility, yet quite a different purpose. While jOOQ is all about SQL, QueryDSL (like LINQ) is mostly about querying.
  • Spring Data: Spring's JdbcTemplate knows RowMappers, which are reflected by jOOQ's
  • diff --git a/jOOQ-website/src/main/resources/pdf.xsl b/jOOQ-website/src/main/resources/pdf.xsl index 99bb307636..684a27c364 100644 --- a/jOOQ-website/src/main/resources/pdf.xsl +++ b/jOOQ-website/src/main/resources/pdf.xsl @@ -332,7 +332,22 @@ - + + + + url(' + http://docs.oracle.com/javaee/6/api/ + + .html + + ') + + + + + + + url('