hibernateasynchronousreactive-programminghibernate-reactive

Why lazy loading in Hibernate Reactive cannot be transparent?


I was reading the doc of Hibernate Reactive and I encountered this statement:

"In Hibernate Reactive, on the other hand, lazy association fetching is an asynchronous process that produces a result via a CompletionStage (or Uni). Therefore, lazy fetching is an explicit operation ..."

I probably have some lack of knowledge that keep me away from understanding the meaning of the statement. Why the fact that the lazy association fetching is an async process, cause it to not be transparent like in standard Hibernate? What is the challenge or the impediment here?

From the example in the doc:

session.find(Author.class, author.id)
       .chain( author -> Mutiny.fetch(author.books) )
       .invoke( books -> ... ) 

why we have to explicitly chain the fetch method to declare that, at some point, the application may need to load the books from the DB? Standard Hibernate don't need it.

Please, make you answer as less vague than possible. I'd like to deeply understand this problem.

Thank you!


Solution

  • Because in HR, every interaction with the database (including lazy fetching) is asynchronous and so each such operation must return a special object which represents a "future" result.

    The operation of fetching the author.books can't return Set<Book> because that would require synchronously fetching the collection. Instead it must return Uni<Set<Book>>.

    And since we don't have a Uni<Set<Book>> in the domain model (we don't want to pollute the domain model with Uni), we use the fetch() method to map the type Set<Book> to Uni<Set<Book>>.

    UPDATE:

    Note that we could in principle make lazy fetching implicit if we required you to declare all your associations as type Uni. For example:

    @Entity
    class Author {
        @Id
        Long id;
        String name;
        @OneToMany
        Uni<List<Book>> books;
        ...
    }
    
    @Entity
    class Book {
        @Id
        Long id;
        String title;
        @ManyToOne
        Uni<Author> author;
        ...
    }
    

    But, in fact, this isn't transparent at all; it leaks the type Uni into the domain model. That's actually much worse than leaking the fetch() function into code which is already dependent on Hibernate Reactive.

    Because now you would not be able to reuse the domain model with regular Hibernate, nor with any other Java frameworks.

    So we did not go down this path.