sql >> Database teknologi >  >> RDS >> Mysql

jooq enkelt forespørgsel med et til mange forhold

Der er mange måder at materialisere en indlejret samling med SQL og/eller med jOOQ. Jeg gennemgår lige nogle af dem:

Brug af joinforbindelser

Hvis du ikke indlejrer disse samlinger dybt, denormaliserer (udjævner) dine resultater med en JOIN kan gøre tricket for dig uden at tilføje for meget overhead, da data bliver duplikeret. I det væsentlige vil du skrive:

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

Ovenstående kort indeholder eksperimentposter som nøgler og indlejrede samlinger, der indeholder alle tags som værdier.

Oprettelse af to forespørgsler

Hvis du vil materialisere en kompleks objektgraf, er det måske ikke længere optimalt at bruge joinforbindelser. I stedet ønsker du sandsynligvis at indsamle dataene i din klient fra to forskellige forespørgsler:

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

Og

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

Og flet nu de to resultater i din klients hukommelse, f.eks.

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

Indlejring af samlinger ved hjælp af SQL/XML eller SQL/JSON

Dette spørgsmål krævede det ikke, men andre kan finde dette spørgsmål i deres søgen efter en måde at skabe indlejring til mange forhold med jOOQ på. Jeg har givet et svar her . Fra og med jOOQ 3.14 kan du bruge din RDBMS's SQL/XML- eller SQL/JSON-funktioner og derefter bruge Jackson, Gson eller JAXB til at indlejre samlinger som denne:

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

Hvor Experiment er en tilpasset Java-klasse som denne:

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

class Tag {
  long id;
  String name;
}

Indlejring af samlinger ved hjælp af MULTISET

Endnu bedre end ovenstående, du kan gemme dig ved hjælp af SQL/XML eller SQL/JSON bag jOOQ 3.15's nye MULTISET operatørsupport . Forudsat at ovenstående Java-klasser er Java 16-poster (eller andre uforanderlige klasser), kan du endda kortlægge indlejrede samlingstyper sikkert ind i dine DTO'er:

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

Hvor Experiment er en tilpasset Java-klasse som denne:

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

Se også dette blogindlæg for mere information .



  1. Sådan opdateres fremmednøgleværdi i mysql-database

  2. MYSQL Venstre Deltag i sidste række af resultatet

  3. Opdater del (ordrenummer), der er primær nøgle i Postgres

  4. SQL-snydeark:Hvad er SQL, SQL-kommandoer og SQL-injektion