Go to file
Lukas Eder 6ef4abdbbb [jOOQ/jOOQ#2682] [jOOQ/jOOQ#15632] Support set operations (UNION etc.)
This includes a refactoring where ScopeStackElement is subclassed for specialisation. We need one key per type of ScopeStackElement, such that values can be null for certain keys. That way, the new ScopeDefinerScopeStack element can be absent even if the DataKeyScopeStackElement is present on all scopes. Future refactors might further specialise the DefaultScopeStackElement, which contains the query part specific contents (e.g. join tree)
2023-09-25 16:38:32 +02:00
.github/ISSUE_TEMPLATE Fix "Use case" -> "Possible solution" field name in feature request template 2022-09-24 19:22:44 +03:00
jOOQ [jOOQ/jOOQ#2682] [jOOQ/jOOQ#15632] Support set operations (UNION etc.) 2023-09-25 16:38:32 +02:00
jOOQ-checker Release 3.19.0-SNAPSHOT 2023-03-08 13:41:09 +01:00
jOOQ-codegen [jOOQ/jOOQ#15621] Synthetic comment flag <deprecated> should produce 2023-09-20 11:41:19 +02:00
jOOQ-codegen-gradle [jOOQ/jOOQ#12985] [jOOQ/jOOQ#15400] Use new kotlin DSL 2023-07-13 16:44:01 +02:00
jOOQ-codegen-maven [jOOQ/jOOQ#15065] Include also: 2023-05-12 15:21:23 +02:00
jOOQ-examples Re-generated code 2023-08-23 10:01:08 +02:00
jOOQ-jackson-extensions Release 3.19.0-SNAPSHOT 2023-03-08 13:41:09 +01:00
jOOQ-kotlin [jOOQ/jOOQ#15551] Add runtime UDT mapping 2023-09-06 14:42:12 +02:00
jOOQ-kotlin-coroutines [jOOQ/jOOQ#14997] Use awaitSingle instead of awaitFirstOrNull in transactionCoroutine to correctly sequence transaction script 2023-05-26 15:42:14 +02:00
jOOQ-meta [jOOQ/jOOQ#15623] Stop using deprecated DSL API in jOOQ-meta 2023-09-20 12:05:59 +02:00
jOOQ-meta-extensions Release 3.19.0-SNAPSHOT 2023-03-08 13:41:09 +01:00
jOOQ-meta-extensions-hibernate Release 3.19.0-SNAPSHOT 2023-03-08 13:41:09 +01:00
jOOQ-meta-extensions-liquibase [jOOQ/jOOQ#10096] LiquibaseDatabase should create database.liquibaseSchemaName, if configured 2023-05-12 17:09:54 +02:00
jOOQ-meta-kotlin [jOOQ/jOOQ#3751] Support UDT object names in MatcherStrategy 2023-08-25 16:44:07 +02:00
jOOQ-migrations Bump org.eclipse.jgit:org.eclipse.jgit in /jOOQ-migrations 2023-09-18 19:22:21 +00:00
jOOQ-migrations-maven [jOOQ/jOOQ#9506] Fix wrong package name 2023-06-16 16:45:15 +02:00
jOOQ-postgres-extensions #14995 fix OffsetDateTimeRange javadoc 2023-05-01 12:24:02 -05:00
jOOQ-scala_2.13 Release 3.19.0-SNAPSHOT 2023-03-08 13:41:09 +01:00
jOOQ-xtend Release 3.19.0-SNAPSHOT 2023-03-08 13:41:09 +01:00
.gitignore [jOOQ/jOOQ#11700] Add a jOOQ-r2dbc module (ignore for now) 2021-03-23 09:16:39 +01:00
.travis.yml Travis: use Maven 3.6.2 2019-09-22 13:23:21 -07:00
CONTRIBUTING.md Update CONTRIBUTING.md 2021-02-19 21:00:32 +01:00
LICENSE [jOOQ/jOOQ#14110] License header should use HTTPS rather than HTTP 2022-10-19 10:43:58 +02:00
pom.xml [jOOQ/jOOQ#15610] The egit 6 dependency has a Java 11 baseline 2023-09-20 12:16:47 +02:00
README.md [jOOQ/jOOQ#6542] Re-write the README 2023-06-07 13:12:15 +02:00
SECURITY.md

jOOQ

jOOQ is an internal DSL and source code generator, modelling the SQL language as a type safe Java API to help you write better SQL.

Its main features include:

Secondary features include:

Examples

Typesafe, embedded SQL

jOOQ's main feature is typesafe, embedded SQL, allowing for IDE auto completion of SQL syntax...

image

... as well as of schema meta data:

image

This allows for preventing errors of various types, including typos of identifiers:

image

Or data type mismatches:

image

The examples are from the code generation blog post.

A more powerful example using nested collections

For many more examples, please have a look at the demo. A key example showing jOOQ's various strengths is from the MULTISET operator announcement blog post:

Given these target DTOs:

record Actor(String firstName, String lastName) {}
record Film(
  String title,
  List<Actor> actors,
  List<String> categories
) {}

You can now write the following query to fetch films, their nested actors and their nested categorise in a single, type safe query:

List<Film> result =
dsl.select(
      FILM.TITLE,
      multiset(
        select(
          FILM.actor().FIRST_NAME, 
          FILM.actor().LAST_NAME)
        .from(FILM.actor())
      ).as("actors").convertFrom(r -> r.map(mapping(Actor::new))),
      multiset(
        select(FILM.category().NAME)
        .from(FILM.category())
      ).as("categories").convertFrom(r -> r.map(Record1::value1))
   )
   .from(FILM)
   .orderBy(FILM.TITLE)
   .fetch(mapping(Film::new));

The query is completely type safe. Change a column type, name, or the target DTO, and it will stop compiling! Trust only your own eyes:

multiset

And here you see the nested result in action from the logs:

execute

How does it work? Look at this annotated example:

List<Film> result =
dsl.select(
      FILM.TITLE,

      // MULTISET is a standard SQL operator that allows for nesting collections
      // directly in SQL. It is either
      // - supported natively
      // - emulated using SQL/JSON or SQL/XML
      multiset(

        // Implicit path based joins allow for simpler navigation of foreign
        // key relationships.
        select(
          FILM.actor().FIRST_NAME, 
          FILM.actor().LAST_NAME)

        // Implicit correlation to outer queries allows for avoiding repetitive
        // writing of predicates.
        .from(FILM.actor())

      // Ad-hoc conversion allows for mapping structural Record2<String, String>
      // types to your custom DTO using constructor references
      ).as("actors").convertFrom(r -> r.map(mapping(Actor::new))),
      multiset(
        select(FILM.category().NAME)
        .from(FILM.category())
      ).as("categories").convertFrom(r -> r.map(Record1::value1))
   )
   .from(FILM)
   .orderBy(FILM.TITLE)
   .fetch(mapping(Film::new));

The generated SQL query might look like this, in PostgreSQL:

select
  film.title,
  (
    select coalesce(
      jsonb_agg(jsonb_build_object(
        'first_name', t.first_name,
        'last_name', t.last_name
      )),
      jsonb_build_array()
    )
    from (
      select
        alias_78509018.first_name, 
        alias_78509018.last_name
      from (
        film_actor
          join actor as alias_78509018
            on film_actor.actor_id = alias_78509018.actor_id
        )
      where film_actor.film_id = film.film_id
    ) as t
  ) as actors,
  (
    select coalesce(
      jsonb_agg(jsonb_build_object('name', t.name)),
      jsonb_build_array()
    )
    from (
      select alias_130639425.name
      from (
        film_category
          join category as alias_130639425
            on film_category.category_id = alias_130639425.category_id
        )
      where film_category.film_id = film.film_id
    ) as t
  ) as categories
from film
order by film.title

This particular example is explained more in detail in the MULTISET operator announcement blog post. For many more examples, please have a look at the demo.