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

jooq jeden dotaz s jedním až mnoha vztahem

Existuje mnoho způsobů, jak zhmotnit vnořenou kolekci pomocí SQL a / nebo jOOQ. Některé z nich právě procházím:

Použití spojení

Pokud tyto kolekce nevnoříte do hloubky, denormalizujete (srovnáte) své výsledky pomocí JOIN může udělat trik za vás, aniž by přidával příliš mnoho režie, protože data jsou duplikována. V podstatě napíšete:

Map<ExperimentRecord, Result<Record>> map =
DSL.using(configuration)
   .select()
   .from(EXPERIMENT)
   .join(TAGS)
   .on(...)
   .fetchGroups(EXPERIMENT);

Výše uvedená mapa obsahuje záznamy experimentu jako klíče a vnořené kolekce obsahující všechny značky jako hodnoty.

Vytvoření dvou dotazů

Pokud chcete zhmotnit komplexní objektový graf, použití spojení již nemusí být optimální. Místo toho budete pravděpodobně chtít shromáždit data ve svém klientovi ze dvou různých dotazů:

Result<ExperimentRecord> experiments = 
DSL.using(configuration)
   .selectFrom(EXPERIMENT)
   .fetch();

A

Tagy
Result<TagsRecord> tags =
DSL.using(configuration)
   .selectFrom(TAGS)
   .where(... restrict to the previous experiments ...)
   .fetch();
 

A nyní sloučte dva výsledky v paměti vašeho klienta, např.

experiments.stream()
           .map(e -> new ExperimentWithTags(
                e, 
                tags.stream()
                    .filter(t -> e.getId().equals(t.getExperimentId()))
                    .collect(Collectors.toList())
           ));

Vnořování kolekcí pomocí SQL/XML nebo SQL/JSON

Tato otázka to nevyžadovala, ale jiní mohou tuto otázku najít při hledání způsobu, jak vnořit do mnoha vztahů s jOOQ. Poskytl jsem odpověď zde . Počínaje jOOQ 3.14 můžete použít schopnosti vašeho RDBMS SQL/XML nebo SQL/JSON a poté použít Jackson, Gson nebo JAXB k vnoření sbírek takto:

List<Experiment> experiments =
ctx.select(
      EXPERIMENT.asterisk(),
      field(
        select(jsonArrayAgg(jsonObject(TAGS.fields())))
        .from(TAGS)
        .where(TAGS.EXPERIMENT_ID.eq(EXPERIMENT.ID))
      ).as("tags")
    )
   .from(EXPERIMENT)
   .fetchInto(Experiment.class);

Kde Experiment je vlastní třída Java, jako je tato:

class Experiment {
  long id;
  String name;
  List<Tag> tags;
}

class Tag {
  long id;
  String name;
}

Vnořování kolekcí pomocí MULTISET

Ještě lepší než výše uvedené, můžete se skrýt pomocí SQL/XML nebo SQL/JSON za novou MULTISET jOOQ 3.15 podpora operátora . Za předpokladu, že výše uvedené třídy Java jsou záznamy Java 16 (nebo jakékoli jiné neměnné třídy), můžete dokonce bezpečně mapovat vnořené typy kolekcí do svých DTO:

List<Experiment> experiments =
ctx.select(
      EXPERIMENT.ID,
      EXPERIMENT.NAME,
      multiset(
        select(TAGS.ID, TAGS.NAME)
        .from(TAGS)
        .where(TAGS.EXPERIMENT_ID.eq(EXPERIMENT.ID))
      ).as("tags").convertFrom(r -> r.map(Records.mapping(Tag::new)))
    )
   .from(EXPERIMENT)
   .fetch(Records.mapping(Experiment::new));

Kde Experiment je vlastní třída Java, jako je tato:

record Experiment(long id, String name, List<Tag> tags) {}
record Tag(long id, String name) {}

Další informace naleznete také v tomto příspěvku na blogu .



  1. system() vrací -1, errno=10 při přihlášení do Oracle

  2. Vraťte hodnocení z více tabulek pomocí mySQL

  3. Data uložena dvakrát v databázi MySQL. Nevíte, co dělám špatně?

  4. porovnání data a času php