JOIN
の使用 これでは機能しません。
この方法で結合を使用している場合は、デカルト積を作成しているため、クエリはかなり非効率になります。 BooksとArticlesテーブルの間で、意味のないすべての組み合わせを重複排除する前に、データベースとJavaクライアントの両方でかなりのメモリとCPUの消費が発生します。
「正しい」SQLアプローチは、 MULTISET
この記事で説明されているように
。残念ながら、jOOQ3.9はMULTISET
をサポートしていません まだ
(多くのデータベースもありません)。したがって、2つの別々のクエリを作成する必要があります:
- すべての本を取得する
- すべての記事を取得する
次に、Java 8 Streamsのようなものを使用して、それらを単一のオブジェクトにマップします。
MULTISET
の使用 jOOQ3.15以降
幸い、jOOQ 3.15以降、MULTISET
を使用してSQLでコレクションをネストするためのすぐに使用できるソリューションがあります。 。クエリは次のようになります:
リフレクションの使用
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);
タイプセーフを使用して、 ad -ホック変換
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));
MULTISET
の詳細 、このブログ投稿を参照してください
、または手動セクション:
jOOQ3.14以降のSQL/XMLまたはSQL/JSONの使用
jOOQ 3.14以降、RDBMSがサポートしている場合は、SQL/XMLまたはSQL/JSONを介してコレクションをネストできます。ドキュメントを作成してから、Gson、Jackson、JAXBなどを使用してJavaクラスにマップし直すことができます。例:
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);
JSON_ARRAYAGG()
に注意してください 空のセットをNULL
に集約します 、空の[]
ではありません 。 それが問題になる場合は、COALESCE()
を使用してください