Korzystanie z JOIN
nie działa na to.
Twoje zapytanie będzie raczej nieefektywne, ponieważ jeśli używasz złączeń w ten sposób, tworzysz produkt kartezjański między książkami a tabelą artykułów, co skutkuje sporym zużyciem pamięci i procesora zarówno w bazie danych, jak i w kliencie Java, zanim usuniesz wszystkie bezsensowne kombinacje.
„Właściwym” podejściem SQL byłoby użycie MULTISET
jak opisano w tym artykule tutaj
. Niestety, jOOQ 3.9 nie obsługuje MULTISET
jeszcze
(ani wiele baz danych). Powinieneś więc utworzyć dwa oddzielne zapytania:
- Pobieranie wszystkich książek
- Pobieranie wszystkich artykułów
A następnie użyj czegoś takiego jak Java 8 Streams, aby zmapować je w pojedynczy obiekt.
Korzystanie z MULTISET
począwszy od jOOQ 3.15
Na szczęście, począwszy od jOOQ 3.15, istnieje gotowe rozwiązanie do zagnieżdżania kolekcji w SQL przy użyciu MULTISET
. Twoje zapytanie wyglądałoby tak:
Korzystanie z odbicia
List<Author> authors =
ctx.select(
AUTHOR.ID,
AUTHOR.NAME,
multiset(
select(BOOKS.TITLE)
.from(BOOKS)
.where(BOOKS.AUTHOR_ID.eq(AUTHOR.ID))
).as("books"),
multiset(
select(ARTICLES.TITLE)
.from(ARTICLES)
.where(ARTICLES.AUTHOR_ID.eq(AUTHOR.ID))
).as("articles")
)
.from(AUTHOR)
.where(AUTHOR.ID.eq(id))
.fetchInto(Author.class);
Korzystając z sejfu typu, reklama konwersja -hoc
List<Author> authors =
ctx.select(
AUTHOR.ID,
AUTHOR.NAME,
multiset(
select(BOOKS.TITLE)
.from(BOOKS)
.where(BOOKS.AUTHOR_ID.eq(AUTHOR.ID))
).as("books").convertFrom(r -> r.map(Record1::value1)),
multiset(
select(ARTICLES.TITLE)
.from(ARTICLES)
.where(ARTICLES.AUTHOR_ID.eq(AUTHOR.ID))
).as("articles").convertFrom(r -> r.map(Record1::value1))
)
.from(AUTHOR)
.where(AUTHOR.ID.eq(id))
.fetch(Records.mapping(Author::new));
Więcej informacji o MULTISET
, zapoznaj się z tym wpisem na blogu
lub sekcje podręcznika:
Korzystanie z SQL/XML lub SQL/JSON od jOOQ 3.14
Począwszy od jOOQ 3.14, możesz zagnieżdżać kolekcje za pomocą SQL/XML lub SQL/JSON, jeśli Twój RDBMS to obsługuje. Możesz stworzyć dokument, a następnie użyć czegoś takiego jak Gson, Jackson lub JAXB, aby zmapować go z powrotem do swoich klas Java. Na przykład:
List<Author> authors =
ctx.select(
AUTHOR.ID,
AUTHOR.NAME,
field(
select(jsonArrayAgg(BOOKS.TITLE))
.from(BOOKS)
.where(BOOKS.AUTHOR_ID.eq(AUTHOR.ID))
).as("books"),
field(
select(jsonArrayAgg(ARTICLES.TITLE))
.from(ARTICLES)
.where(ARTICLES.AUTHOR_ID.eq(AUTHOR.ID))
).as("articles")
)
.from(AUTHOR)
.where(AUTHOR.ID.eq(id))
.fetchInto(Author.class);
Zauważ, że JSON_ARRAYAGG()
agreguje puste zestawy w NULL
, a nie w pusty []
. Jeśli to jest problem, użyj COALESCE()