Има много начини за материализиране на вложена колекция с SQL и/или с jOOQ. Просто минавам през някои от тях:
Използване на съединения
Ако не вложите дълбоко тези колекции, денормализиране (изравняване) на вашите резултати с JOIN
може да свърши работа вместо вас, без да добавяте твърде много разходи, тъй като данните се дублират. По същество ще напишете:
Map<ExperimentRecord, Result<Record>> map =
DSL.using(configuration)
.select()
.from(EXPERIMENT)
.join(TAGS)
.on(...)
.fetchGroups(EXPERIMENT);
Горната карта съдържа експериментални записи като ключове и вложени колекции, съдържащи всички тагове като стойности.
Създаване на две заявки
Ако искате да материализирате сложна обектна графика, използването на съединения може вече да не е оптимално. Вместо това вероятно искате да съберете данните във вашия клиент от две отделни заявки:
Result<ExperimentRecord> experiments =
DSL.using(configuration)
.selectFrom(EXPERIMENT)
.fetch();
И
Result<TagsRecord> tags =
DSL.using(configuration)
.selectFrom(TAGS)
.where(... restrict to the previous experiments ...)
.fetch();
И сега обединете двата резултата в паметта на вашия клиент, напр.
experiments.stream()
.map(e -> new ExperimentWithTags(
e,
tags.stream()
.filter(t -> e.getId().equals(t.getExperimentId()))
.collect(Collectors.toList())
));
Вложени колекции с помощта на SQL/XML или SQL/JSON
Този въпрос не го изискваше, но други може да открият този въпрос в търсене на начин за вмъкване на много връзки с jOOQ. Дадох отговор тук . Започвайки с jOOQ 3.14, можете да използвате възможностите на вашата RDBMS за SQL/XML или SQL/JSON и след това да използвате Jackson, Gson или JAXB за влагане на колекции по следния начин:
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);
Където Experiment
е персонализиран Java клас като този:
class Experiment {
long id;
String name;
List<Tag> tags;
}
class Tag {
long id;
String name;
}
Влагане на колекции с помощта на MULTISET
Дори по-добре от горното, можете да се скриете с помощта на SQL/XML или SQL/JSON зад новия MULTISET
на jOOQ 3.15 операторска поддръжка
. Ако приемем, че горните класове на Java са записи на Java 16 (или други неизменни класове), можете дори да картографирате безопасно вложени колекции във вашите 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));
Където Experiment
е персонализиран Java клас като този:
record Experiment(long id, String name, List<Tag> tags) {}
record Tag(long id, String name) {}
Вижте също тази публикация в блога за повече информация .