Det finns många sätt att materialisera en kapslad samling med SQL och/eller med jOOQ. Jag går bara igenom några av dem:
Använda joins
Om du inte kapar in dessa samlingar på djupet, avnormaliserar (planerar) dina resultat med en JOIN
kan göra susen för dig, utan att lägga till för mycket overhead eftersom data dupliceras. I huvudsak kommer du att skriva:
Map<ExperimentRecord, Result<Record>> map =
DSL.using(configuration)
.select()
.from(EXPERIMENT)
.join(TAGS)
.on(...)
.fetchGroups(EXPERIMENT);
Kartan ovan innehåller experimentposter som nycklar och kapslade samlingar som innehåller alla taggar som värden.
Skapar två frågor
Om du vill materialisera en komplex objektgraf kanske det inte längre är optimalt att använda kopplingar. Istället vill du förmodligen samla in data i din klient från två distinkta frågor:
Result<ExperimentRecord> experiments =
DSL.using(configuration)
.selectFrom(EXPERIMENT)
.fetch();
Och
Result<TagsRecord> tags =
DSL.using(configuration)
.selectFrom(TAGS)
.where(... restrict to the previous experiments ...)
.fetch();
Och slå nu samman de två resultaten i din klients minne, t.ex.
experiments.stream()
.map(e -> new ExperimentWithTags(
e,
tags.stream()
.filter(t -> e.getId().equals(t.getExperimentId()))
.collect(Collectors.toList())
));
Inkapsla samlingar med SQL/XML eller SQL/JSON
Den här frågan krävde det inte, men andra kanske hittar den här frågan i jakten på ett sätt att bygga ihop till många relationer med jOOQ. Jag har gett ett svar här . Från och med jOOQ 3.14 kan du använda din RDBMS:s SQL/XML- eller SQL/JSON-funktioner och sedan använda Jackson, Gson eller JAXB för att kapsla samlingar så här:
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);
Där Experiment
är en anpassad Java-klass så här:
class Experiment {
long id;
String name;
List<Tag> tags;
}
class Tag {
long id;
String name;
}
Inkapsla samlingar med MULTISET
Ännu bättre än ovan, du kan gömma dig med SQL/XML eller SQL/JSON bakom jOOQ 3.15s nya MULTISET
operatörssupport
. Förutsatt att ovanstående Java-klasser är Java 16-poster (eller andra oföränderliga klasser), kan du till och med mappa kapslade samlingstyper säkert till dina 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));
Där Experiment
är en anpassad Java-klass så här:
record Experiment(long id, String name, List<Tag> tags) {}
record Tag(long id, String name) {}
Se även detta blogginlägg för mer information .