liveBook · Manning

Hibernate Reactive

As explained in Quarkus in Action

Hibernate Reactive is a Hibernate library for nonblocking, asynchronous object-relational persistence using reactive database drivers.

Hibernate Reactive provides nonblocking database access for reactive applications using reactive database drivers. Unlike traditional Hibernate ORM and JPA calls, which leave a thread waiting for a database response, persistence operations produce asynchronous results. In Quarkus, those results can be expressed as a JDK CompletionStage or as SmallRye Mutiny’s Uni for one result and Multi for multiple results. This lets a request’s I/O thread serve other work while the database operation completes. section 7.7 section 8.4.1

Hibernate Reactive Panache keeps the familiar entity or repository approach to data access, but methods return types such as Uni<Entity> or Uni<List<Entity>> rather than immediate values. An entity can therefore retain its shape while its Panache import changes to the reactive variant. A reservation service using PostgreSQL also replaces its blocking ORM, JDBC, and REST Data extensions with reactive counterparts and configures a reactive datasource URL. section 7.7.1

Listing 7.33 Replacing blocking ORM extensions with their reactive versions
$ quarkus ext remove quarkus-hibernate-orm-panache quarkus-jdbc-postgresql
 quarkus-hibernate-orm-rest-data-panache
Looking for the newly published extensions in registry.quarkus.io
[SUCCESS] ✅  Extension io.quarkus:quarkus-jdbc-postgresql has been
 uninstalled
[SUCCESS] ✅  Extension io.quarkus:quarkus-hibernate-orm-rest-data-panache
 has been uninstalled
[SUCCESS] ✅  Extension io.quarkus:quarkus-hibernate-orm-panache has been
 uninstalled

$ quarkus ext add quarkus-hibernate-reactive-panache
 quarkus-reactive-pg-client quarkus-hibernate-reactive-rest-data-panache
[SUCCESS] ✅  Extension io.quarkus:quarkus-hibernate-reactive-panache has
 been installed
[SUCCESS] ✅  Extension io.quarkus:quarkus-reactive-pg-client has been
 installed
[SUCCESS] ✅  Extension
 io.quarkus:quarkus-hibernate-reactive-rest-data-panache has been
 installed

The extension commands show the concrete swap from blocking Panache and PostgreSQL JDBC support to Hibernate Reactive Panache, the reactive PostgreSQL client, and reactive REST Data. section 7.7.1

At an HTTP boundary, return Uni from a JAX-RS method so the request can wait for a result without blocking its I/O thread. For a reservation insert, persist() returns a Uni containing the persisted entity; an onItem callback continues processing when that entity arrives. Mark the method @WithTransaction rather than using the nonreactive @Transactional boundary: the transaction commits only after the asynchronous result becomes available. section 7.7.2 section 8.4.1

Keep the whole request path nonblocking

A reservation made for the current day also starts a rental through an HTTP client. Changing only the database call leaves a blocking client call on the reactive path and causes a BlockingNotAllowedException. Make the client return Uni<Rental>, chain that result after persistence, and then return the persisted reservation. To calculate availability, combine the asynchronous inventory and reservation results before removing reserved cars from the inventory map. section 7.7.2

Listing 7.41 Combining the two Uni results in the availability method
@GET
@Path("availability")
public Uni<Collection<Car>> availability(@RestQuery LocalDate startDate,
                                         @RestQuery LocalDate endDate) {
    // obtain all cars from inventory
    Uni<List<Car>> availableCarsUni = inventoryClient.allCars();
    // get all current reservations
    Uni<List<Reservation>> reservationsUni = Reservation.listAll();
    return Uni.combine().all().unis(availableCarsUni, reservationsUni)
        .with((availableCars, reservations) -> {
        // create a map from id to car
        Map<Long, Car> carsById = new HashMap<>();
        for (Car car : availableCars) {
            carsById.put(car.id, car);
        }

        // for each reservation, remove the car from the map
        for (Reservation reservation : reservations) {
            if (reservation.isReserved(startDate, endDate)) {
                carsById.remove(reservation.carId);
            }
        }
        return carsById.values();
    });
}

The availability listing shows Uni.combine().all().unis(...) joining an inventory-client result with a reactive reservation query before calculating available cars. section 7.7.2

Reactive return types alone do not make a service nonblocking. Database I/O through a blocking repository still requires @Blocking, even if the surrounding method returns a reactive type. Tests must also adapt: reactive persistence tests run on a Vert.x context with a TransactionalUniAsserter, and mocked client responses return Uni values. section 8.4.2 section 7.7.2

How Quarkus in Action covers it

How deep it goes
Works through extension replacement, configuration, endpoint changes, transactions, and tests; defers a deeper treatment of reactive programming.
Examples
Uses reservation persistence, rental-client calls, availability queries, extension commands, and reactive persistence tests.
What it assumes
Assumes familiarity with Panache-style data access while introducing Uni and Multi as asynchronous result types before deeper reactive-programming coverage.
What you can do after
Apply it via Quarkus Hibernate Reactive Panache to migrate reservation persistence and keep its HTTP workflow nonblocking.
How it connects
Connects Panache, reactive database drivers, SmallRye Mutiny, JAX-RS, and reactive transactions.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Quarkus in Action. The section links point to the parts of the book it draws on.