Simplify your persistence code for Hibernate ORM via the active record or the repository pattern
npx @tessl/cli install tessl/maven-io-quarkus--quarkus-hibernate-orm-panache@3.23.0A Quarkus extension that dramatically simplifies persistence layer development by providing two complementary patterns: the Active Record pattern through PanacheEntity and the Repository pattern through PanacheRepository. It allows developers to use public fields directly in entity classes while providing sophisticated query capabilities with simplified HQL syntax that automatically expands shorthand queries into full HQL.
mvn io.quarkus:quarkus-maven-plugin:create -DprojectGroupId=org.acme -DprojectArtifactId=my-project -Dextensions=hibernate-orm-panacheimport io.quarkus.hibernate.orm.panache.PanacheEntity;
import io.quarkus.hibernate.orm.panache.PanacheRepository;
import io.quarkus.hibernate.orm.panache.Panache;
import io.quarkus.panache.common.Page;
import io.quarkus.panache.common.Sort;
import io.quarkus.panache.common.Parameters;import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.Entity;
@Entity
public class Person extends PanacheEntity {
public String name;
public LocalDate birth;
public PersonStatus status;
public static Person findByName(String name) {
return find("name", name).firstResult();
}
public static List<Person> findAlive() {
return list("status", PersonStatus.Alive);
}
public static void deleteStefs() {
delete("name", "Stef");
}
}
// Usage
Person person = new Person();
person.name = "John Doe";
person.persist();
List<Person> allPeople = Person.listAll();
Person john = Person.findByName("John Doe");import io.quarkus.hibernate.orm.panache.PanacheRepository;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class PersonRepository implements PanacheRepository<Person> {
public Person findByName(String name) {
return find("name", name).firstResult();
}
public List<Person> findAlive() {
return list("status", PersonStatus.Alive);
}
public void deleteStefs() {
delete("name", "Stef");
}
}
// Usage
@Inject
PersonRepository personRepository;
Person person = new Person();
person.name = "Jane Doe";
personRepository.persist(person);
List<Person> allPeople = personRepository.listAll();
Person jane = personRepository.findByName("Jane Doe");Panache provides two main architectural patterns:
Core functionality for entities using the Active Record pattern through PanacheEntity and PanacheEntityBase. Provides static methods for querying, persistence, and database operations directly on entity classes.
// Find operations
public static <T extends PanacheEntityBase> T findById(Object id);
public static <T extends PanacheEntityBase> Optional<T> findByIdOptional(Object id);
public static <T extends PanacheEntityBase> PanacheQuery<T> find(String query, Object... params);
public static <T extends PanacheEntityBase> PanacheQuery<T> findAll();
// List operations
public static <T extends PanacheEntityBase> List<T> list(String query, Object... params);
public static <T extends PanacheEntityBase> List<T> listAll();
// Stream operations
public static <T extends PanacheEntityBase> Stream<T> stream(String query, Object... params);
public static <T extends PanacheEntityBase> Stream<T> streamAll();
// Count operations
public static long count();
public static long count(String query, Object... params);
// Persistence operations
public void persist();
public void persistAndFlush();
public static void persist(Object firstEntity, Object... entities);
// Delete operations
public void delete();
public static long deleteAll();
public static boolean deleteById(Object id);
public static long delete(String query, Object... params);Repository-based persistence operations through PanacheRepository and PanacheRepositoryBase interfaces. Provides the same query and persistence capabilities as Active Record but through dedicated repository classes for better separation of concerns.
// Find operations
public Entity findById(Id id);
public Optional<Entity> findByIdOptional(Id id);
public PanacheQuery<Entity> find(String query, Object... params);
public PanacheQuery<Entity> findAll();
// List operations
public List<Entity> list(String query, Object... params);
public List<Entity> listAll();
// Stream operations
public Stream<Entity> stream(String query, Object... params);
public Stream<Entity> streamAll();
// Count operations
public long count();
public long count(String query, Object... params);
// Persistence operations
public void persist(Entity entity);
public void persistAndFlush(Entity entity);
public void persist(Entity firstEntity, Entity... entities);
// Delete operations
public void delete(Entity entity);
public long deleteAll();
public boolean deleteById(Id id);
public long delete(String query, Object... params);Advanced query building capabilities including pagination, sorting, filtering, and result processing through the PanacheQuery interface. Supports both page-based and range-based result retrieval.
// Pagination
public <T extends Entity> PanacheQuery<T> page(Page page);
public <T extends Entity> PanacheQuery<T> page(int pageIndex, int pageSize);
public Page page();
public boolean hasNextPage();
public int pageCount();
// Sorting and filtering
public <T extends Entity> PanacheQuery<T> withLock(LockModeType lockModeType);
public <T extends Entity> PanacheQuery<T> withHint(String hintName, Object value);
public <T extends Entity> PanacheQuery<T> filter(String filterName, Parameters parameters);
// Result retrieval
public long count();
public <T extends Entity> List<T> list();
public <T extends Entity> Stream<T> stream();
public <T extends Entity> T firstResult();
public <T extends Entity> Optional<T> firstResultOptional();
public <T extends Entity> T singleResult();Utility classes for transaction management, EntityManager access, parameter building, and sorting configuration. Includes the Panache utility class for global operations and supporting classes for query parameters.
// Panache utilities
public static EntityManager getEntityManager();
public static Session getSession();
public static TransactionManager getTransactionManager();
public static int executeUpdate(String query, Object... params);
public static void flush();
// Parameter building
public static Parameters with(String name, Object value);
public Parameters and(String name, Object value);
public Map<String, Object> map();
// Sorting
public static Sort by(String column);
public static Sort by(String column, Direction direction);
public Sort and(String name, Direction direction);
// Pagination
public static Page of(int index, int size);
public static Page ofSize(int size);
public Page next();
public Page previous();public abstract class PanacheEntity extends PanacheEntityBase {
@Id
@GeneratedValue
public Long id;
}
public abstract class PanacheEntityBase {
// All static and instance methods for Active Record pattern
}
public interface PanacheRepository<Entity> extends PanacheRepositoryBase<Entity, Long> {
// Repository pattern for entities with Long ID
}
public interface PanacheRepositoryBase<Entity, Id> {
// All default methods for Repository pattern
}public interface PanacheQuery<Entity> {
// Query building and result retrieval methods
}
public class Page {
public final int index;
public final int size;
public Page(int index, int size);
public static Page of(int index, int size);
public static Page ofSize(int size);
public Page next();
public Page previous();
}
public class Parameters {
public static Parameters with(String name, Object value);
public Parameters and(String name, Object value);
public Map<String, Object> map();
}
public class Sort {
public static Sort by(String column);
public static Sort by(String column, Direction direction);
public Sort and(String name, Direction direction);
public enum Direction {
Ascending, Descending
}
public enum NullPrecedence {
NULLS_FIRST, NULLS_LAST
}
}