jOOQ один запрос с отношением один ко многим

У меня есть эксперимент с таблицей и теги таблицы. Для одного эксперимента может быть много тегов. схема:

--------                  --------
|Table1|  1           n   |Table2|
|      | <--------------> |      |
|      |                  |      |
--------                  --------
(experiment)              (tags)

можно ли создать запрос с помощью jooq, который возвращает эксперименты и соответствующий список тегов. что-то вроде результата, где запись-это experimentRecord и список тегов или карта.

У меня также есть запрос, который возвращает только один результат, есть ли что-то удобное?

EDIT: java8, новейший jooq.

2 ответов


существует много способов материализовать вложенную коллекцию с помощью SQL и / или jOOQ. Я просто просматриваю некоторые из них:

использование joins

если вы не глубоко гнездятся эти коллекции, denormalising (уплощение) ваши результаты с 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())
           ));

теперь вы можете использовать SimpleFlatMapper чтобы сопоставить результат с Tuple2>. Все, что вам нужно сделать, это.

1-Создайте сопоставитель, укажите ключевой столбец, предположив, что это будет id Jdbcmapper mapper = JdbcMapperFactory .метод newinstance() - ... addKeys (эксперимент.ID.getName()) .newMapper(новый TypeReference>>() {});

2-Используйте mapper в результирующем наборе вашего запроса

try (ResultSet rs = DSL.using(configuration)
   .select()
   .from(EXPERIMENT)
   .join(TAGS)
   .on(...)
   .fetchResultSet()) {
    Stream<Tuple2<ExperimentRecord, List<TagRecord>>> stream = mapper.stream(rs);
    ....
}

посмотреть здесь дополнительные подробности