Hibernate Reactive

Example#1

Product.java

package zjc.examples.vertx.hibernate;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.math.BigDecimal;

@Entity
public class Product {

  @Id
  @GeneratedValue
  private Long id;

  @Column(unique = true)
  private String name;

  @Column(nullable = false)
  private BigDecimal price;

  public Product() {
  }

  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;
  }

  public BigDecimal getPrice() {
    return price;
  }

  public void setPrice(BigDecimal price) {
    this.price = price;
  }
}

MainVerticle.java

package zjc.examples.vertx.hibernate;

import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.vertx.core.AbstractVerticle;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.json.JsonObject;
import io.vertx.mutiny.core.Vertx;
import io.vertx.mutiny.core.http.HttpServer;
import io.vertx.mutiny.ext.web.Router;
import io.vertx.mutiny.ext.web.RoutingContext;
import io.vertx.mutiny.ext.web.handler.BodyHandler;
import org.hibernate.reactive.mutiny.Mutiny;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.PostgreSQLContainer;

import javax.persistence.Persistence;
import java.util.List;
import java.util.Map;

// tag::preamble[]
public class MainVerticle extends AbstractVerticle {

  private static final Logger logger = LoggerFactory.getLogger(MainVerticle.class);
  private Mutiny.SessionFactory emf;  // <1>D

  @Override
  public Uni<Void> asyncStart() {
// end::preamble[]

    // tag::hr-start[]
    Uni<Void> startHibernate = Uni.createFrom().deferred(() -> {
      var pgPort = config().getInteger("pgPort", 5432);
      var props = Map.of("javax.persistence.jdbc.url", "jdbc:postgresql://localhost:" + pgPort + "/postgres");  // <1>

      emf = Persistence
        .createEntityManagerFactory("pg-demo", props)
        .unwrap(Mutiny.SessionFactory.class);

      return Uni.createFrom().voidItem();
    });

    startHibernate = vertx.executeBlocking(startHibernate)  // <2>
      .onItem().invoke(() -> logger.info("✅ Hibernate Reactive is ready"));
    // end::hr-start[]

    // tag::routing[]
    Router router = Router.router(vertx);

    BodyHandler bodyHandler = BodyHandler.create();
    router.post().handler(bodyHandler::handle);

    router.get("/products").respond(this::listProducts);
    router.get("/products/:id").respond(this::getProduct);
    router.post("/products").respond(this::createProduct);
    // end::routing[]

    // tag::async-start[]
    Uni<HttpServer> startHttpServer = vertx.createHttpServer()
      .requestHandler(router)
      .listen(8080)
      .onItem().invoke(() -> logger.info("✅ HTTP server listening on port 8080"));

    return Uni.combine().all().unis(startHibernate, startHttpServer).discardItems();  // <1>
    // end::async-start[]
  }

  // tag::crud-methods[]
  private Uni<List<Product>> listProducts(RoutingContext ctx) {
    return emf.withSession(session -> session
      .createQuery("from Product", Product.class)
      .getResultList());
  }

  private Uni<Product> getProduct(RoutingContext ctx) {
    long id = Long.parseLong(ctx.pathParam("id"));
    return emf.withSession(session -> session
      .find(Product.class, id))
      .onItem().ifNull().continueWith(Product::new);
  }

  private Uni<Product> createProduct(RoutingContext ctx) {
    Product product = ctx.body().asPojo(Product.class);
    return emf.withSession(session -> session.
      persist(product)
      .call(session::flush)
      .replaceWith(product));
  }
  // end::crud-methods[]

