Istnieje wiele sposobów na zmaterializowanie zagnieżdżonej kolekcji za pomocą SQL i/lub jOOQ. Przeglądam tylko niektóre z nich:
Korzystanie z połączeń
Jeśli nie zagnieżdżasz głęboko tych kolekcji, denormalizujesz (spłaszczasz) wyniki za pomocą JOIN
może załatwić sprawę za Ciebie, nie obciążając zbytnio duplikowaniem danych. Zasadniczo napiszesz:
Map<ExperimentRecord, Result<Record>> map =
DSL.using(configuration)
.select()
.from(EXPERIMENT)
.join(TAGS)
.on(...)
.fetchGroups(EXPERIMENT);
Powyższa mapa zawiera rekordy eksperymentu jako klucze i zagnieżdżone kolekcje zawierające wszystkie tagi jako wartości.
Tworzenie dwóch zapytań
Jeśli chcesz zmaterializować złożony graf obiektów, użycie złączeń może nie być już optymalne. Zamiast tego prawdopodobnie chcesz zebrać dane w swoim kliencie z dwóch różnych zapytań:
EksperymentyResult<ExperimentRecord> experiments =
DSL.using(configuration)
.selectFrom(EXPERIMENT)
.fetch();
I
TagiResult<TagsRecord> tags =
DSL.using(configuration)
.selectFrom(TAGS)
.where(... restrict to the previous experiments ...)
.fetch();
A teraz połącz oba wyniki w pamięci klienta, np.
experiments.stream()
.map(e -> new ExperimentWithTags(
e,
tags.stream()
.filter(t -> e.getId().equals(t.getExperimentId()))
.collect(Collectors.toList())
));
Zagnieżdżanie kolekcji przy użyciu SQL/XML lub SQL/JSON
To pytanie nie wymagało tego, ale inni mogą znaleźć to pytanie w poszukiwaniu sposobu na zagnieżdżenie wielu relacji z jOOQ. Podałem odpowiedź tutaj . Począwszy od jOOQ 3.14, możesz użyć możliwości SQL/XML lub SQL/JSON swojego RDBMS, a następnie użyć Jacksona, Gson lub JAXB do zagnieżdżenia kolekcji w następujący sposób:
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);
Gdzie Experiment
to niestandardowa klasa Java, taka jak ta:
class Experiment {
long id;
String name;
List<Tag> tags;
}
class Tag {
long id;
String name;
}
Zagnieżdżanie kolekcji przy użyciu MULTISET
Jeszcze lepsze niż powyższe, możesz ukryć się za pomocą SQL/XML lub SQL/JSON za nowym MULTISET
jOOQ 3.15 wsparcie operatora
. Zakładając, że powyższe klasy Javy są rekordami Javy 16 (lub innymi niezmiennymi klasami), możesz nawet bezpiecznie mapować zagnieżdżone kolekcje typu do swoich 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));
Gdzie Experiment
to niestandardowa klasa Java, taka jak ta:
record Experiment(long id, String name, List<Tag> tags) {}
record Tag(long id, String name) {}
Zobacz także ten wpis na blogu, aby uzyskać więcej informacji .