diff --git a/extensions/panache/hibernate-orm-panache/runtime/src/main/java/io/quarkus/hibernate/orm/panache/PanacheQuery.java b/extensions/panache/hibernate-orm-panache/runtime/src/main/java/io/quarkus/hibernate/orm/panache/PanacheQuery.java
index d7a07e580dd96..c8c6c6d8fadc0 100644
--- a/extensions/panache/hibernate-orm-panache/runtime/src/main/java/io/quarkus/hibernate/orm/panache/PanacheQuery.java
+++ b/extensions/panache/hibernate-orm-panache/runtime/src/main/java/io/quarkus/hibernate/orm/panache/PanacheQuery.java
@@ -12,8 +12,10 @@
import org.hibernate.Session;
import org.hibernate.annotations.FilterDef;
+import io.quarkus.hibernate.orm.panache.common.ProjectedFieldName;
import io.quarkus.panache.common.Page;
import io.quarkus.panache.common.Parameters;
+import io.quarkus.panache.common.exception.PanacheQueryException;
/**
*
@@ -33,10 +35,29 @@ public interface PanacheQuery {
// Builder
/**
- * Defines a projection class: the getters, and the public fields, will be used to restrict which fields should be
- * retrieved from the database.
+ * 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 a named query, we throw a {@link PanacheQueryException}
+ * - If this is already a project query of the form
select distinct? new…
, we throw a
+ * {@link PanacheQueryException}
*
- * @return a new query with the same state as the previous one (params, page, range, lockMode, hints, ...).
+ * @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 a named query or an already-projected query
*/
public PanacheQuery project(Class type);
diff --git a/extensions/panache/hibernate-reactive-panache/runtime/src/main/java/io/quarkus/hibernate/reactive/panache/PanacheQuery.java b/extensions/panache/hibernate-reactive-panache/runtime/src/main/java/io/quarkus/hibernate/reactive/panache/PanacheQuery.java
index 7ce81efb0a749..7ac8dc2256be7 100644
--- a/extensions/panache/hibernate-reactive-panache/runtime/src/main/java/io/quarkus/hibernate/reactive/panache/PanacheQuery.java
+++ b/extensions/panache/hibernate-reactive-panache/runtime/src/main/java/io/quarkus/hibernate/reactive/panache/PanacheQuery.java
@@ -10,8 +10,10 @@
import org.hibernate.Session;
import org.hibernate.annotations.FilterDef;
+import io.quarkus.hibernate.reactive.panache.common.ProjectedFieldName;
import io.quarkus.panache.common.Page;
import io.quarkus.panache.common.Parameters;
+import io.quarkus.panache.common.exception.PanacheQueryException;
import io.smallrye.common.annotation.CheckReturnValue;
import io.smallrye.mutiny.Uni;
@@ -33,10 +35,29 @@ public interface PanacheQuery {
// Builder
/**
- * Defines a projection class: the getters, and the public fields, will be used to restrict which fields should be
- * retrieved from the database.
+ * 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 a named query, we throw a {@link PanacheQueryException}
+ * - If this is already a project query of the form
select distinct? new…
, we throw a
+ * {@link PanacheQueryException}
*
- * @return a new query with the same state as the previous one (params, page, range, lockMode, hints, ...).
+ * @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 a named query or an already-projected query
*/
public PanacheQuery project(Class type);