  public static void main(String[] args) {

    long startTime = System.currentTimeMillis();

    logger.info("🚀 Starting a PostgreSQL container");

    // tag::tc-start[]
    PostgreSQLContainer<?> postgreSQLContainer = new PostgreSQLContainer<>("postgres:11-alpine")
      .withDatabaseName("postgres")
      .withUsername("postgres")
      .withPassword("vertx-in-action");

    postgreSQLContainer.start();
    // end::tc-start[]

    long tcTime = System.currentTimeMillis();

    logger.info("🚀 Starting Vert.x");

    // tag::vertx-start[]
    Vertx vertx = Vertx.vertx();

    DeploymentOptions options = new DeploymentOptions().setConfig(new JsonObject()
      .put("pgPort", postgreSQLContainer.getMappedPort(5432))); // <1>

    vertx.deployVerticle(MainVerticle::new, options).subscribe().with(  // <2>
      ok -> {
        long vertxTime = System.currentTimeMillis();
        logger.info("✅ Deployment success");
        logger.info("💡 PostgreSQL container started in {}ms", (tcTime - startTime));
        logger.info("💡 Vert.x app started in {}ms", (vertxTime - tcTime));
      },
      err -> logger.error("🔥 Deployment failure", err));
    // end::vertx-start[]
  }
}

Complete code: http://jreact.com/index.php/2023/12/12/vertx-hibernate-example-01/

Example#2

  • Vert.x
  • PostgreSQL
  • Hibernate reactive
  • REST
  • Flyway

Running

mvn compile exec:java

