Menggunakan JOIN
tidak bekerja untuk ini.
Permintaan Anda akan agak tidak efisien karena jika Anda menggunakan gabungan dengan cara ini, Anda membuat produk kartesius antara buku dan tabel artikel, menghasilkan cukup banyak memori dan konsumsi CPU baik di database dan di klien Java Anda, sebelum Anda menghapus duplikat semua kombinasi yang tidak berarti.
Pendekatan SQL yang "benar" adalah dengan menggunakan MULTISET
seperti yang dijelaskan dalam artikel ini di sini
. Sayangnya, jOOQ 3.9 tidak mendukung MULTISET
belum
(juga tidak banyak database). Jadi, Anda harus membuat dua kueri terpisah:
- Mengambil semua buku
- Mengambil semua artikel
Dan kemudian gunakan sesuatu seperti Java 8 Streams untuk memetakannya ke dalam satu objek.
Menggunakan MULTISET
mulai dari jOOQ 3.15
Untungnya, mulai dari jOOQ 3.15, ada solusi out-of-the-box untuk mengumpulkan koleksi di SQL menggunakan MULTISET
. Kueri Anda akan terlihat seperti ini:
Menggunakan refleksi
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);
Menggunakan jenis brankas, iklan konversi -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));
Untuk informasi lebih lanjut tentang MULTISET
, silakan merujuk ke posting blog ini
, atau bagian manual:
Menggunakan SQL/XML atau SQL/JSON mulai dari jOOQ 3.14
Mulai dari jOOQ 3.14, Anda dapat mengumpulkan koleksi melalui SQL/XML atau SQL/JSON, jika RDBMS Anda mendukungnya. Anda dapat membuat dokumen, lalu menggunakan sesuatu seperti Gson, Jackson, atau JAXB untuk memetakannya kembali ke kelas Java Anda. Misalnya:
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);
Perhatikan bahwa JSON_ARRAYAGG()
menggabungkan set kosong menjadi NULL
, bukan menjadi []
empty yang kosong . Jika itu masalah, gunakan COALESCE()