Classi c SQL стратегии для вложения коллекций
В вашем простом примере, LEFT JOIN
, безусловно, вариант. Это то, что ORM, такие как JPA / Hibernate, делают также негласно, когда они выбирают вложенные коллекции. Стратегия имеет ряд недостатков:
- Есть дублирование данных. Для каждого
BAR
(дочерняя таблица) вы будете дублировать данные соответствующего FOO
(родительская таблица). Это может привести к большим накладным расходам на передачу по проводам. Это становится все хуже и хуже, чем больше соединений (т.е. больше вложений) вам требуется - Есть декартовы произведения. Вы не можете вкладывать более одной коллекции, не производя декартовы произведения между дочерними таблицами, если вы хотите сделать это за один go. С декартовым произведением будет трудно «запомнить», какие комбинации на самом деле являются законными, а какие являются артефактами вашего дерева соединений. Итак, вы вернетесь к выполнению нескольких запросов, по одному для каждой ветви дерева вложений
Использование стандартного SQL JSON
Но вот, есть лучший способ, начиная из jOOQ 3.14. Вы можете использовать XML или JSON, в зависимости от используемого вами диалекта базы данных. Ключевыми функциями здесь являются XMLAGG
и JSON_ARRAYAGG
, которые позволяют объединять данные в элемент XML или объект JSON. Поскольку вы собираетесь создавать JSON документы с GraphQL, я думаю, вы будете использовать JSON.
Используя стандарт SQL (например, как реализовано Oracle), ваш сгенерированный SQL запрос для вашего примера может выглядеть следующим образом:
SELECT
JSON_ARRAYAGG(
JSON_OBJECT(
KEY "id" VALUE foo.id,
KEY "name" VALUE foo.name,
KEY "bars" VALUE (
SELECT
JSON_ARRAYAGG(
JSON_OBJECT(
KEY "id" VALUE bar.id,
KEY "name" VALUE bar.name
)
)
FROM bar
WHERE bar.foo_id = foo.id
)
)
)
FROM foo
В нынешнем виде эти диалекты должны поддерживать jsonArrayAgg()
и jsonObject()
(или его эмуляция, например, в PostgreSQL):
- CockroachDB
- Db2 LUW 11 +
- H2
- MariaDB 10.2 +
- MySQL 5.7 +
- Oracle 12c +
- PostgreSQL
Эмуляция в SQL Сервер с использованием FOR JSON
может быть возможно и в будущем.
Решение «из коробки»
На самом деле, мне приходило в голову раньше, чтобы обеспечить это из коробка. Мы могли бы сделать это в ближайшее время: https://github.com/jOOQ/jOOQ/issues/10122