[INFO] Scanning for projects...
[INFO] 
[INFO] --------------< zjc.examples:vertx-hibernate-example-02 >---------------
[INFO] Building vertx-hibernate-example-02 1.0.0-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- resources:3.3.1:resources (default-resources) @ vertx-hibernate-example-02 ---
[INFO] Copying 4 resources from src/main/resources to target/classes
[INFO] 
[INFO] --- compiler:3.10.1:compile (default-compile) @ vertx-hibernate-example-02 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 7 source files to /home/zbyszek/IdeaProjects/reactive/github/zjc-examples/vertx/hibernate/vertx-hibernate-example-02/target/classes
[INFO] /home/zbyszek/IdeaProjects/reactive/github/zjc-examples/vertx/hibernate/vertx-hibernate-example-02/src/main/java/zjc/examples/vertx/hibernate/utils/DbUtils.java: /home/zbyszek/IdeaProjects/reactive/github/zjc-examples/vertx/hibernate/vertx-hibernate-example-02/src/main/java/zjc/examples/vertx/hibernate/utils/DbUtils.java uses or overrides a deprecated API.
[INFO] /home/zbyszek/IdeaProjects/reactive/github/zjc-examples/vertx/hibernate/vertx-hibernate-example-02/src/main/java/zjc/examples/vertx/hibernate/utils/DbUtils.java: Recompile with -Xlint:deprecation for details.
[INFO] 
[INFO] --- exec:3.0.0:java (default-cli) @ vertx-hibernate-example-02 ---
2023-12-14 16:21:26,827 INFO [zjc.examples.vertx.hibernate.MainVerticle.main()] zjc.examples.vertx.hibernate.MainVerticle - 🚀 Starting a PostgreSQL
2023-12-14 16:21:27,038 INFO [zjc.examples.vertx.hibernate.MainVerticle.main()] zjc.examples.vertx.hibernate.MainVerticle - 🚀 Starting Vert.x
2023-12-14 16:21:27,121 INFO [vert.x-eventloop-thread-0] org.flywaydb.core.internal.license.VersionPrinter - Flyway Community Edition 9.0.2 by Redgate
2023-12-14 16:21:27,121 INFO [vert.x-eventloop-thread-0] org.flywaydb.core.internal.license.VersionPrinter - See what's new here: https://flywaydb.org/documentation/learnmore/releaseNotes#9.0.2
2023-12-14 16:21:27,121 INFO [vert.x-eventloop-thread-0] org.flywaydb.core.internal.license.VersionPrinter - 
2023-12-14 16:21:27,123 DEBUG [vert.x-eventloop-thread-0] org.flywaydb.core.internal.util.FeatureDetector - AWS SDK available: false
2023-12-14 16:21:27,123 DEBUG [vert.x-eventloop-thread-0] org.flywaydb.core.internal.util.FeatureDetector - Google Cloud Storage available: false
2023-12-14 16:21:27,124 DEBUG [vert.x-eventloop-thread-0] o.f.c.internal.scanner.classpath.ClassPathScanner - Multiple databases found that handle url 'jdbc:postgresql://localhost:5432/vertx-rest': CockroachDB, PostgreSQL
2023-12-14 16:21:27,124 DEBUG [vert.x-eventloop-thread-0] o.f.c.internal.scanner.classpath.ClassPathScanner - Scanning for classpath resources at 'classpath:db/callback' ...
2023-12-14 16:21:27,124 DEBUG [vert.x-eventloop-thread-0] o.f.c.internal.scanner.classpath.ClassPathScanner - Determining location urls for classpath:db/callback using ClassLoader java.net.URLClassLoader@537ca28e ...
2023-12-14 16:21:27,124 DEBUG [vert.x-eventloop-thread-0] o.f.c.internal.scanner.classpath.ClassPathScanner - Unable to resolve location classpath:db/callback.
2023-12-14 16:21:27,124 DEBUG [vert.x-eventloop-thread-0] o.f.c.internal.scanner.classpath.ClassPathScanner - Scanning for classpath resources at 'classpath:db/migration' ...
2023-12-14 16:21:27,124 DEBUG [vert.x-eventloop-thread-0] o.f.c.internal.scanner.classpath.ClassPathScanner - Determining location urls for classpath:db/migration using ClassLoader java.net.URLClassLoader@537ca28e ...
2023-12-14 16:21:27,125 DEBUG [vert.x-eventloop-thread-0] o.f.c.internal.scanner.classpath.ClassPathScanner - Scanning URL: file:/home/zbyszek/IdeaProjects/reactive/github/zjc-examples/vertx/hibernate/vertx-hibernate-example-02/target/classes/db/migration
2023-12-14 16:21:27,125 DEBUG [vert.x-eventloop-thread-0] org.flywaydb.core.internal.util.FeatureDetector - JBoss VFS v2 available: false
2023-12-14 16:21:27,126 DEBUG [vert.x-eventloop-thread-0] o.f.c.i.s.c.FileSystemClassPathLocationScanner - Scanning starting at classpath root in filesystem: /home/zbyszek/IdeaProjects/reactive/github/zjc-examples/vertx/hibernate/vertx-hibernate-example-02/target/classes/
2023-12-14 16:21:27,126 DEBUG [vert.x-eventloop-thread-0] o.f.c.i.s.c.FileSystemClassPathLocationScanner - Scanning for resources in path: /home/zbyszek/IdeaProjects/reactive/github/zjc-examples/vertx/hibernate/vertx-hibernate-example-02/target/classes/db/migration (db/migration)
2023-12-14 16:21:27,128 DEBUG [vert.x-eventloop-thread-0] o.f.c.internal.scanner.classpath.ClassPathScanner - Found resource: db/migration/V0.1__create_product_table.sql
2023-12-14 16:21:27,128 DEBUG [vert.x-eventloop-thread-0] o.f.c.internal.scanner.classpath.ClassPathScanner - Scanning for classes at classpath:db/migration
2023-12-14 16:21:27,132 DEBUG [vert.x-eventloop-thread-0] o.f.core.internal.resource.ResourceNameValidator - Validating V0.1__create_product_table.sql
2023-12-14 16:21:27,222 INFO [vert.x-eventloop-thread-0] zjc.examples.vertx.hibernate.MainVerticle - ✅ HTTP server listening on port 8080
2023-12-14 16:21:27,266 INFO [vert.x-worker-thread-0] org.hibernate.jpa.internal.util.LogHelper - HHH000204: Processing PersistenceUnitInfo [name: pg-demo]
2023-12-14 16:21:27,322 INFO [vert.x-worker-thread-0] org.hibernate.Version - HHH000412: Hibernate ORM core version 5.6.12.Final
2023-12-14 16:21:27,507 INFO [vert.x-worker-thread-0] org.hibernate.annotations.common.Version - HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2023-12-14 16:21:27,571 INFO [vert.x-eventloop-thread-0] o.f.core.internal.database.base.BaseDatabaseType - Database: jdbc:postgresql://localhost:5432/vertx-rest (PostgreSQL 14.9)
2023-12-14 16:21:27,572 DEBUG [vert.x-eventloop-thread-0] o.f.core.internal.database.base.BaseDatabaseType - Driver  : PostgreSQL JDBC Driver 42.2.18
2023-12-14 16:21:27,575 DEBUG [vert.x-eventloop-thread-0] org.flywaydb.core.FlywayExecutor - DDL Transactions Supported: true
2023-12-14 16:21:27,577 DEBUG [vert.x-eventloop-thread-0] o.f.c.internal.schemahistory.SchemaHistoryFactory - Schemas: 
2023-12-14 16:21:27,577 DEBUG [vert.x-eventloop-thread-0] o.f.c.internal.schemahistory.SchemaHistoryFactory - Default schema: null
2023-12-14 16:21:27,589 DEBUG [vert.x-eventloop-thread-0] o.f.c.internal.callback.SqlScriptCallbackFactory - Scanning for SQL callbacks ...
2023-12-14 16:21:27,598 DEBUG [vert.x-eventloop-thread-0] org.flywaydb.core.internal.command.DbValidate - Validating migrations ...
2023-12-14 16:21:27,611 DEBUG [vert.x-eventloop-thread-0] org.flywaydb.core.internal.scanner.Scanner - Filtering out resource: db/migration/V0.1__create_product_table.sql (filename: V0.1__create_product_table.sql)
2023-12-14 16:21:27,637 DEBUG [vert.x-eventloop-thread-0] org.flywaydb.core.FlywayExecutor - Memory usage: 73 of 138M
2023-12-14 16:21:27,681 INFO [vert.x-worker-thread-0] org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.PostgreSQL10Dialect
2023-12-14 16:21:27,910 INFO [vert.x-worker-thread-0] o.h.reactive.provider.impl.ReactiveIntegrator - HR000001: Hibernate Reactive
2023-12-14 16:21:28,299 INFO [vert.x-worker-thread-0] o.h.reactive.pool.impl.DefaultSqlClientPool - HR000011: SQL Client URL [jdbc:postgresql://localhost:5432/vertx-rest]
2023-12-14 16:21:28,304 INFO [vert.x-worker-thread-0] o.h.r.pool.impl.DefaultSqlClientPoolConfiguration - HR000025: Connection pool size: 10
[Hibernate] 
    select
        * 
    from
        information_schema.sequences
[Hibernate] 
    select
        table_catalog as table_cat ,
        table_schema as table_schem ,
        table_name as table_name ,
        table_type as table_type ,
        null as remarks 
    from
        information_schema.tables 
    where
        1 = 1 
        and table_name like $1 
        and table_type in (
            $2, $3, $4, $5 
        ) 
[Hibernate] 
    select
        table_name as table_name,
        column_name as column_name,
        case 
            when udt_name = 'bpchar' then 'CHAR' 
            else udt_name 
        end as type_name,
        null as column_size,
        null as decimal_digits,
        is_nullable as is_nullable,
        null as data_type 
    from
        information_schema.columns 
    where
        1 = 1 
    order by
        table_catalog,
        table_schema,
        table_name,
        column_name,
        ordinal_position
2023-12-14 16:21:28,655 INFO [vert.x-eventloop-thread-0] zjc.examples.vertx.hibernate.MainVerticle - ✅ Hibernate Reactive is ready
2023-12-14 16:21:28,657 INFO [vert.x-eventloop-thread-1] zjc.examples.vertx.hibernate.MainVerticle - ✅ Deployment success
2023-12-14 16:21:28,657 INFO [vert.x-eventloop-thread-1] zjc.examples.vertx.hibernate.MainVerticle - 💡 PostgreSQL started in 211ms
2023-12-14 16:21:28,657 INFO [vert.x-eventloop-thread-1] zjc.examples.vertx.hibernate.MainVerticle - 💡 Vert.x app started in 1619ms

Complete code: http://jreact.com/index.php/2023/12/14/vertx-hibernate-example-02/

Example#3

  • Vert.x
  • io.vertx.mutiny.ext.web.Router
    • Mutiny.SessionFactory emf;
    • SessionFactory factory;
  • REST
  • Hibernate Reactive
  • One to Many relationship
  • PostgreSQL

Running

mvn compile exec:java

Complete code: http://jreact.com/index.php/2023/12/17/vertx-hibernate-one-to-many-example-01/