sql >> Databáze >  >> RDS >> Mysql

Vybrat jeden k mnoha v Jooq

Pomocí JOIN na to nefunguje.

Váš dotaz bude spíše neefektivní, protože pokud používáte spojení tímto způsobem, vytváříte karteziánský produkt mezi knihami a tabulkou článků, což vede ke značné spotřebě paměti a CPU v databázi i ve vašem Java klientovi, než deduplikujete všechny nesmyslné kombinace.

„Správným“ přístupem SQL by bylo použití MULTISET jak je popsáno v tomto článku zde . Bohužel jOOQ 3.9 nepodporuje MULTISET ještě (ani mnoho databází). Měli byste tedy vytvořit dva samostatné dotazy:

  1. Načítání všech knih
  2. Načítání všech článků

A pak použít něco jako Java 8 Streams k jejich mapování do jednoho objektu.

Pomocí MULTISET počínaje jOOQ 3.15

Naštěstí od jOOQ 3.15 existuje hotové řešení pro vnořování kolekcí do SQL pomocí MULTISET . Váš dotaz by vypadal takto:

Použití odrazu

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);

Použití typu safe, reklama -hoc konverze

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));

Další informace o MULTISET , přejděte na tento blogový příspěvek , nebo sekce manuálu:

Použití SQL/XML nebo SQL/JSON počínaje jOOQ 3.14

Počínaje jOOQ 3.14 můžete kolekce vnořovat pomocí SQL/XML nebo SQL/JSON, pokud to vaše RDBMS podporuje. Můžete vytvořit dokument a pak použít něco jako Gson, Jackson nebo JAXB k jeho mapování zpět do vašich tříd Java. Například:

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);

Všimněte si, že JSON_ARRAYAGG() agreguje prázdné sady do NULL , nikoli do prázdného [] . Pokud se jedná o problém, použijte COALESCE()




  1. Srovnání mezi pluginem MySQL Clone a Xtrabackup

  2. Zaseknutý přístup odepřen pro uživatele 'root'@'localhost' - Terminál, Mac

  3. Jak zabránit smazání prvního řádku v tabulce (PostgreSQL)?

  4. INSERT COMMAND ::ERROR:hodnota sloupce neexistuje