Hibernate Reactive is a reactive API for Hibernate ORM, supporting non-blocking database drivers and a reactive style of interaction with the database.

Hibernate Reactive is not a replacement for Hibernate ORM or the future of Hibernate ORM. It is a different stack tailored for reactive use cases where you need high-concurrency.

Also, using Quarkus REST (formerly RESTEasy Reactive), our default REST layer, does not require the use of Hibernate Reactive. It is perfectly valid to use Quarkus REST with Hibernate ORM, and if you do not need high-concurrency, or are not accustomed to the reactive paradigm, it is recommended to use Hibernate ORM.

Hibernate Reactive works with the same annotations and most of the configuration described in the Hibernate ORM guide. This guide will only focus on what’s specific for Hibernate Reactive.

This technology is considered preview.

In preview, backward compatibility and presence in the ecosystem is not guaranteed. Specific improvements might require changing configuration or APIs, and plans to become stable are under way. Feedback is welcome on our mailing list or as issues in our GitHub issue tracker.

For a full list of possible statuses, check our FAQ entry.

Solution

We recommend that you follow the instructions in the next sections and create the application step by step. However, you can go right to the completed example.

Clone the Git repository: git clone $${quickstarts-base-url}.git, or download an $${quickstarts-base-url}/archive/main.zip[archive].

The solution is located in the hibernate-reactive-quickstart directory.

Setting up and configuring Hibernate Reactive

When using Hibernate Reactive in Quarkus, you need to:

  • add your configuration settings in application.properties

  • annotate your entities with @Entity and any other mapping annotations as usual

Other configuration needs have been automated: Quarkus will make some opinionated choices and educated guesses.

Add the following dependencies to your project:

For instance:

pom.xml
<!-- Hibernate Reactive dependency -->
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-hibernate-reactive</artifactId>
</dependency>

<!-- Reactive SQL client for PostgreSQL -->
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-reactive-pg-client</artifactId>
</dependency>
build.gradle
// Hibernate Reactive dependency
implementation("io.quarkus:quarkus-hibernate-reactive")

Reactive SQL client for PostgreSQL
implementation("io.quarkus:quarkus-reactive-pg-client")

Annotate your persistent objects with @Entity, then add the relevant configuration properties in application.properties:

Example application.properties
# datasource configuration
quarkus.datasource.db-kind = postgresql
quarkus.datasource.username = quarkus_test
quarkus.datasource.password = quarkus_test

quarkus.datasource.reactive.url = vertx-reactive:postgresql://localhost/quarkus_test (1)

# drop and create the database at startup (use `update` to only update the schema)
quarkus.hibernate-orm.schema-management.strategy=drop-and-create
1 The only different property from a Hibernate ORM configuration

Note that these configuration properties are not the same ones as in your typical Hibernate Reactive configuration file. They will often map to Hibernate Reactive configuration properties but could have different names and don’t necessarily map 1:1 to each other.

Blocking (non-reactive) and reactive configuration can be mixed together in the same project.

Configuring Hibernate Reactive using the standard persistence.xml configuration file is not supported.

See section Configuration Reference for Hibernate Reactive for the list of properties you can set in application.properties.

A Mutiny.SessionFactory will be created based on the Quarkus datasource configuration as long as the Hibernate Reactive extension is listed among your project dependencies.

The dialect will be selected based on the Reactive SQL client - unless you set one explicitly.

For more information on dialect selection and database versions, see the corresponding section of the Hibernate ORM guide.

You can then happily inject your Mutiny.SessionFactory:

Example application bean using Hibernate Reactive
@ApplicationScoped
public class SantaClausService {
    @Inject
    Mutiny.SessionFactory sf; (1)

    public Uni<Void> createGift(String giftDescription) {
	Gift gift = new Gift();
        gift.setName(giftDescription);
	return sf.withTransaction(session -> session.persist(gift)) (2)
    }
}
1 Inject your session factory and have fun
2 .withTransaction() will automatically flush at commit
Make sure to wrap methods modifying your database (e.g. session.persist(entity)) within a transaction.
Example of an Entity
@Entity
public class Gift {
    private Long id;
    private String name;

