diff --git a/docs/src/main/asciidoc/rest-data-panache.adoc b/docs/src/main/asciidoc/rest-data-panache.adoc
index c3e931ec0de92..7846ecc2c62fd 100644
--- a/docs/src/main/asciidoc/rest-data-panache.adoc
+++ b/docs/src/main/asciidoc/rest-data-panache.adoc
@@ -371,6 +371,7 @@ It applies to the paged resources only and is a number starting with 1. Default
 * `sort` - a comma separated list of fields which should be used for sorting a result of a list operation.
 Fields are sorted in the ascending order unless they're prefixed with a `-`.
 E.g. `?sort=name,-age` will sort the result by the name ascending by the age descending.
+* `namedQuery` - a named query that should be configured at entity level using the annotation `@NamedQuery`.
 
 For example, if you want to get two `People` entities in the first page, you should call `http://localhost:8080/people?page=0&size=2`, and the response should look like:
 
@@ -405,6 +406,25 @@ Additionally, you can also filter by the entity fields by adding a query param w
 
 IMPORTANT: Filtering by fields is only supported for primitive types.
 
+== Complex filtering to list entities using @NamedQuery
+
+You can specify a named query to filter when listing the entities. For example, having the following named query in your entity:
+
+[source,java]
+----
+@Entity
+@NamedQuery(name = "Person.containsInName", query = "from Person where name like CONCAT('%', CONCAT(:name, '%'))")
+public class Person extends PanacheEntity {
+  String name;
+}
+----
+
+In this example, we have added a named query to list all the persons that contains some text in the `name` field. 
+
+Next, we can set a query param `namedQuery` when listing the entities using the generated resource with the name of the named query that we want to use, for example, calling `http://localhost:8080/people?namedQuery=Person.containsInName&name=ter` would return all the persons which name contains the text "ter".
+
+For more information about how named queries work, go to https://quarkus.io/guides/hibernate-orm-panache#named-queries[the Hibernate ORM guide] or to https://quarkus.io/guides/hibernate-reactive-panache#named-queries[the Hibernate Reactive guide].
+
 == Resource Method Before/After Listeners
 
 REST Data with Panache supports the subscription to the following resource method hooks: 
diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/AbstractGetMethodTest.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/AbstractGetMethodTest.java
index 769ca585a5edb..4f9dd7823d60c 100644
--- a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/AbstractGetMethodTest.java
+++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/AbstractGetMethodTest.java
@@ -109,6 +109,18 @@ void shouldListWithManyFilters() {
                 .and().body("name", contains("first"));
     }
 
