liveBook · Manning

Repository pattern

As explained in Quarkus in Action

The repository pattern encapsulates data-access operations behind an abstraction that manages persistence and retrieval for domain objects.

The repository pattern puts database operations in a separate object rather than on the entity itself. In a Quarkus application, Panache supports this approach alongside the active record pattern. Keeping persistence operations outside entity classes can improve separation of concerns and flexibility; the choice of pattern does not determine the database. section 7.2

To use a Panache repository for a MySQL-backed inventory:

  • Add the quarkus-hibernate-orm-panache and quarkus-jdbc-mysql extensions, then configure the MySQL datasource. section 7.2.1
  • Define an ordinary JPA entity with @Entity and an ID. Unlike an entity extending PanacheEntity, a plain JPA entity declares its own ID field. section 7.2.1
  • Create an @ApplicationScoped class implementing PanacheRepository<Car>. It can start empty and gain application-specific query methods as needed. section 7.2.1
Listing 7.14 The code of the CarRepository class
package org.acme.inventory.repository;

import io.quarkus.hibernate.orm.panache.PanacheRepository;
import jakarta.enterprise.context.ApplicationScoped;
import org.acme.inventory.model.Car;

@ApplicationScoped
public class CarRepository implements PanacheRepository<Car> {
}

The minimal repository declaration shows where Panache’s database operations become available without putting them on the Car entity. section 7.2.1

Find a car by license plate

Add findByLicensePlateNumberOptional to the repository. It calls find("licensePlateNumber", licensePlateNumber).firstResultOptional(), letting a caller request one matching car rather than list every car and filter manually. section 7.2.1 section 7.2.2

Inject the repository into the GraphQL and gRPC inventory services in place of the in-memory stub. Call listAll to read cars, persist to register one, and the custom lookup followed by delete to remove one. Database-changing GraphQL methods use @Transactional; the gRPC persistence callback instead starts a transaction with QuarkusTransaction.requiringNew(). section 7.2.2

For development or testing, src/main/resources/import.sql can load initial cars when Quarkus connects; this import is disabled in production mode by default. The pattern is not limited to MySQL: Panache also offers MongoDB repository interfaces, although the MongoDB rental example uses active record instead. section 7.2.2 section 7.6.1

How Quarkus in Action covers it

How deep it goes
Builds a MySQL-backed repository from extensions and a JPA entity through a custom lookup, service calls, and transaction handling.
Examples
Uses a car inventory, a license-plate lookup, GraphQL and gRPC operations, and an SQL seed script.
What it assumes
Introduces the repository’s role while using Java, JPA annotations, and Quarkus extensions in the implementation.
What you can do after
Apply it via Panache to persist, list, find, and delete inventory entities through a repository.
How it connects
Contrasts with active record and connects Panache, Hibernate ORM, JPA entities, CDI, and transactions.

Also explained in

Compare how 9 books explain repository pattern →

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.