    @Id
    @SequenceGenerator(name = "giftSeq", sequenceName = "gift_id_seq", allocationSize = 1, initialValue = 1)
    @GeneratedValue(generator = "giftSeq")
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

To load SQL statements when Hibernate Reactive starts, add an import.sql file in your src/main/resources/ directory. This script can contain any SQL DML statements. Make sure to terminate each statement with a semicolon.

This is useful to have a data set ready for your tests or demos.

Hibernate Reactive configuration properties

There are various optional properties useful to refine your session factory or guide Quarkus' guesses.

When no properties are set, Quarkus can typically infer everything it needs to set up Hibernate Reactive and will have it use the default datasource.

The configuration properties listed here allow you to override such defaults, and customize and tune various aspects.

Hibernate Reactive uses the same properties you would use for Hibernate ORM: see Configuration Reference for Hibernate Reactive.

Hibernate ORM and Reactive extensions simultaneously

If you add both Hibernate ORM and Hibernate Reactive extensions to your Quarkus app, they can be mixed together in the same project.

This is useful if your app normally uses Hibernate ORM (which is blocking), but you want to try Hibernate Reactive to see if it works better for your case.

By adding the second extension, you can use the reactive API in another part of your code - without needing to create a separate app.

Hibernate ORM and Hibernate Reactive won’t share the same persistence context, so it’s recommended you stick to one or the other in a given method. For example use Hibernate ORM in blocking REST endpoints, and use Hibernate Reactive in reactive REST endpoints.
  • To use the both extension simultaneously, add both extension to the pom.xml file:

            <!-- Hibernate reactive -->
            <dependency>
                <groupId>io.quarkus</groupId>
                <artifactId>quarkus-hibernate-reactive</artifactId>
            </dependency>
            <dependency>
                <groupId>io.quarkus</groupId>
                <artifactId>quarkus-reactive-pg-client</artifactId>
            </dependency>
    
            <!-- Hibernate ORM -->
            <dependency>
                <groupId>io.quarkus</groupId>
                <artifactId>quarkus-jdbc-postgresql</artifactId>
            </dependency>
            <dependency>
                <groupId>io.quarkus</groupId>
                <artifactId>quarkus-hibernate-orm</artifactId>
            </dependency>
  • Also update the applications.properties file:

%prod.quarkus.datasource.reactive.url=postgresql:///your_database
%prod.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/hibernate_orm_test
  • The presence of the JDBC driver will enable Hibernate ORM. If you want to disable it, and only use Hibernate Reactive, you can use:

    quarkus.hibernate-orm.blocking=false

Quarkus will set many Hibernate Reactive configuration settings automatically, and will often use more modern defaults.

CDI integration

If you are familiar with using Hibernate Reactive in Quarkus, you probably already have injected the Mutiny.SessionFactory using CDI:

@Inject
Mutiny.SessionFactory sessionFactory;

This will inject the Mutiny.SessionFactory of the default persistence unit.

Prior to Quarkus 3.0 it was also possible to inject a @RequestScoped bean for Mutiny.Session. However, the lifecycle of a reactive session does not fit the lifecycle of the CDI request context. Therefore, this bean is removed in Quarkus 3.0.

Activate/deactivate persistence units

When a persistence unit is configured at build time, and it is assigned entity types or an active datasource, the persistence unit is active by default. Quarkus starts the corresponding Hibernate Reactive SessionFactory when the application starts.

To deactivate a persistence unit at runtime, see the corresponding section of the Hibernate ORM guide.

If you decide to follow the example from the Hibernate ORM guide to declare a custom CDI bean for the active persistence unit, but you use Hibernate Reactive, make sure to work with the Mutiny.SessionFactory type instead of Session: this is one way Hibernate Reactive’s API entrypoint differs from Hibernate ORM’s.

See CDI integration for details.

Automatically transitioning to Flyway to Manage Schemas

Hibernate Reactive can be used in the same application as Flyway. See this section of the Flyway extension documentation for details regarding configuration of Flyway in a reactive application.

If you have the Flyway extension installed when running in development mode, Quarkus provides a simple way to initialize your Flyway configuration using the schema generated automatically by Hibernate Reactive.

See the Hibernate ORM guide for more details.

Testing

Using Hibernate Reactive in a @QuarkusTest is slightly more involved than using Hibernate ORM due to the asynchronous nature of the APIs and the fact that all operations need to run on a Vert.x Event Loop.

Two components are necessary to write these tests:

  • The use of @io.quarkus.test.vertx.RunOnVertxContext or @io.quarkus.test.TestReactiveTransaction on the test methods

