An example of stack overflow when get an object using java quarkus reactive panache:
@Table(name = "author")
public class Author extends PanacheEntityBase {
private Long id;
private String authorName;
@OneToMany(fetch = FetchType.LAZY)
private Set<Book> books;
}
---------
@Table(name = "book")
public class Book extends PanacheEntityBase {
private Long id;
private String bookName;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id")
private Author author;
@ManyToMany(fetch = FetchType.LAZY)
private Set<Publisher> publishers;
}
---------
@Table(name = "publisher")
public class Publisher extends PanacheEntityBase {
private Long id;
private String publisherName;
@ManyToMany(fetch = FetchType.LAZY)
@JoinColumn(...)
private Set<Book> books;
}
I do find an author and got error with LazyInitializationException.
return find("authorId", id).firstResult()
.onItem().call(au -> Mutiny.fetch(au.books())); Root cause: Bi-directional relationships between authors and publishers can result in an infinite loop of related entities.
Of course, if I map it to a DTO object with no relationships, the problem is solved. Reffered link: https://github.com/quarkusio/quarkus/issues/23757 The problem is that I want to keep working something with Author, not AuthorDTO...
In your project you have multiple associations:
The first problem is that you are not telling Jackson that the association between Author and Book is bidirectional, this might result in a StackOverflow exception. You can solve it using the annotations
@JsonManagedReferenceand@JsonBackReference:The
LazyInitializationExceptionhappens because you are fetching thebooksassociation, but not thepublishersone. Also, in general, you shouldn't useMutiny.fetchto fetch the associations. The problem with it is that you will end up with a N+1 issue. You can solve the problem using a HQL query:This way you can get everything you need with one query.
I've forked your project and added all the changes needed to make it work quickly in this commit.
I haven't tested it, but mapping the association with publishers as a
SUBSELECTtype, should also work well for this scenario. This way, you just need to fetch the first association (Mutiny.fetch(book.publishers)), and all the publishers for each book are going to be fetched.