sql >> Database >  >> RDS >> Mysql

Een-op-veel selecteren in Jooq

Met behulp van JOIN werkt hier niet voor.

Uw zoekopdracht zal nogal inefficiënt zijn, want als u joins op deze manier gebruikt, maakt u een cartesiaans product tussen de boeken en de artikeltabel, wat resulteert in behoorlijk wat geheugen- en CPU-verbruik, zowel in de database als in uw Java-client, voordat u alle zinloze combinaties dedupliceert.

De "juiste" SQL-aanpak zou zijn om MULTISET zoals beschreven in dit artikel hier . Helaas biedt jOOQ 3.9 geen ondersteuning voor MULTISET nog (noch veel databases). U moet dus twee afzonderlijke zoekopdrachten maken:

  1. Alle boeken ophalen
  2. Alle artikelen ophalen

En gebruik dan iets als Java 8 Streams om ze in een enkel object in kaart te brengen.

Gebruik MULTISET vanaf jOOQ 3.15

Gelukkig is er vanaf jOOQ 3.15 een kant-en-klare oplossing voor het nesten van collecties in SQL met behulp van MULTISET . Uw zoekopdracht ziet er als volgt uit:

Reflectie gebruiken

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

Met gebruik van type safe, ad -hoc conversie

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

Voor meer informatie over MULTISET , raadpleeg deze blogpost , of de handleidingen:

SQL/XML of SQL/JSON gebruiken vanaf jOOQ 3.14

Vanaf jOOQ 3.14 kunt u collecties nesten via SQL/XML of SQL/JSON, als uw RDBMS dat ondersteunt. U kunt een document maken en vervolgens iets als Gson, Jackson of JAXB gebruiken om het terug te koppelen aan uw Java-klassen. Bijvoorbeeld:

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

Merk op dat JSON_ARRAYAGG() voegt lege sets samen tot NULL , niet in een lege [] . Als dat een probleem is, gebruik dan COALESCE()




  1. MySQL SQRT() Functie – Retourneer de vierkantswortel van een getal in MySQL

  2. SELECT DISTINCT ON-query's converteren van Postgresql naar MySQL

  3. Hoe kan ik gegevens uit een versleutelde database lezen met SQLiteAssetHelper?

  4. Hoe de serversortering in MySQL te tonen