I have an application in Spring Boot 3.4.x using Spring Data R2DBC.
Let's say I have two aggregate roots, Book and Author. I understand that from the reactive point of view, it is not possible to work directly with Book#author but Book#authorId, so I fetch them as:
bookRepository.findById(bookId)
.flatMap(book -> authorRepository.findById(book.getAuthorId())
.flatMap(author -> Mono.just(new BookWithAuthor(book, author))));
I have the following wrapper.
record BookWithAuthor(Book book, Author author){}
The issue is that it means two SQL queries. How do I manage it in a single one?
Of course, I may create a DTO object BookAuthorDTO with all properties of Book and Author and modify the repository interface.
@Query("""
SELECT b.*, a.*
FROM book b
JOIN author a ON b.author_id = a.id
WHERE b.id = :bookId
""")
Mono<BookAuthorDto> findDtoById(long bookId);
It is acceptable in this trivial example. But when I have more complicated classes, I do not like that the structure is flat and all properties are mixed together. If I join more aggregate roots, the mapping is even more cumbersome.
I am looking for an elegant solution similar to:
@Query("""
SELECT b.*, a.*
FROM book b
JOIN author a ON b.author_id = a.id
WHERE b.id = :bookId
""")
Mono<Tuple2<Book, Author>> findTupleById(long bookId);
Is it feasible?