withHint(String hintName, Object value);
+
+ /**
+ *
+ * Enables a Hibernate filter during fetching of results for this query. Your filter must be declared
+ * with {@link FilterDef} on your entity or package, and enabled with {@link Filter} on your entity.
+ *
+ * WARNING: setting filters can only be done on the underlying Hibernate {@link Session} and so this
+ * will modify the session's filters for the duration of obtaining the results (not while building
+ * the query). Enabled filters will be removed from the session afterwards, but no effort is made to
+ * preserve filters enabled on the session outside of this API.
+ *
+ * @param filterName The name of the filter to enable
+ * @param parameters The set of parameters for the filter, if the filter requires parameters
+ * @return this query, modified
+ */
+ public PanacheQuery filter(String filterName, Map parameters);
+
+ /**
+ *
+ * Enables a Hibernate filter during fetching of results for this query. Your filter must be declared
+ * with {@link FilterDef} on your entity or package, and enabled with {@link Filter} on your entity.
+ *
+ * WARNING: setting filters can only be done on the underlying Hibernate {@link Session} and so this
+ * will modify the session's filters for the duration of obtaining the results (not while building
+ * the query). Enabled filters will be removed from the session afterwards, but no effort is made to
+ * preserve filters enabled on the session outside of this API.
+ *
+ * @param filterName The name of the filter to enable
+ * @return this query, modified
+ */
+ public PanacheQuery filter(String filterName);
+
+ // Results
+
+ /**
+ * Reads and caches the total number of entities this query operates on. This causes a database
+ * query with SELECT COUNT(*) and a query equivalent to the current query, minus
+ * ordering.
+ *
+ * @return the total number of entities this query operates on, cached.
+ */
+ public Count count();
+
+ /**
+ * Returns the current page of results as a {@link List}.
+ *
+ * @return the current page of results as a {@link List}.
+ * @see #stream()
+ * @see #page(Page)
+ * @see #page()
+ */
+ public EntityList list();
+
+ /**
+ * Returns the current page of results as a {@link Stream}.
+ *
+ * @return the current page of results as a {@link Stream}.
+ * @see #list()
+ * @see #page(Page)
+ * @see #page()
+ */
+ // FIXME: down
+ // public Stream stream();
+
+ /**
+ * Returns the first result of the current page index. This ignores the current page size to fetch
+ * a single result.
+ *
+ * @return the first result of the current page index, or null if there are no results.
+ * @see #singleResult()
+ */
+ public Entity firstResult();
+
+ /**
+ * Returns the first result of the current page index. This ignores the current page size to fetch
+ * a single result.
+ *
+ * @return if found, an optional containing the entity, else Optional.empty().
+ * @see #singleResultOptional()
+ */
+ // FIXME: down
+ // public Optional firstResultOptional();
+
+ /**
+ * Executes this query for the current page and return a single result.
+ *
+ * @return the single result (throws if there is not exactly one)
+ * @throws NoResultException if there is no result
+ * @throws NonUniqueResultException if there are more than one result
+ * @see #firstResult()
+ */
+ public Entity singleResult();
+
+ /**
+ * Executes this query for the current page and return a single result.
+ *
+ * @return if found, an optional containing the entity, else Optional.empty().
+ * @throws NonUniqueResultException if there are more than one result
+ * @see #firstResultOptional()
+ */
+ // FIXME: down
+ // public Optional singleResultOptional();
+}
diff --git a/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/PanacheRepository.java b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/PanacheRepository.java
new file mode 100644
index 0000000000000..308c91dfcad43
--- /dev/null
+++ b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/PanacheRepository.java
@@ -0,0 +1,20 @@
+package io.quarkus.hibernate.panache;
+
+import io.quarkus.hibernate.panache.managed.blocking.PanacheManagedBlockingRepositoryBase;
+import io.quarkus.hibernate.panache.managed.reactive.PanacheManagedReactiveRepositoryBase;
+import io.quarkus.hibernate.panache.stateless.blocking.PanacheStatelessBlockingRepositoryBase;
+import io.quarkus.hibernate.panache.stateless.reactive.PanacheStatelessReactiveRepositoryBase;
+
+public interface PanacheRepository extends PanacheManagedBlockingRepositoryBase {
+ public interface Managed extends PanacheManagedBlockingRepositoryBase {
+ }
+
+ public interface Stateless extends PanacheStatelessBlockingRepositoryBase {
+ }
+
+ public interface Reactive extends PanacheManagedReactiveRepositoryBase {
+
+ public interface Stateless extends PanacheStatelessReactiveRepositoryBase {
+ }
+ }
+}
diff --git a/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/PanacheRepositoryQueries.java b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/PanacheRepositoryQueries.java
new file mode 100644
index 0000000000000..1fcc024235618
--- /dev/null
+++ b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/PanacheRepositoryQueries.java
@@ -0,0 +1,301 @@
+package io.quarkus.hibernate.panache;
+
+import java.util.Map;
+
+import jakarta.persistence.LockModeType;
+
+import io.quarkus.panache.common.Parameters;
+import io.quarkus.panache.common.Sort;
+
+public interface PanacheRepositoryQueries, Count, Confirmation, Id> {
+
+ // Queries
+
+ /**
+ * Find an entity of this type by ID.
+ *
+ * @param id the ID of the entity to find.
+ * @return the entity found, or null if not found.
+ */
+ Entity findById(Id id);
+
+ /**
+ * Find an entity of this type by ID and lock it.
+ *
+ * @param id the ID of the entity to find.
+ * @param lockModeType the locking strategy to be used when retrieving the entity.
+ * @return the entity found, or null if not found.
+ */
+ Entity findById(Id id, LockModeType lockModeType);
+
+ /**
+ * Find entities using a query, with optional indexed parameters.
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param params optional sequence of indexed parameters
+ * @return a new {@link PanacheQuery} instance for the given query
+ * @see #find(String, Sort, Object...)
+ * @see #find(String, Map)
+ * @see #find(String, Parameters)
+ * @see #list(String, Object...)
+ * @see #stream(String, Object...)
+ */
+ Query find(String query, Object... params);
+
+ /**
+ * Find entities using a query and the given sort options, with optional indexed parameters.
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param sort the sort strategy to use
+ * @param params optional sequence of indexed parameters
+ * @return a new {@link PanacheQuery} instance for the given query
+ * @see #find(String, Object...)
+ * @see #find(String, Sort, Map)
+ * @see #find(String, Sort, Parameters)
+ * @see #list(String, Sort, Object...)
+ * @see #stream(String, Sort, Object...)
+ */
+ Query find(String query, Sort sort, Object... params);
+
+ /**
+ * Find entities using a query, with named parameters.
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param params {@link Map} of named parameters
+ * @return a new {@link PanacheQuery} instance for the given query
+ * @see #find(String, Sort, Map)
+ * @see #find(String, Object...)
+ * @see #find(String, Parameters)
+ * @see #list(String, Map)
+ * @see #stream(String, Map)
+ */
+ Query find(String query, Map params);
+
+ /**
+ * Find entities using a query and the given sort options, with named parameters.
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param sort the sort strategy to use
+ * @param params {@link Map} of indexed parameters
+ * @return a new {@link PanacheQuery} instance for the given query
+ * @see #find(String, Map)
+ * @see #find(String, Sort, Object...)
+ * @see #find(String, Sort, Parameters)
+ * @see #list(String, Sort, Map)
+ * @see #stream(String, Sort, Map)
+ */
+ Query find(String query, Sort sort, Map params);
+
+ /**
+ * Find all entities of this type.
+ *
+ * @return a new {@link PanacheQuery} instance to find all entities of this type.
+ * @see #findAll(Sort)
+ * @see #listAll()
+ * @see #streamAll()
+ */
+ Query findAll();
+
+ /**
+ * Find all entities of this type, in the given order.
+ *
+ * @param sort the sort order to use
+ * @return a new {@link PanacheQuery} instance to find all entities of this type.
+ * @see #findAll()
+ * @see #listAll(Sort)
+ * @see #streamAll(Sort)
+ */
+ Query findAll(Sort sort);
+
+ /**
+ * Find entities matching a query, with optional indexed parameters.
+ * This method is a shortcut for find(query, params).list().
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param params optional sequence of indexed parameters
+ * @return a {@link List} containing all results, without paging
+ * @see #list(String, Sort, Object...)
+ * @see #list(String, Map)
+ * @see #list(String, Parameters)
+ * @see #find(String, Object...)
+ * @see #stream(String, Object...)
+ */
+ EntityList list(String query, Object... params);
+
+ /**
+ * Find entities matching a query and the given sort options, with optional indexed parameters.
+ * This method is a shortcut for find(query, sort, params).list().
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param sort the sort strategy to use
+ * @param params optional sequence of indexed parameters
+ * @return a {@link List} containing all results, without paging
+ * @see #list(String, Object...)
+ * @see #list(String, Sort, Map)
+ * @see #list(String, Sort, Parameters)
+ * @see #find(String, Sort, Object...)
+ * @see #stream(String, Sort, Object...)
+ */
+ EntityList list(String query, Sort sort, Object... params);
+
+ /**
+ * Find entities matching a query, with named parameters.
+ * This method is a shortcut for find(query, params).list().
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param params {@link Map} of named parameters
+ * @return a {@link List} containing all results, without paging
+ * @see #list(String, Sort, Map)
+ * @see #list(String, Object...)
+ * @see #list(String, Parameters)
+ * @see #find(String, Map)
+ * @see #stream(String, Map)
+ */
+ EntityList list(String query, Map params);
+
+ /**
+ * Find entities matching a query and the given sort options, with named parameters.
+ * This method is a shortcut for find(query, sort, params).list().
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param sort the sort strategy to use
+ * @param params {@link Map} of indexed parameters
+ * @return a {@link List} containing all results, without paging
+ * @see #list(String, Map)
+ * @see #list(String, Sort, Object...)
+ * @see #list(String, Sort, Parameters)
+ * @see #find(String, Sort, Map)
+ * @see #stream(String, Sort, Map)
+ */
+ EntityList list(String query, Sort sort, Map params);
+
+ /**
+ * Find all entities of this type.
+ * This method is a shortcut for findAll().list().
+ *
+ * @return a {@link List} containing all results, without paging
+ * @see #listAll(Sort)
+ * @see #findAll()
+ * @see #streamAll()
+ */
+ EntityList listAll();
+
+ /**
+ * Find all entities of this type, in the given order.
+ * This method is a shortcut for findAll(sort).list().
+ *
+ * @param sort the sort order to use
+ * @return a {@link List} containing all results, without paging
+ * @see #listAll()
+ * @see #findAll(Sort)
+ * @see #streamAll(Sort)
+ */
+ EntityList listAll(Sort sort);
+
+ /**
+ * Counts the number of this type of entity in the database.
+ *
+ * @return the number of this type of entity in the database.
+ * @see #count(String, Object...)
+ * @see #count(String, Map)
+ * @see #count(String, Parameters)
+ */
+ Count count();
+
+ /**
+ * Counts the number of this type of entity matching the given query, with optional indexed parameters.
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param params optional sequence of indexed parameters
+ * @return the number of entities counted.
+ * @see #count()
+ * @see #count(String, Map)
+ * @see #count(String, Parameters)
+ */
+ Count count(String query, Object... params);
+
+ /**
+ * Counts the number of this type of entity matching the given query, with named parameters.
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param params {@link Map} of named parameters
+ * @return the number of entities counted.
+ * @see #count()
+ * @see #count(String, Object...)
+ * @see #count(String, Parameters)
+ */
+ Count count(String query, Map params);
+
+ /**
+ * Delete all entities of this type from the database.
+ *
+ * WARNING: the default implementation of this method uses a bulk delete query and ignores
+ * cascading rules from the JPA model.
+ *
+ * @return the number of entities deleted.
+ * @see #delete(String, Object...)
+ * @see #delete(String, Map)
+ * @see #delete(String, Parameters)
+ */
+ Count deleteAll();
+
+ /**
+ * Delete an entity of this type by ID.
+ *
+ * @param id the ID of the entity to delete.
+ * @return false if the entity was not deleted (not found).
+ */
+ Confirmation deleteById(Id id);
+
+ /**
+ * Delete all entities of this type matching the given query, with optional indexed parameters.
+ *
+ * WARNING: the default implementation of this method uses a bulk delete query and ignores
+ * cascading rules from the JPA model.
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param params optional sequence of indexed parameters
+ * @return the number of entities deleted.
+ * @see #deleteAll()
+ * @see #delete(String, Map)
+ * @see #delete(String, Parameters)
+ */
+ Count delete(String query, Object... params);
+
+ /**
+ * Delete all entities of this type matching the given query, with named parameters.
+ *
+ * WARNING: the default implementation of this method uses a bulk delete query and ignores
+ * cascading rules from the JPA model.
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param params {@link Map} of named parameters
+ * @return the number of entities deleted.
+ * @see #deleteAll()
+ * @see #delete(String, Object...)
+ * @see #delete(String, Parameters)
+ */
+ Count delete(String query, Map params);
+
+ /**
+ * Update all entities of this type matching the given query, with optional indexed parameters.
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param params optional sequence of indexed parameters
+ * @return the number of entities updated.
+ * @see #update(String, Map)
+ * @see #update(String, Parameters)
+ */
+ Count update(String query, Object... params);
+
+ /**
+ * Update all entities of this type matching the given query, with named parameters.
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param params {@link Map} of named parameters
+ * @return the number of entities updated.
+ * @see #update(String, Object...)
+ * @see #update(String, Parameters)
+ */
+ Count update(String query, Map params);
+}
diff --git a/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/PanacheRepositorySwitcher.java b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/PanacheRepositorySwitcher.java
new file mode 100644
index 0000000000000..05fb56be29e79
--- /dev/null
+++ b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/PanacheRepositorySwitcher.java
@@ -0,0 +1,29 @@
+package io.quarkus.hibernate.panache;
+
+import io.quarkus.hibernate.orm.panache.common.runtime.AbstractJpaOperations;
+import io.quarkus.hibernate.panache.managed.blocking.PanacheManagedBlockingRepositoryBase;
+import io.quarkus.hibernate.panache.managed.reactive.PanacheManagedReactiveRepositoryBase;
+import io.quarkus.hibernate.panache.stateless.blocking.PanacheStatelessBlockingRepositoryBase;
+import io.quarkus.hibernate.panache.stateless.reactive.PanacheStatelessReactiveRepositoryBase;
+
+public interface PanacheRepositorySwitcher {
+ default PanacheManagedBlockingRepositoryBase managedBlocking() {
+ // FIXME: generate in impl
+ throw AbstractJpaOperations.implementationInjectionMissing();
+ }
+
+ default PanacheManagedReactiveRepositoryBase managedReactive() {
+ // FIXME: generate in impl
+ throw AbstractJpaOperations.implementationInjectionMissing();
+ }
+
+ default PanacheStatelessBlockingRepositoryBase statelessBlocking() {
+ // FIXME: generate in impl
+ throw AbstractJpaOperations.implementationInjectionMissing();
+ }
+
+ default PanacheStatelessReactiveRepositoryBase statelessReactive() {
+ // FIXME: generate in impl
+ throw AbstractJpaOperations.implementationInjectionMissing();
+ }
+}
diff --git a/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/WithId.java b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/WithId.java
new file mode 100644
index 0000000000000..4bb53fff62617
--- /dev/null
+++ b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/WithId.java
@@ -0,0 +1,33 @@
+package io.quarkus.hibernate.panache;
+
+import java.util.UUID;
+
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
+import jakarta.persistence.MappedSuperclass;
+
+@MappedSuperclass
+public class WithId {
+ /**
+ * The auto-generated ID field. This field is set by Hibernate ORM when this entity
+ * is persisted.
+ */
+ @Id
+ @GeneratedValue
+ public IdType id;
+
+ @Override
+ public java.lang.String toString() {
+ return this.getClass().getSimpleName() + "<" + id + ">";
+ }
+
+ public abstract static class AutoLong extends WithId {
+ }
+
+ public abstract static class AutoString extends WithId {
+ }
+
+ public abstract static class AutoUUID extends WithId {
+ }
+
+}
diff --git a/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/blocking/PanacheBlockingQuery.java b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/blocking/PanacheBlockingQuery.java
new file mode 100644
index 0000000000000..7869246555c32
--- /dev/null
+++ b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/blocking/PanacheBlockingQuery.java
@@ -0,0 +1,66 @@
+package io.quarkus.hibernate.panache.blocking;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import jakarta.persistence.NonUniqueResultException;
+
+import io.quarkus.hibernate.panache.PanacheQuery;
+
+public interface PanacheBlockingQuery extends PanacheQuery, Boolean, Long> {
+
+ /**
+ * Defines a projection class. This will transform the returned values into instances of the given type using the following
+ * mapping rules:
+ *
+ * - If your query already selects some specific columns (starts with
select distinct? a, b, c…) then we
+ * transform
+ * it into a query of the form: select distinct? new ProjectionClass(a, b, c)…. There must be a matching
+ * constructor
+ * that accepts the selected column types, in the right order.
+ * - If your query does not select any specific column (starts with
from…) then we transform it into a query
+ * of the form:
+ * select new ProjectionClass(a, b, c…) from… where we fetch the list of selected columns from your projection
+ * class'
+ * single constructor, using its parameter names (or their {@link ProjectedFieldName} annotations), in the same order as the
+ * constructor.
+ * - If this is already a project query of the form
select distinct? new…, we throw a
+ * {@link PanacheQueryException}
+ *
+ * @param type the projected class type
+ * @return a new query with the same state as the previous one (params, page, range, lockMode, hints, ...) but a projected
+ * result of the type
+ * type
+ * @throws PanacheQueryException if this represents an already-projected query
+ */
+ public PanacheQuery, Boolean, Long> project(Class type);
+
+ /**
+ * Returns the current page of results as a {@link Stream}.
+ *
+ * @return the current page of results as a {@link Stream}.
+ * @see #list()
+ * @see #page(Page)
+ * @see #page()
+ */
+ public Stream stream();
+
+ /**
+ * Returns the first result of the current page index. This ignores the current page size to fetch
+ * a single result.
+ *
+ * @return if found, an optional containing the entity, else Optional.empty().
+ * @see #singleResultOptional()
+ */
+ public Optional firstResultOptional();
+
+ /**
+ * Executes this query for the current page and return a single result.
+ *
+ * @return if found, an optional containing the entity, else Optional.empty().
+ * @throws NonUniqueResultException if there are more than one result
+ * @see #firstResultOptional()
+ */
+ public Optional singleResultOptional();
+}
diff --git a/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/blocking/PanacheRepositoryBlockingQueries.java b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/blocking/PanacheRepositoryBlockingQueries.java
new file mode 100644
index 0000000000000..038c2cb1dbcc4
--- /dev/null
+++ b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/blocking/PanacheRepositoryBlockingQueries.java
@@ -0,0 +1,130 @@
+package io.quarkus.hibernate.panache.blocking;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import jakarta.persistence.LockModeType;
+
+import io.quarkus.hibernate.panache.PanacheRepositoryQueries;
+import io.quarkus.panache.common.Parameters;
+import io.quarkus.panache.common.Sort;
+
+public interface PanacheRepositoryBlockingQueries
+ extends PanacheRepositoryQueries, PanacheBlockingQuery, Long, Boolean, Id> {
+
+ // Queries
+
+ /**
+ * Find an entity of this type by ID.
+ *
+ * @param id the ID of the entity to find.
+ * @return if found, an optional containing the entity, else Optional.empty().
+ */
+ Optional findByIdOptional(Id id);
+
+ /**
+ * Find an entity of this type by ID.
+ *
+ * @param id the ID of the entity to find.
+ * @return if found, an optional containing the entity, else Optional.empty().
+ */
+ Optional findByIdOptional(Id id, LockModeType lockModeType);
+
+ /**
+ * Find entities matching a query, with optional indexed parameters.
+ * This method is a shortcut for find(query, params).stream().
+ * It requires a transaction to work.
+ * Without a transaction, the underlying cursor can be closed before the end of the stream.
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param params optional sequence of indexed parameters
+ * @return a {@link Stream} containing all results, without paging
+ * @see #stream(String, Sort, Object...)
+ * @see #stream(String, Map)
+ * @see #stream(String, Parameters)
+ * @see #find(String, Object...)
+ * @see #list(String, Object...)
+ */
+ Stream stream(String query, Object... params);
+
+ /**
+ * Find entities matching a query and the given sort options, with optional indexed parameters.
+ * This method is a shortcut for find(query, sort, params).stream().
+ * It requires a transaction to work.
+ * Without a transaction, the underlying cursor can be closed before the end of the stream.
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param sort the sort strategy to use
+ * @param params optional sequence of indexed parameters
+ * @return a {@link Stream} containing all results, without paging
+ * @see #stream(String, Object...)
+ * @see #stream(String, Sort, Map)
+ * @see #stream(String, Sort, Parameters)
+ * @see #find(String, Sort, Object...)
+ * @see #list(String, Sort, Object...)
+ */
+ Stream stream(String query, Sort sort, Object... params);
+
+ /**
+ * Find entities matching a query, with named parameters.
+ * This method is a shortcut for find(query, params).stream().
+ * It requires a transaction to work.
+ * Without a transaction, the underlying cursor can be closed before the end of the stream.
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param params {@link Map} of named parameters
+ * @return a {@link Stream} containing all results, without paging
+ * @see #stream(String, Sort, Map)
+ * @see #stream(String, Object...)
+ * @see #stream(String, Parameters)
+ * @see #find(String, Map)
+ * @see #list(String, Map)
+ */
+ Stream stream(String query, Map params);
+
+ /**
+ * Find entities matching a query and the given sort options, with named parameters.
+ * This method is a shortcut for find(query, sort, params).stream().
+ * It requires a transaction to work.
+ * Without a transaction, the underlying cursor can be closed before the end of the stream.
+ *
+ * @param query a {@link io.quarkus.hibernate.panache query string}
+ * @param sort the sort strategy to use
+ * @param params {@link Map} of indexed parameters
+ * @return a {@link Stream} containing all results, without paging
+ * @see #stream(String, Map)
+ * @see #stream(String, Sort, Object...)
+ * @see #stream(String, Sort, Parameters)
+ * @see #find(String, Sort, Map)
+ * @see #list(String, Sort, Map)
+ */
+ Stream stream(String query, Sort sort, Map params);
+
+ /**
+ * Find all entities of this type.
+ * This method is a shortcut for findAll().stream().
+ * It requires a transaction to work.
+ * Without a transaction, the underlying cursor can be closed before the end of the stream.
+ *
+ * @return a {@link Stream} containing all results, without paging
+ * @see #streamAll(Sort)
+ * @see #findAll()
+ * @see #listAll()
+ */
+ Stream streamAll(Sort sort);
+
+ /**
+ * Find all entities of this type, in the given order.
+ * This method is a shortcut for findAll().stream().
+ * It requires a transaction to work.
+ * Without a transaction, the underlying cursor can be closed before the end of the stream.
+ *
+ * @return a {@link Stream} containing all results, without paging
+ * @see #streamAll()
+ * @see #findAll(Sort)
+ * @see #listAll(Sort)
+ */
+ Stream streamAll();
+}
diff --git a/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/PanacheManagedEntityOperations.java b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/PanacheManagedEntityOperations.java
new file mode 100644
index 0000000000000..142ab0eb83927
--- /dev/null
+++ b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/PanacheManagedEntityOperations.java
@@ -0,0 +1,58 @@
+package io.quarkus.hibernate.panache.managed;
+
+import java.util.Map;
+import java.util.stream.Stream;
+
+import jakarta.json.bind.annotation.JsonbTransient;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+import io.quarkus.hibernate.panache.PanacheEntityMarker;
+import io.quarkus.panache.common.Parameters;
+
+public interface PanacheManagedEntityOperations extends PanacheEntityMarker {
+ /**
+ * Persist this entity in the database, if not already persisted. This will set your ID field if it is not already set.
+ *
+ * @see #isPersistent()
+ * @see #persist(Iterable)
+ * @see #persist(Stream)
+ * @see #persist(Object, Object...)
+ */
+ public Completion persist();
+
+ /**
+ * Persist this entity in the database, if not already persisted. This will set your ID field if it is not already set.
+ * Then flushes all pending changes to the database.
+ *
+ * @see #isPersistent()
+ * @see #persist(Iterable)
+ * @see #persist(Stream)
+ * @see #persist(Object, Object...)
+ */
+ public Completion persistAndFlush();
+
+ /**
+ * Delete this entity from the database, if it is already persisted.
+ *
+ * @see #isPersistent()
+ * @see #delete(String, Object...)
+ * @see #delete(String, Map)
+ * @see #delete(String, Parameters)
+ * @see #deleteAll()
+ */
+ public Completion delete();
+
+ /**
+ * Returns true if this entity is persistent in the database. If yes, all modifications to
+ * its persistent fields will be automatically committed to the database at transaction
+ * commit time.
+ *
+ * @return true if this entity is persistent in the database.
+ */
+ @JsonbTransient
+ // @JsonIgnore is here to avoid serialization of this property with jackson
+ @JsonIgnore
+ public Confirmation isPersistent();
+
+}
diff --git a/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/PanacheManagedRepositoryOperations.java b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/PanacheManagedRepositoryOperations.java
new file mode 100644
index 0000000000000..cf2713c78a310
--- /dev/null
+++ b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/PanacheManagedRepositoryOperations.java
@@ -0,0 +1,95 @@
+package io.quarkus.hibernate.panache.managed;
+
+import java.util.Map;
+import java.util.stream.Stream;
+
+public interface PanacheManagedRepositoryOperations {
+
+ // Operations
+
+ /**
+ * Returns the {@link Session} for the entity class for extra operations (eg. CriteriaQueries)
+ *
+ * @return the {@link Session} for the entity class
+ */
+ Session getSession();
+
+ /**
+ * Persist the given entity in the database, if not already persisted.
+ *
+ * @param entity the entity to persist.
+ * @see #isPersistent(Object)
+ * @see #persist(Iterable)
+ * @see #persist(Stream)
+ * @see #persist(Object, Object...)
+ */
+ Completion persist(Entity entity);
+
+ /**
+ * Persist the given entity in the database, if not already persisted.
+ * Then flushes all pending changes to the database.
+ *
+ * @param entity the entity to persist.
+ * @see #isPersistent(Object)
+ * @see #persist(Iterable)
+ * @see #persist(Stream)
+ * @see #persist(Object, Object...)
+ */
+ Completion persistAndFlush(Entity entity);
+
+ /**
+ * Delete the given entity from the database, if it is already persisted.
+ *
+ * @param entity the entity to delete.
+ * @see #isPersistent(Object)
+ * @see #delete(String, Object...)
+ * @see #delete(String, Map)
+ * @see #deleteAll()
+ */
+ Completion delete(Entity entity);
+
+ /**
+ * Returns true if the given entity is persistent in the database. If yes, all modifications to
+ * its persistent fields will be automatically committed to the database at transaction
+ * commit time.
+ *
+ * @param entity the entity to check
+ * @return true if the entity is persistent in the database.
+ */
+ Confirmation isPersistent(Entity entity);
+
+ /**
+ * Flushes all pending changes to the database using the Session for the entity class.
+ */
+ Completion flush();
+
+ /**
+ * Persist all given entities.
+ *
+ * @param entities the entities to persist
+ * @see #persist(Object)
+ * @see #persist(Stream)
+ * @see #persist(Object,Object...)
+ */
+ Completion persist(Iterable entities);
+
+ /**
+ * Persist all given entities.
+ *
+ * @param entities the entities to persist
+ * @see #persist(Object)
+ * @see #persist(Iterable)
+ * @see #persist(Object,Object...)
+ */
+ Completion persist(Stream entities);
+
+ /**
+ * Persist all given entities.
+ *
+ * @param entities the entities to persist
+ * @see #persist(Object)
+ * @see #persist(Stream)
+ * @see #persist(Iterable)
+ */
+ Completion persist(Entity firstEntity, @SuppressWarnings("unchecked") Entity... entities);
+}
diff --git a/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/blocking/PanacheManagedBlockingEntity.java b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/blocking/PanacheManagedBlockingEntity.java
new file mode 100644
index 0000000000000..c130f6eecb17e
--- /dev/null
+++ b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/blocking/PanacheManagedBlockingEntity.java
@@ -0,0 +1,77 @@
+package io.quarkus.hibernate.panache.managed.blocking;
+
+import java.util.Map;
+import java.util.stream.Stream;
+
+import jakarta.json.bind.annotation.JsonbTransient;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+import io.quarkus.hibernate.panache.managed.PanacheManagedEntityOperations;
+import io.quarkus.hibernate.panache.runtime.spi.PanacheBlockingOperations;
+import io.quarkus.hibernate.panache.runtime.spi.PanacheOperations;
+import io.quarkus.panache.common.Parameters;
+
+public interface PanacheManagedBlockingEntity extends PanacheManagedEntityOperations {
+
+ private PanacheBlockingOperations operations() {
+ return PanacheOperations.getBlockingManaged();
+ }
+
+ /**
+ * Persist this entity in the database, if not already persisted. This will set your ID field if it is not already set.
+ *
+ * @see #isPersistent()
+ * @see #persist(Iterable)
+ * @see #persist(Stream)
+ * @see #persist(Object, Object...)
+ */
+ @Override
+ public default Void persist() {
+ return operations().persist(this);
+ }
+
+ /**
+ * Persist this entity in the database, if not already persisted. This will set your ID field if it is not already set.
+ * Then flushes all pending changes to the database.
+ *
+ * @see #isPersistent()
+ * @see #persist(Iterable)
+ * @see #persist(Stream)
+ * @see #persist(Object, Object...)
+ */
+ @Override
+ public default Void persistAndFlush() {
+ return operations().persistAndFlush(this);
+ }
+
+ /**
+ * Delete this entity from the database, if it is already persisted.
+ *
+ * @see #isPersistent()
+ * @see #delete(String, Object...)
+ * @see #delete(String, Map)
+ * @see #delete(String, Parameters)
+ * @see #deleteAll()
+ */
+ @Override
+ public default Void delete() {
+ return operations().delete(this);
+ }
+
+ /**
+ * Returns true if this entity is persistent in the database. If yes, all modifications to
+ * its persistent fields will be automatically committed to the database at transaction
+ * commit time.
+ *
+ * @return true if this entity is persistent in the database.
+ */
+ @JsonbTransient
+ // @JsonIgnore is here to avoid serialization of this property with jackson
+ @JsonIgnore
+ @Override
+ public default Boolean isPersistent() {
+ return operations().isPersistent(this);
+ }
+
+}
diff --git a/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/blocking/PanacheManagedBlockingRepository.java b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/blocking/PanacheManagedBlockingRepository.java
new file mode 100644
index 0000000000000..ef00cd271e932
--- /dev/null
+++ b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/blocking/PanacheManagedBlockingRepository.java
@@ -0,0 +1,5 @@
+package io.quarkus.hibernate.panache.managed.blocking;
+
+public interface PanacheManagedBlockingRepository extends PanacheManagedBlockingRepositoryBase {
+
+}
diff --git a/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/blocking/PanacheManagedBlockingRepositoryBase.java b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/blocking/PanacheManagedBlockingRepositoryBase.java
new file mode 100644
index 0000000000000..cefbf8b6a76b2
--- /dev/null
+++ b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/blocking/PanacheManagedBlockingRepositoryBase.java
@@ -0,0 +1,10 @@
+package io.quarkus.hibernate.panache.managed.blocking;
+
+import io.quarkus.hibernate.panache.PanacheRepositorySwitcher;
+
+public interface PanacheManagedBlockingRepositoryBase
+ extends PanacheManagedBlockingRepositoryOperations,
+ PanacheManagedBlockingRepositoryQueries,
+ PanacheRepositorySwitcher {
+
+}
diff --git a/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/blocking/PanacheManagedBlockingRepositoryOperations.java b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/blocking/PanacheManagedBlockingRepositoryOperations.java
new file mode 100644
index 0000000000000..39aa3af302401
--- /dev/null
+++ b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/blocking/PanacheManagedBlockingRepositoryOperations.java
@@ -0,0 +1,129 @@
+package io.quarkus.hibernate.panache.managed.blocking;
+
+import java.util.Map;
+import java.util.stream.Stream;
+
+import org.hibernate.Session;
+
+import io.quarkus.hibernate.orm.panache.common.runtime.AbstractJpaOperations;
+import io.quarkus.hibernate.panache.managed.PanacheManagedRepositoryOperations;
+import io.quarkus.hibernate.panache.runtime.spi.PanacheBlockingOperations;
+import io.quarkus.hibernate.panache.runtime.spi.PanacheOperations;
+
+public interface PanacheManagedBlockingRepositoryOperations
+ extends PanacheManagedRepositoryOperations {
+
+ private Class extends Entity> getEntityClass() {
+ return AbstractJpaOperations.getRepositoryEntityClass(getClass());
+ }
+
+ private PanacheBlockingOperations operations() {
+ return PanacheOperations.getBlockingManaged();
+ }
+
+ // Operations
+
+ /**
+ * Returns the {@link Session} for the entity class for extra operations (eg. CriteriaQueries)
+ *
+ * @return the {@link Session} for the entity class
+ */
+ default Session getSession() {
+ return operations().getSession(getEntityClass());
+ }
+
+ /**
+ * Persist the given entity in the database, if not already persisted.
+ *
+ * @param entity the entity to persist.
+ * @see #isPersistent(Object)
+ * @see #persist(Iterable)
+ * @see #persist(Stream)
+ * @see #persist(Object, Object...)
+ */
+ default Void persist(Entity entity) {
+ return operations().persist(entity);
+ }
+
+ /**
+ * Persist the given entity in the database, if not already persisted.
+ * Then flushes all pending changes to the database.
+ *
+ * @param entity the entity to persist.
+ * @see #isPersistent(Object)
+ * @see #persist(Iterable)
+ * @see #persist(Stream)
+ * @see #persist(Object, Object...)
+ */
+ default Void persistAndFlush(Entity entity) {
+ return operations().persistAndFlush(entity);
+ }
+
+ /**
+ * Delete the given entity from the database, if it is already persisted.
+ *
+ * @param entity the entity to delete.
+ * @see #isPersistent(Object)
+ * @see #delete(String, Object...)
+ * @see #delete(String, Map)
+ * @see #deleteAll()
+ */
+ default Void delete(Entity entity) {
+ return operations().delete(entity);
+ }
+
+ /**
+ * Returns true if the given entity is persistent in the database. If yes, all modifications to
+ * its persistent fields will be automatically committed to the database at transaction
+ * commit time.
+ *
+ * @param entity the entity to check
+ * @return true if the entity is persistent in the database.
+ */
+ default Boolean isPersistent(Entity entity) {
+ return operations().isPersistent(entity);
+ }
+
+ /**
+ * Flushes all pending changes to the database using the Session for the entity class.
+ */
+ default Void flush() {
+ return operations().flush(getEntityClass());
+ }
+
+ /**
+ * Persist all given entities.
+ *
+ * @param entities the entities to persist
+ * @see #persist(Object)
+ * @see #persist(Stream)
+ * @see #persist(Object,Object...)
+ */
+ default Void persist(Iterable entities) {
+ return operations().persist(entities);
+ }
+
+ /**
+ * Persist all given entities.
+ *
+ * @param entities the entities to persist
+ * @see #persist(Object)
+ * @see #persist(Iterable)
+ * @see #persist(Object,Object...)
+ */
+ default Void persist(Stream entities) {
+ return operations().persist(entities);
+ }
+
+ /**
+ * Persist all given entities.
+ *
+ * @param entities the entities to persist
+ * @see #persist(Object)
+ * @see #persist(Stream)
+ * @see #persist(Iterable)
+ */
+ default Void persist(Entity firstEntity, @SuppressWarnings("unchecked") Entity... entities) {
+ return operations().persist(firstEntity, entities);
+ }
+}
diff --git a/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/blocking/PanacheManagedBlockingRepositoryQueries.java b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/blocking/PanacheManagedBlockingRepositoryQueries.java
new file mode 100644
index 0000000000000..0bc6e2ae498dc
--- /dev/null
+++ b/extensions/panache/hibernate-panache/runtime/src/main/java/io/quarkus/hibernate/panache/managed/blocking/PanacheManagedBlockingRepositoryQueries.java
@@ -0,0 +1,180 @@
+package io.quarkus.hibernate.panache.managed.blocking;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import jakarta.persistence.LockModeType;
+
+import io.quarkus.hibernate.orm.panache.common.runtime.AbstractJpaOperations;
+import io.quarkus.hibernate.panache.blocking.PanacheBlockingQuery;
+import io.quarkus.hibernate.panache.blocking.PanacheRepositoryBlockingQueries;
+import io.quarkus.hibernate.panache.runtime.spi.PanacheBlockingOperations;
+import io.quarkus.hibernate.panache.runtime.spi.PanacheOperations;
+import io.quarkus.panache.common.Sort;
+
+public interface PanacheManagedBlockingRepositoryQueries extends PanacheRepositoryBlockingQueries {
+ private Class extends Entity> getEntityClass() {
+ return AbstractJpaOperations.getRepositoryEntityClass(getClass());
+ }
+
+ private PanacheBlockingOperations operations() {
+ return PanacheOperations.getBlockingManaged();
+ }
+
+ @Override
+ default Entity findById(Id id) {
+ return (Entity) operations().findById(getEntityClass(), id);
+ }
+
+ @Override
+ default Entity findById(Id id, LockModeType lockModeType) {
+ return (Entity) operations().findById(getEntityClass(), id, lockModeType);
+ }
+
+ @Override
+ default Optional findByIdOptional(Id id) {
+ return (Optional) operations().findByIdOptional(getEntityClass(), id);
+ }
+
+ @Override
+ default Optional findByIdOptional(Id id, LockModeType lockModeType) {
+ return (Optional) operations().findByIdOptional(getEntityClass(), id, lockModeType);
+ }
+
+ @Override
+ default PanacheBlockingQuery