Panache simplifies database access in Quarkus by reducing the boilerplate around entities and queries. Its Hibernate ORM integration offers two ways to organize persistence code: active record puts operations on the entity; the repository pattern puts them in a separate object. Both can express database operations, so choose the arrangement that fits the application. section 7.0 section 7.2
For a relational database, the implementation path depends on that choice:
- Active record: add quarkus-hibernate-orm-panache and a database-specific JDBC extension, configure the data source, annotate the entity with @Entity, and extend PanacheEntity. Call instance methods such as persist() or static methods such as listAll() and count(). section 7.1.2 section 7.1.1
- Repository: use the same Panache extension with the appropriate JDBC driver, define a JPA entity, and create an @ApplicationScoped class implementing PanacheRepository<EntityType>. Inject that repository where database operations are needed; custom query methods can live there. section 7.2.1 section 7.2.2
Listing 7.1 Panache example of active record manipulation
// Assume we have an entity named Car
// persisting into the database called on the object instance
car.persist();
// deleting an entity
car.delete();
// listing all Cars from the database called as a static method
Car.listAll();
// find Car by ID
Car.findById(carId);
// list all blue Cars
Car.list("color", Color.Blue);
// count all cars
Car.count();
// delete Car by ID
Car.deleteById(carId);
The active-record listing distinguishes calls on one entity, such as persist() and delete(), from entity-class queries such as findById(), list(), and count(). section 7.1.1
Replace a reservation stub with PostgreSQL
Make Reservation an @Entity extending PanacheEntity, then call reservation.persist() inside a @Transactional endpoint. Queries for all reservations or reservations for one car can use entity methods instead of an injected stub repository. In development mode, leaving the JDBC URL undefined lets Dev Services start and connect a PostgreSQL container; the example supplies a production-profile URL separately. Its drop-and-create schema setting drops and recreates the database at startup. section 7.1.2 section 7.1.3
Keep inventory operations in a repository
A MySQL-backed inventory uses a JPA Car entity and a PanacheRepository<Car>. Its GraphQL service injects the repository, calls listAll() to read cars, and uses @Transactional methods for persist() and deletion. An import.sql file supplies initial development or test data; that import is disabled in production mode by default. section 7.2.1 section 7.2.2
The same entity-oriented approach also reaches MongoDB: quarkus-mongodb-panache supplies the integration, an active-record document extends PanacheMongoEntity, and a repository can instead extend PanacheMongoRepository. This uses MongoDB documents rather than relational tables. Other integrations include generated REST CRUD resources for Panache entities and a Panache layer over Hibernate Reactive for reactive persistence APIs; those are distinct choices, not requirements for basic ORM use. section 7.6 section 7.6.1 section 7.8
