Core Java

Hibernate Panache Example

Hibernate ORM with Panache is a modern, simplified way to use Hibernate in Java applications. Built into the Quarkus framework, it allows us to interact with databases using less boilerplate code, providing a clean and expressive API on top of standard JPA. In this article, we will build a simple CRUD application using Hibernate ORM with Panache.

1. Project Setup

First, we need to create a Quarkus project with the appropriate extensions for Hibernate ORM with Panache and an H2 database. We will use Maven as our build tool.

You can create a Quarkus application using Hibernate ORM with Panache by using the online project generator available at code.quarkus.io. Simply select the following extensions: Hibernate ORM with Panache, JDBC Driver – H2, and RESTEasy Classic JSON-B, then generate your application to get started.

Screenshot from code.quarkus.io showcasing a Java Hibernate Panache example project setup.

Alternatively, you can use the Quarkus Maven plugin to generate the project from the command line:

mvn io.quarkus:quarkus-maven-plugin:3.24.1:create \
    -DprojectGroupId=com.jcg \
    -DprojectArtifactId=panache-demo \
    -DclassName="com.jcg.PersonResource" \
    -Dpath="/" \
    -Dextensions="resteasy-jsonb,hibernate-orm-panache,jdbc-h2"

This command scaffolds a Quarkus project with the necessary dependencies for REST API development, ORM with Panache, and an in-memory H2 database, which makes it easy to run and test without needing an external DB.

Maven Configuration (pom.xml)

Verify your pom.xml has the correct dependencies for REST, Hibernate ORM with Panache, and H2.

        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-hibernate-orm-panache</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-jdbc-h2</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-resteasy-jsonb</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-arc</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-hibernate-orm</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-resteasy</artifactId>
        </dependency>

Application Configuration (application.properties)

Next, configure H2 and Hibernate settings in src/main/resources/application.properties.

quarkus.datasource.db-kind=h2
quarkus.datasource.jdbc.url=jdbc:h2:mem:default;DB_CLOSE_DELAY=-1
quarkus.datasource.username=sa
quarkus.datasource.password=sa

quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-orm.log.sql=true

This configuration sets the H2 database to run in-memory, with drop-and-create to recreate the schema on each start. SQL logging is enabled for visibility into Hibernate’s actions.

2. Creating the Entity

Let’s define a simple Person entity that extends PanacheEntity, which provides an ID and several convenient static methods.

@Entity
public class Person extends PanacheEntity {

    public String name;
    public int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
}

The Person class maps to a database table. Extending PanacheEntity auto-generates a primary key and adds useful ORM utilities like persist, findById, and listAll.

Creating the Repository (Optional)

Although Panache entities support static access methods, you can optionally define a repository for better abstraction.

@ApplicationScoped
public class PersonRepository implements PanacheRepository<Person> {
    
    // Custom queries can go here
}

This optional class provides repository-style access to the Person entity. It allows custom methods and can be injected into services or resources for cleaner architecture.

3. Creating the REST Resource

Now, let’s expose the Person entity through a RESTful API using Quarkus RESTEasy.

@Path("/people")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class PersonResource {

    @GET
    public List getAll() {
        return Person.listAll();
    }

    @POST
    @Transactional
    public void addPerson(Person person) {
        person.persist();
    }

    @GET
    @Path("/{id}")
    public Person getById(@PathParam("id") Long id) {
        return Person.findById(id);
    }

    @DELETE
    @Path("/{id}")
    @Transactional
    public void deleteById(@PathParam("id") Long id) {
        Person.deleteById(id);
    }
}

This REST resource class provides HTTP endpoints for interacting with the Person entity using standard CRUD operations. The @Path("/people") annotation defines the base URI path for all the methods in this class. The @GET method without a sub-path returns a list of all people in the database by calling Person.listAll(), which is a static Panache utility method that retrieves all rows from the corresponding table.

The @POST method is annotated with @Transactional, which is essential when performing operations that modify the database state, like persisting new entities. Here, person.persist() saves the incoming Person object to the database.

The @GET method with a path parameter /people/{id} uses Person.findById(id) to retrieve a single person record by its ID, automatically mapped from the URL. The @DELETE method also uses a path parameter and removes the record by calling Person.deleteById(id), another Panache utility method that simplifies deletion by ID.

By using Panache’s active record pattern, this resource avoids the need for a separate service or DAO layer for simple use cases.

4. Running the Application

To start the app in development mode with live reload enabled, run:

./mvnw quarkus:dev 

This starts the Quarkus app with live-reload capabilities, making it ideal for iterative development. Since we use H2, no external DB setup is needed.

5. Testing the API

You can test your REST endpoints using tools like curl or Postman. Here are example commands to test the application:

Create New Persons

curl -X POST -H "Content-Type: application/json" \
  -d '{"name": "Grace Hopper", "age": 85}' \
  http://localhost:8080/people

curl -X POST -H "Content-Type: application/json" \
  -d '{"name": "Alan Turing", "age": 41}' \
  http://localhost:8080/people

Get All People

curl http://localhost:8080/people

Sample Output:

[
  {
    "id": 1,
    "age": 85,
    "name": "Grace Hopper"
  },
  {
    "id": 2,
    "age": 41,
    "name": "Alan Turing"
  }
]

Get Person by ID

curl http://localhost:8080/people/1

Delete Person by ID

curl -X DELETE http://localhost:8080/people/1

These commands test your API by creating, retrieving, and deleting Person records. They demonstrate how easily REST endpoints interact with the Panache entity.

6. Conclusion

In this article, we explored how to build a CRUD REST API using Hibernate ORM with Panache in Quarkus, powered by the H2 in-memory database. Panache significantly reduces the effort required to manage entities and queries while offering a modern and fluent API. H2 makes it easy to develop and test without installing a full database engine. This setup is ideal for rapid prototyping.

7. Download the Source Code

Download
You can download the full source code of this example here: java hibernate panache

Omozegie Aziegbe

Omos Aziegbe is a technical writer and web/application developer with a BSc in Computer Science and Software Engineering from the University of Bedfordshire. Specializing in Java enterprise applications with the Jakarta EE framework, Omos also works with HTML5, CSS, and JavaScript for web development. As a freelance web developer, Omos combines technical expertise with research and writing on topics such as software engineering, programming, web application development, computer science, and technology.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button