+    @Test
+    void shouldListWithNamedQuery() {
+        given().accept("application/json")
+                .when()
+                .queryParam("name", "s")
+                .queryParam("namedQuery", "Item.containsInName")
+                .get("/items")
+                .then().statusCode(200)
+                .and().body("id", contains(1, 2))
+                .and().body("name", contains("first", "second"));
+    }
+
     @Test
     void shouldListSimpleHalObjects() {
         given().accept("application/hal+json")
diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/Item.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/Item.java
index a1f94de46c346..1b69b84afb9d2 100644
--- a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/Item.java
+++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/entity/Item.java
@@ -1,8 +1,10 @@
 package io.quarkus.hibernate.orm.rest.data.panache.deployment.entity;
 
 import javax.persistence.Entity;
+import javax.persistence.NamedQuery;
 
 @Entity
+@NamedQuery(name = "Item.containsInName", query = "from Item where name like CONCAT('%', CONCAT(:name, '%'))")
 public class Item extends AbstractItem<Long> {
 
 }
diff --git a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/repository/Item.java b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/repository/Item.java
index 86a46ea9cee76..da0e9cb0d59eb 100644
--- a/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/repository/Item.java
+++ b/extensions/panache/hibernate-orm-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/orm/rest/data/panache/deployment/repository/Item.java
@@ -1,8 +1,10 @@
 package io.quarkus.hibernate.orm.rest.data.panache.deployment.repository;
 
 import javax.persistence.Entity;
+import javax.persistence.NamedQuery;
 
 @Entity
+@NamedQuery(name = "Item.containsInName", query = "from Item where name like CONCAT('%', CONCAT(:name, '%'))")
 public class Item extends AbstractItem<Long> {
 
 }
diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/AbstractGetMethodTest.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/AbstractGetMethodTest.java
index ab2776bd0dcbb..ca6ebebabacd4 100644
--- a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/AbstractGetMethodTest.java
+++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/AbstractGetMethodTest.java
@@ -109,6 +109,18 @@ void shouldListWithManyFilters() {
                 .and().body("name", contains("first"));
     }
 
+    @Test
+    void shouldListWithNamedQuery() {
+        given().accept("application/json")
+                .when()
+                .queryParam("name", "s")
+                .queryParam("namedQuery", "Item.containsInName")
+                .get("/items")
+                .then().statusCode(200)
+                .and().body("id", contains(1, 2))
+                .and().body("name", contains("first", "second"));
+    }
+
     @Test
     void shouldListSimpleHalObjects() {
         given().accept("application/hal+json")
diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/Item.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/Item.java
index e5dc5a8edf83a..1dafc18413e99 100644
--- a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/Item.java
+++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/entity/Item.java
@@ -1,8 +1,10 @@
 package io.quarkus.hibernate.reactive.rest.data.panache.deployment.entity;
 
 import javax.persistence.Entity;
+import javax.persistence.NamedQuery;
 
 @Entity
+@NamedQuery(name = "Item.containsInName", query = "from Item where name like CONCAT('%', CONCAT(:name, '%'))")
 public class Item extends AbstractItem<Long> {
 
 }
diff --git a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/repository/Item.java b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/repository/Item.java
index 803a5ab96e13c..c380ccc0406e1 100644
--- a/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/repository/Item.java
+++ b/extensions/panache/hibernate-reactive-rest-data-panache/deployment/src/test/java/io/quarkus/hibernate/reactive/rest/data/panache/deployment/repository/Item.java
@@ -1,8 +1,10 @@
 package io.quarkus.hibernate.reactive.rest.data.panache.deployment.repository;
 
 import javax.persistence.Entity;
+import javax.persistence.NamedQuery;
 
 @Entity
+@NamedQuery(name = "Item.containsInName", query = "from Item where name like CONCAT('%', CONCAT(:name, '%'))")
 public class Item extends AbstractItem<Long> {
 
 }
diff --git a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/ListMethodImplementor.java b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/ListMethodImplementor.java
index 784d0c55b3108..42d513e83eef5 100644
--- a/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/ListMethodImplementor.java
+++ b/extensions/panache/rest-data-panache/deployment/src/main/java/io/quarkus/rest/data/panache/deployment/methods/ListMethodImplementor.java
@@ -28,6 +28,8 @@
 
 import io.quarkus.deployment.Capabilities;
 import io.quarkus.gizmo.AnnotatedElement;
+import io.quarkus.gizmo.AssignableResultHandle;
+import io.quarkus.gizmo.BranchResult;
 import io.quarkus.gizmo.BytecodeCreator;
 import io.quarkus.gizmo.ClassCreator;
 import io.quarkus.gizmo.FieldDescriptor;
@@ -174,6 +176,7 @@ private void implementPaged(ClassCreator classCreator, ResourceMetadata resource
         parameters.add(param("page", int.class));
         parameters.add(param("size", int.class));
         parameters.add(param("uriInfo", UriInfo.class));
+        parameters.add(param("namedQuery", String.class));
         parameters.addAll(compatibleFieldsForQuery);
         MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(getMethodName(), classCreator,
                 isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()),
@@ -194,8 +197,9 @@ private void implementPaged(ClassCreator classCreator, ResourceMetadata resource
         addQueryParamAnnotation(methodCreator.getParameterAnnotations(2), "size");
         addDefaultValueAnnotation(methodCreator.getParameterAnnotations(2), Integer.toString(DEFAULT_PAGE_SIZE));
         addContextAnnotation(methodCreator.getParameterAnnotations(3));
+        addQueryParamAnnotation(methodCreator.getParameterAnnotations(4), "namedQuery");
         Map<String, ResultHandle> fieldValues = new HashMap<>();
-        int index = 4;
+        int index = 5;
         for (SignatureMethodCreator.Parameter param : compatibleFieldsForQuery) {
             addQueryParamAnnotation(methodCreator.getParameterAnnotations(index), param.getName());
             fieldValues.put(param.getName(), methodCreator.getMethodParam(index));
@@ -209,6 +213,7 @@ private void implementPaged(ClassCreator classCreator, ResourceMetadata resource
         ResultHandle pageSize = methodCreator.getMethodParam(2);
         ResultHandle page = paginationImplementor.getPage(methodCreator, pageIndex, pageSize);
         ResultHandle uriInfo = methodCreator.getMethodParam(3);
+        ResultHandle namedQuery = methodCreator.getMethodParam(4);
 
         if (isNotReactivePanache()) {
             TryBlock tryBlock = implementTryBlock(methodCreator, EXCEPTION_MESSAGE);
@@ -219,7 +224,7 @@ private void implementPaged(ClassCreator classCreator, ResourceMetadata resource
                     resource, page);
 
             ResultHandle links = paginationImplementor.getLinks(tryBlock, uriInfo, page, pageCount);
-            ResultHandle entities = list(tryBlock, resourceMetadata, resource, page, sort, fieldValues);
+            ResultHandle entities = list(tryBlock, resourceMetadata, resource, page, sort, namedQuery, fieldValues);
 
             // Return response
             returnValueWithLinks(tryBlock, resourceMetadata, resourceProperties, entities, links);
@@ -234,7 +239,7 @@ private void implementPaged(ClassCreator classCreator, ResourceMetadata resource
                     (body, pageCount) -> {
                         ResultHandle pageCountAsInt = body.checkCast(pageCount, Integer.class);
                         ResultHandle links = paginationImplementor.getLinks(body, uriInfo, page, pageCountAsInt);
-                        ResultHandle uniEntities = list(body, resourceMetadata, resource, page, sort, fieldValues);
+                        ResultHandle uniEntities = list(body, resourceMetadata, resource, page, sort, namedQuery, fieldValues);
                         body.returnValue(UniImplementor.map(body, uniEntities, EXCEPTION_MESSAGE,
                                 (listBody, list) -> returnValueWithLinks(listBody, resourceMetadata, resourceProperties, list,
                                         links)));
@@ -257,6 +262,7 @@ private void implementNotPaged(ClassCreator classCreator, ResourceMetadata resou
         Collection<SignatureMethodCreator.Parameter> compatibleFieldsForQuery = getFieldsToQuery(resourceMetadata);
         List<SignatureMethodCreator.Parameter> parameters = new ArrayList<>();
         parameters.add(param("sort", List.class));
+        parameters.add(param("namedQuery", String.class));
         parameters.addAll(compatibleFieldsForQuery);
         MethodCreator methodCreator = SignatureMethodCreator.getMethodCreator(getMethodName(), classCreator,
                 isNotReactivePanache() ? ofType(Response.class) : ofType(Uni.class, resourceMetadata.getEntityType()),
@@ -271,8 +277,9 @@ private void implementNotPaged(ClassCreator classCreator, ResourceMetadata resou
         addOpenApiResponseAnnotation(methodCreator, Response.Status.OK, resourceMetadata.getEntityType(), true);
         addSecurityAnnotations(methodCreator, resourceProperties);
         addQueryParamAnnotation(methodCreator.getParameterAnnotations(0), "sort");
+        addQueryParamAnnotation(methodCreator.getParameterAnnotations(1), "namedQuery");
         Map<String, ResultHandle> fieldValues = new HashMap<>();
-        int index = 1;
+        int index = 2;
         for (SignatureMethodCreator.Parameter param : compatibleFieldsForQuery) {
             addQueryParamAnnotation(methodCreator.getParameterAnnotations(index), param.getName());
             fieldValues.put(param.getName(), methodCreator.getMethodParam(index));
@@ -280,17 +287,18 @@ private void implementNotPaged(ClassCreator classCreator, ResourceMetadata resou
         }
 
         ResultHandle sortQuery = methodCreator.getMethodParam(0);
+        ResultHandle namedQuery = methodCreator.getMethodParam(1);
         ResultHandle sort = sortImplementor.getSort(methodCreator, sortQuery);
         ResultHandle resource = methodCreator.readInstanceField(resourceFieldDescriptor, methodCreator.getThis());
 
         if (isNotReactivePanache()) {
             TryBlock tryBlock = implementTryBlock(methodCreator, EXCEPTION_MESSAGE);
-            ResultHandle entities = list(tryBlock, resourceMetadata, resource, null, sort, fieldValues);
+            ResultHandle entities = list(tryBlock, resourceMetadata, resource, null, sort, namedQuery, fieldValues);
             returnValue(tryBlock, resourceMetadata, resourceProperties, entities);
             tryBlock.close();
         } else {
             ResultHandle uniEntities = list(methodCreator, resourceMetadata, resource, methodCreator.loadNull(), sort,
-                    fieldValues);
+                    namedQuery, fieldValues);
             methodCreator.returnValue(UniImplementor.map(methodCreator, uniEntities, EXCEPTION_MESSAGE,
                     (body, entities) -> returnValue(body, resourceMetadata, resourceProperties, entities)));
         }
@@ -299,7 +307,8 @@ private void implementNotPaged(ClassCreator classCreator, ResourceMetadata resou
     }
 
     public ResultHandle list(BytecodeCreator creator, ResourceMetadata resourceMetadata, ResultHandle resource,
-            ResultHandle page, ResultHandle sort, Map<String, ResultHandle> fieldValues) {
+            ResultHandle page, ResultHandle sort, ResultHandle namedQuery, Map<String, ResultHandle> fieldValues) {
+
         ResultHandle dataParams = creator.newInstance(ofConstructor(HashMap.class));
         ResultHandle queryList = creator.newInstance(ofConstructor(ArrayList.class));
         for (Map.Entry<String, ResultHandle> field : fieldValues.entrySet()) {
@@ -313,13 +322,29 @@ public ResultHandle list(BytecodeCreator creator, ResourceMetadata resourceMetad
                     dataParams, fieldValueFromQueryIsSet.load(fieldName), fieldValueFromQuery);
         }
 
+        /**
+         * String query;
+         * if (namedQuery != null) {
+         * query = "#" + namedQuery;
+         * } else {
+         * query = String.join(" AND ", queryList);
+         * }
+         */
+        AssignableResultHandle query = creator.createVariable(String.class);
+        BranchResult checkIfNamedQueryIsNull = creator.ifNull(namedQuery);
+        BytecodeCreator whenNamedQueryIsNull = checkIfNamedQueryIsNull.trueBranch();
+        BytecodeCreator whenNamedQueryIsNotNull = checkIfNamedQueryIsNull.falseBranch();
+        whenNamedQueryIsNotNull.assign(query, whenNamedQueryIsNotNull.invokeVirtualMethod(
+                ofMethod(String.class, "concat", String.class, String.class),
+                whenNamedQueryIsNotNull.load("#"), namedQuery));
+        whenNamedQueryIsNull.assign(query, whenNamedQueryIsNull.invokeStaticMethod(
+                ofMethod(String.class, "join", String.class, CharSequence.class, Iterable.class),
+                creator.load(" AND "), queryList));
+
         return creator.invokeVirtualMethod(
                 ofMethod(resourceMetadata.getResourceClass(), "list", isNotReactivePanache() ? List.class : Uni.class,
                         Page.class, Sort.class, String.class, Map.class),
-                resource, page == null ? creator.loadNull() : page, sort,
-                creator.invokeStaticMethod(ofMethod(String.class, "join", String.class, CharSequence.class, Iterable.class),
-                        creator.load(" AND "), queryList),
-                dataParams);
+                resource, page == null ? creator.loadNull() : page, sort, query, dataParams);
     }
 
     private boolean isFieldTypeCompatibleForQueryParam(Type fieldType) {