Sử dụng JOIN
không hoạt động cho điều này.
Truy vấn của bạn sẽ khá kém hiệu quả bởi vì nếu bạn đang sử dụng các phép nối theo cách này, bạn đang tạo ra một sản phẩm xe đẩy giữa sách và bảng bài báo, dẫn đến tiêu thụ khá nhiều bộ nhớ và CPU cả trong cơ sở dữ liệu và trong ứng dụng khách Java của bạn, trước khi bạn loại bỏ tất cả các kết hợp vô nghĩa.
Cách tiếp cận SQL "đúng" sẽ là sử dụng MULTISET
như được mô tả trong bài viết này tại đây
. Rất tiếc, jOOQ 3.9 không hỗ trợ MULTISET
chưa
(cũng không có nhiều cơ sở dữ liệu). Vì vậy, bạn nên tạo hai truy vấn riêng biệt:
- Tìm nạp tất cả các sách
- Tìm nạp tất cả các bài báo
Và sau đó sử dụng một thứ gì đó như Java 8 Streams để ánh xạ chúng thành một đối tượng duy nhất.
Sử dụng MULTISET
bắt đầu từ jOOQ 3.15
May mắn thay, bắt đầu từ jOOQ 3.15, có một giải pháp tiện ích để lồng các bộ sưu tập trong SQL bằng cách sử dụng MULTISET
. Truy vấn của bạn sẽ giống như sau:
Sử dụng phản chiếu
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);
Sử dụng loại an toàn, quảng cáo -hoc chuyển đổi
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));
Để biết thêm thông tin về MULTISET
, vui lòng tham khảo bài đăng trên blog này
hoặc các phần thủ công:
Sử dụng SQL / XML hoặc SQL / JSON bắt đầu từ jOOQ 3.14
Bắt đầu từ jOOQ 3.14, bạn có thể lồng các bộ sưu tập qua SQL / XML hoặc SQL / JSON, nếu RDBMS của bạn hỗ trợ điều đó. Bạn có thể tạo một tài liệu, sau đó sử dụng một cái gì đó như Gson, Jackson hoặc JAXB để ánh xạ nó trở lại các lớp Java của bạn. Ví dụ:
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);
Lưu ý rằng JSON_ARRAYAGG()
tổng hợp các tập hợp trống thành NULL
, không vào một []
trống . Nếu đó là sự cố, hãy sử dụng COALESCE()