  • The use of io.quarkus.test.vertx.UniAsserter as a test method parameter.

These classes are provided by the quarkus-test-vertx dependency.

A very simple example usage looks like:

@QuarkusTest
public class SomeTest {

    @Inject
    Mutiny.SessionFactory sessionFactory;

    @Test
    @RunOnVertxContext
    public void testQuery(UniAsserter asserter) {
        asserter.assertThat(() -> sessionFactory.withSession(s -> s.createQuery(
                "from Gift g where g.name = :name").setParameter("name", "Lego").getResultList()),
                list -> org.junit.jupiter.api.Assertions.assertEquals(list.size(), 1));
    }

}
See the Javadoc of UniAsserter for a full description of the various methods that can be used for creating assertions.

You can also extend the io.quarkus.test.vertx.UniAsserterInterceptor to wrap the injected UniAsserter and customize the default behavior. For example, the interceptor can be used to execute the assert methods within a separate database transaction.:

@QuarkusTest
public class SomeTest {

   @Test
   @RunOnVertxContext
   public void testEntity(UniAsserter asserter) {
      asserter = new UniAsserterInterceptor(asserter) {
         @Override
         protected <T> Supplier<Uni<T>> transformUni(Supplier<Uni<T>> uniSupplier) {
            return () -> Panache.withTransaction(uniSupplier);
         }
      };
      asserter.execute(() -> new MyEntity().persist());
      asserter.assertEquals(() -> MyEntity.count(), 1l);
      asserter.execute(() -> MyEntity.deleteAll());
   }
}

Multiple persistence units

Setting up multiple persistence units

In a similar fashion to Hibernate ORM, Hibernate Reactive supports multiple persistence units.

You can define multiple persistence units and datasources, and they can mix blocking and reactive datasources. To ensure that a datasource supports reactive, you need to set the reactive property to true.

Example application.properties
quarkus.datasource."users".reactive.url=vertx-reactive:postgresql://localhost/users (1)
quarkus.datasource."users".db-kind=postgresql
%prod.quarkus.datasource."users".username=hibernate_orm_test
%prod.quarkus.datasource."users".password=hibernate_orm_test

quarkus.datasource."inventory".reactive.url=vertx-reactive:postgresql://localhost/inventory (2)
quarkus.datasource."inventory".db-kind=postgresql
%prod.quarkus.datasource."inventory".username=hibernate_orm_test
%prod.quarkus.datasource."inventory".password=hibernate_orm_test

quarkus.hibernate-orm."users".datasource=users (3)
quarkus.hibernate-orm."users".packages=io.quarkus.hibernate.reactive.multiplepersistenceunits.model.config.user

quarkus.hibernate-orm."inventory".datasource=inventory (4)
quarkus.hibernate-orm."inventory".packages=io.quarkus.hibernate.orm.multiplepersistenceunits.model.config.inventory
1 Define a reactive datasource named users.
2 Define a reactive datasource named inventory.
3 Define a persistence unit named users and specify the datasource.
4 Define a persistence unit named inventory and specify the datasource.

When using named persistence units, you must set the datasource property to the name of the corresponding datasource.

Limitations and other things you should know

Quarkus does not modify the libraries it uses; this rule applies to Hibernate Reactive as well: when using this extension you will mostly have the same experience as using the original library.

But while they share the same code, Quarkus does configure some components automatically and inject custom implementations for some extension points; this should be transparent and useful but if you’re an expert of Hibernate Reactive you might want to know what is being done.

Here’s a list of things to pay attention when using Hibernate Reactive in Quarkus:

Simplifying Hibernate Reactive with Panache

The Hibernate Reactive with Panache extension facilitates the usage of Hibernate Reactive by providing active record style entities (and repositories) and focuses on making your entities trivial and fun to write in Quarkus.

Validation modes and Hibernate Validator integration

To find out more on how the quarkus.hibernate-orm.validation.mode configuration property. influence your Hibernate Reactive application see the corresponding Hibernate ORM guide, as these modes work the same in both cases.

Configuration Reference for Hibernate Reactive

You will notice that some properties contain "jdbc" in their name: this is because Hibernate ORM refers to its "data access" layer as "JDBC" for historical reasons. Hibernate Reactive uses Vert.x Reactive SQL clients for its data access layer rather than JDBC.

Regardless of their name, these properties still make sense for Hibernate Reactive.