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 .