sql >> Databasteknik >  >> RDS >> Mysql

En-till-många välj i Jooq

Med JOIN fungerar inte för detta.

Din fråga kommer att vara ganska ineffektiv eftersom om du använder joins på det här sättet skapar du en kartesisk produkt mellan böckerna och artikeltabellen, vilket resulterar i en hel del minnes- och CPU-förbrukning både i databasen och i din Java-klient, innan du deduplicerar alla meningslösa kombinationer.

Den "korrekta" SQL-metoden skulle vara att använda MULTISET som beskrivs i den här artikeln här . Tyvärr har jOOQ 3.9 inte stöd för MULTISET ännu (inte många databaser). Så du bör skapa två separata frågor:

  1. Hämtar alla böcker
  2. Hämtar alla artiklar

Och använd sedan något som Java 8 Streams för att mappa dem till ett enda objekt.

Med MULTISET från och med jOOQ 3.15

Lyckligtvis, från och med jOOQ 3.15, finns det en färdig lösning för att kapsla samlingar i SQL med MULTISET . Din fråga skulle se ut så här:

Använda reflektion

List<Author> authors =
ctx.select(
      AUTHOR.ID,
      AUTHOR.NAME,
      multiset(
        select(BOOKS.TITLE)
        .from(BOOKS)
        .where(BOOKS.AUTHOR_ID.eq(AUTHOR.ID))
      ).as("books"),
      multiset(
        select(ARTICLES.TITLE)
        .from(ARTICLES)
        .where(ARTICLES.AUTHOR_ID.eq(AUTHOR.ID))
      ).as("articles")
    )
   .from(AUTHOR)
   .where(AUTHOR.ID.eq(id))
   .fetchInto(Author.class);

Använd typ säker, annons -hoc-konvertering

List<Author> authors =
ctx.select(
      AUTHOR.ID,
      AUTHOR.NAME,
      multiset(
        select(BOOKS.TITLE)
        .from(BOOKS)
        .where(BOOKS.AUTHOR_ID.eq(AUTHOR.ID))
      ).as("books").convertFrom(r -> r.map(Record1::value1)),
      multiset(
        select(ARTICLES.TITLE)
        .from(ARTICLES)
        .where(ARTICLES.AUTHOR_ID.eq(AUTHOR.ID))
      ).as("articles").convertFrom(r -> r.map(Record1::value1))
    )
   .from(AUTHOR)
   .where(AUTHOR.ID.eq(id))
   .fetch(Records.mapping(Author::new));

För mer information om MULTISET , se detta blogginlägg , eller de manuella avsnitten:

Använder SQL/XML eller SQL/JSON från och med jOOQ 3.14

Från och med jOOQ 3.14 kan du kapsla samlingar via SQL/XML eller SQL/JSON, om din RDBMS stödjer det. Du kan skapa ett dokument och sedan använda något som Gson, Jackson eller JAXB för att mappa tillbaka det till dina Java-klasser. Till exempel:

List<Author> authors =
ctx.select(
      AUTHOR.ID,
      AUTHOR.NAME,
      field(
        select(jsonArrayAgg(BOOKS.TITLE))
        .from(BOOKS)
        .where(BOOKS.AUTHOR_ID.eq(AUTHOR.ID))
      ).as("books"),
      field(
        select(jsonArrayAgg(ARTICLES.TITLE))
        .from(ARTICLES)
        .where(ARTICLES.AUTHOR_ID.eq(AUTHOR.ID))
      ).as("articles")
    )
   .from(AUTHOR)
   .where(AUTHOR.ID.eq(id))
   .fetchInto(Author.class);

Observera att JSON_ARRAYAGG() aggregerar tomma uppsättningar till NULL , inte i en tom [] . Om det är ett problem, använd COALESCE()




  1. Hur Tand() fungerar i PostgreSQL

  2. Vanlig användare med SYSBACKUP-behörighet

  3. SQLite ALTER TABELL

  4. Importera stor CSV-fil till MySQL