ProjectionQuery

Summary

Executing Queries

After defining your projection and applying filters, sorting, or pagination, the next step is to execute the query and retrieve the results.

  1. For all the following examples, consider that we have a Customer entity and an associated projection CustomerProjection, as defined in the Definition of Projection section.
  2. In the following examples, we assume a JPA context in which the ProjectionProcessor receives an EntityManager instance, responsible for executing the queries.

Basic execution ↑

To execute a query, you can use the execute method of the ProjectionProcessor class. This method accepts either a projection class or a ProjectionQuery instance and returns the results according to the projection definition.

ProjectionProcessor processor = new ProjectionProcessor(entityManager);
List<CustomerProjection> customers = processor.execute(CustomerProjection.class);

In this example, the execute method is called with the projection class CustomerProjection, and it will return a list of CustomerProjection objects containing the projected data.


Execution with ProjectionQuery ↑

If you are using the ProjectionQuery class to build your query, the execution process is similar. You can pass the ProjectionQuery instance to the execute method of the ProjectionProcessor.

ProjectionProcessor processor = new ProjectionProcessor(entityManager);

ProjectionQuery<Customer, CustomerProjection> query = ProjectionQuery
    .fromTo(Customer.class, CustomerProjection.class)
    .filter("age", "greater_than", 18)
    .order("name", OrderDirection.ASC)
    .paging(0, 20)
    .distinct();

List<CustomerProjection> customers = processor.execute(query);

Paginated Execution ↑

If you want to obtain the results in paginated format, you can use the executePageable method of the ProjectionProcessor, which returns a ProjectionPage object containing the results and pagination information.

ProjectionProcessor processor = new ProjectionProcessor(entityManager);

ProjectionQuery<Customer, CustomerProjection> query = ProjectionQuery
        .fromTo(Customer.class, CustomerProjection.class)
        .filter("age", "greater_than", 18)
        .order("name", OrderDirection.ASC)
        .paging(0, 20)
        .distinct();

ProjectionPage<CustomerProjection> page = processor.executePageable(query);

ProjectionPage contains the result list along with pagination metadata, such as the total number of records, current page index, page size, and related information.

executePageable requires paging(first, size); otherwise, it throws IllegalStateException. The first argument is a zero-based row offset, not a page number. Use a stable sort order, such as name followed by the unique id, when paging.

List<CustomerProjection> content = page.content();
long totalElements = page.totalElements();
int pageNumber = page.pageNumber();
int pageSize = page.pageSize();
int totalPages = page.totalPages();
boolean hasNext = page.hasNext();
boolean hasPrevious = page.hasPrevious();

pageNumber() is zero-based and derived from first / size.

The processor fetches the requested page first and runs a count query only if that page is nonempty. In version 3.6.0, an empty page returns totalElements = 0 without counting, including when the offset is beyond the available results. An empty page therefore does not establish that no earlier rows match.

Use execute(query) when you only need the limited result list and do not need a count query.


← Previous: Pagination and Sorting · ↑ Back to top · Next → Custom Select Handlers