com.blazebit.persistence.FullQueryBuilder Maven / Gradle / Ivy
/*
* Copyright 2014 - 2019 Blazebit.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.blazebit.persistence;
import javax.persistence.TypedQuery;
import java.lang.reflect.Constructor;
/**
* A base interface for builders that support normal query functionality.
* This interface is shared between the criteria builder and paginated criteria builder.
*
* @param The query result type
* @param The concrete builder type
* @author Christian Beikov
* @since 1.1.0
*/
public interface FullQueryBuilder> extends QueryBuilder, FetchBuilder {
/**
* Copies this query builder into a new one, using it's projection as an overridable default.
*
* @param resultClass The result class of the query
* @param The type of the result class
* @return A new query builder
* @since 1.2.0
*/
public FullQueryBuilder copy(Class resultClass);
/**
* Returns a query that counts the results that would be produced if the current query was run.
*
* @return A query for determining the count of the result list represented by this query builder
* @since 1.2.0
*/
public TypedQuery getCountQuery();
/**
* Returns the query string that selects the count of elements.
*
* @return The query string
* @since 1.3.0
*/
public String getCountQueryString();
/**
* Invokes {@link FullQueryBuilder#pageBy(int, int, String, String...)} with the identifiers of the query root entity.
*
* @param firstResult The position of the first result to retrieve, numbered from 0
* @param maxResults The maximum number of results to retrieve
* @return This query builder as paginated query builder
*/
public PaginatedCriteriaBuilder page(int firstResult, int maxResults);
/**
* Invokes {@link FullQueryBuilder#pageByAndNavigate(Object, int, String, String...)} with the identifiers of the query root entity.
*
* @deprecated This method causes a method resolution ambiguity. Use {{@link #pageAndNavigate(Object, int)}} instead.
* @param entityId The id of the entity which should be located on the page
* @param maxResults The maximum number of results to retrieve
* @return This query builder as paginated query builder
*/
@Deprecated
public PaginatedCriteriaBuilder page(Object entityId, int maxResults);
/**
* Invokes {@link FullQueryBuilder#pageByAndNavigate(Object, int, String, String...)} with the identifiers of the query root entity.
*
* @param entityId The id of the entity which should be located on the page
* @param maxResults The maximum number of results to retrieve
* @return This query builder as paginated query builder
* @since 1.3.0
*/
public PaginatedCriteriaBuilder pageAndNavigate(Object entityId, int maxResults);
/**
* Invokes {@link FullQueryBuilder#pageBy(KeysetPage, int, int, String, String...)} with the identifiers of the query root entity.
*
* @param keysetPage The key set from a previous result, may be null
* @param firstResult The position of the first result to retrieve, numbered from 0
* @param maxResults The maximum number of results to retrieve
* @return This query builder as paginated query builder
* @see PagedList#getKeysetPage()
*/
public PaginatedCriteriaBuilder page(KeysetPage keysetPage, int firstResult, int maxResults);
/**
* Like {@link FullQueryBuilder#pageBy(int, int, String, String...)} but lacks the varargs parameter to avoid heap pollution.
*
* @param firstResult The position of the first result to retrieve, numbered from 0
* @param maxResults The maximum number of results to retrieve
* @param identifierExpression The first identifier expression
* @return This query builder as paginated query builder
* @since 1.3.0
*/
public PaginatedCriteriaBuilder pageBy(int firstResult, int maxResults, String identifierExpression);
/**
* Like {@link FullQueryBuilder#pageByAndNavigate(Object, int, String, String...)} but lacks the varargs parameter to avoid heap pollution.
*
* @param entityId The id of the entity which should be located on the page
* @param maxResults The maximum number of results to retrieve
* @param identifierExpression The first identifier expression
* @return This query builder as paginated query builder
* @since 1.3.0
*/
public PaginatedCriteriaBuilder pageByAndNavigate(Object entityId, int maxResults, String identifierExpression);
/**
* Like {@link FullQueryBuilder#pageBy(KeysetPage, int, int, String, String...)} but lacks the varargs parameter to avoid heap pollution.
*
* @param keysetPage The key set from a previous result, may be null
* @param firstResult The position of the first result to retrieve, numbered from 0
* @param maxResults The maximum number of results to retrieve
* @param identifierExpression The first identifier expression
* @return This query builder as paginated query builder
* @since 1.3.0
* @see PagedList#getKeysetPage()
*/
public PaginatedCriteriaBuilder pageBy(KeysetPage keysetPage, int firstResult, int maxResults, String identifierExpression);
/**
* Paginates the results of this query based on the given identifier expressions.
*
* In JPA, the use of setFirstResult
and setMaxResults
is not defined when involving fetch joins for collections.
* When no collection joins are involved, this is fine as rows essentially represent objects, but when collections are joined, this is no longer true.
* JPA providers usually fall back to querying all data and doing pagination in-memory based on objects or simply don't support that kind of query.
*
* This API allows to specify the identifier expressions to use for pagination and transparently handles collection join support.
* The big advantage of this API over plain setFirstResult
and setMaxResults
can also be seen when doing scalar queries.
*
*
* An example for such queries would be a query that joins a collection:
*
* SELECT d.id, contacts.name FROM Document d LEFT JOIN d.contacts contacts
*
* If one Document
has associated multiple contacts, the above query will produce multiple result set rows for that document.
* Paginating via setFirstResult
and setMaxResults
would produce unexpected results whereas using this API, will produce the expected results.
*
*
*
* When paginating on the identifier i.e. d.id
, the results are implicitly grouped by the document id and distinct. Therefore calling
* distinct() on a PaginatedCriteriaBuilder is not allowed.
*
*
* @param firstResult The position of the first result to retrieve, numbered from 0
* @param maxResults The maximum number of results to retrieve
* @param identifierExpression The first identifier expression
* @param identifierExpressions The other identifier expressions
* @return This query builder as paginated query builder
* @since 1.3.0
*/
public PaginatedCriteriaBuilder pageBy(int firstResult, int maxResults, String identifierExpression, String... identifierExpressions);
/**
* Paginates the results of this query and navigates to the page on which
* the object with the given identifier is located.
*
* Beware that the same limitations like for {@link FullQueryBuilder#page(int, int)} apply.
* If the object with the given identifier does not exist in the result list:
*
* - The result of {@link PaginatedCriteriaBuilder#getResultList()} will contain the first page
* - {@link PagedList#getFirstResult()} will return
-1
*
*
* @param entityId The id of the object which should be located on the page
* @param maxResults The maximum number of results to retrieve
* @param identifierExpression The first identifier expression
* @param identifierExpressions The other identifier expressions
* @return This query builder as paginated query builder
* @since 1.3.0
*/
public PaginatedCriteriaBuilder pageByAndNavigate(Object entityId, int maxResults, String identifierExpression, String... identifierExpressions);
/**
* Like {@link FullQueryBuilder#page(int, int)} but additionally uses key set pagination when possible.
*
* Beware that keyset pagination should not be used as a direct replacement for offset pagination.
* Since entries that have a lower rank than some keyset might be added or removed, the calculations
* for the firstResult might be wrong. If strict pagination is required, then the {@link KeysetPage} should
* not be used when the count of lower ranked items changes which will result in the use of offset pagination for that request.
*
*
* Key set pagination is possible if and only if the following conditions are met:
*
* - The keyset reference values fit the order by expressions of this query builder AND
* - {@link KeysetPage#getMaxResults()} and
maxResults
evaluate to the same value AND
* - One of the following conditions is met:
*
* - The absolute value of {@link KeysetPage#getFirstResult()}
- firstResult
is 0
* - The absolute value of {@link KeysetPage#getFirstResult()}
- firstResult
is equal to the value of
* maxResults
*
*
*
*
*
* @param keysetPage The key set from a previous result, may be null
* @param firstResult The position of the first result to retrieve, numbered from 0
* @param maxResults The maximum number of results to retrieve
* @param identifierExpression The first identifier expression
* @param identifierExpressions The other identifier expressions
* @return This query builder as paginated query builder
* @since 1.3.0
* @see PagedList#getKeysetPage()
*/
public PaginatedCriteriaBuilder pageBy(KeysetPage keysetPage, int firstResult, int maxResults, String identifierExpression, String... identifierExpressions);
/*
* Join methods
*/
/**
* Adds a join to the query, possibly specializing implicit joins, and giving the joined element an alias.
* If fetch is set to true, a join fetch will be added.
*
* @param path The path to join
* @param alias The alias for the joined element
* @param type The join type
* @param fetch True if a join fetch should be added
* @return The query builder for chaining calls
*/
public X join(String path, String alias, JoinType type, boolean fetch);
/**
* Adds a join to the query, possibly specializing implicit joins, and giving the joined element an alias.
* The resulting join will be the default join meaning that expressions which use the absolute path will refer to this join.
* If fetch is set to true, a join fetch will be added.
*
* @param path The path to join
* @param alias The alias for the joined element
* @param type The join type
* @param fetch True if a join fetch should be added
* @return The query builder for chaining calls
*/
public X joinDefault(String path, String alias, JoinType type, boolean fetch);
/**
* Like {@link FullQueryBuilder#join(java.lang.String, java.lang.String, com.blazebit.persistence.JoinType, boolean) } but with
* {@link JoinType#INNER} and fetch set to true.
*
* @param path The path to join
* @param alias The alias for the joined element
* @return The query builder for chaining calls
*/
public X innerJoinFetch(String path, String alias);
/**
* Like {@link FullQueryBuilder#joinDefault(java.lang.String, java.lang.String, com.blazebit.persistence.JoinType, boolean) } but with
* {@link JoinType#INNER} and fetch set to true.
*
* @param path The path to join
* @param alias The alias for the joined element
* @return The query builder for chaining calls
*/
public X innerJoinFetchDefault(String path, String alias);
/**
* Like {@link FullQueryBuilder#join(java.lang.String, java.lang.String, com.blazebit.persistence.JoinType, boolean) } but with
* {@link JoinType#LEFT} and fetch set to true.
*
* @param path The path to join
* @param alias The alias for the joined element
* @return The query builder for chaining calls
*/
public X leftJoinFetch(String path, String alias);
/**
* Like {@link FullQueryBuilder#joinDefault(java.lang.String, java.lang.String, com.blazebit.persistence.JoinType, boolean) } but with
* {@link JoinType#LEFT} and fetch set to true.
*
* @param path The path to join
* @param alias The alias for the joined element
* @return The query builder for chaining calls
*/
public X leftJoinFetchDefault(String path, String alias);
/**
* Like {@link FullQueryBuilder#join(java.lang.String, java.lang.String, com.blazebit.persistence.JoinType, boolean) } but with
* {@link JoinType#RIGHT} and fetch set to true.
*
* @param path The path to join
* @param alias The alias for the joined element
* @return The query builder for chaining calls
*/
public X rightJoinFetch(String path, String alias);
/**
* Like {@link FullQueryBuilder#joinDefault(java.lang.String, java.lang.String, com.blazebit.persistence.JoinType, boolean) } but with
* {@link JoinType#RIGHT} and fetch set to true.
*
* @param path The path to join
* @param alias The alias for the joined element
* @return The query builder for chaining calls
*/
public X rightJoinFetchDefault(String path, String alias);
/*
* Select methods
*/
/**
* Starts a {@link SelectObjectBuilder} for the given class. The types of the parameter arguments used in the
* {@link SelectObjectBuilder} must match a constructor of the given class.
*
* @param The new query result type specified by the given class
* @param clazz The class which should be used for the select new select clause
* @return The select object builder for the given class
*/
public SelectObjectBuilder extends FullQueryBuilder> selectNew(Class clazz);
/**
* Starts a {@link SelectObjectBuilder} for the given constructor. The types of the parameter arguments used in the
* {@link SelectObjectBuilder} must match the given constructor.
*
* @param The new query result type specified by the given class
* @param constructor The constructor which should be used for the select new select clause
* @return The select object builder for the given class
*/
public SelectObjectBuilder extends FullQueryBuilder> selectNew(Constructor constructor);
/**
* Applies the given object builder to this query. The object builder provides the select clauses and is used to transform the
* result set tuples.
*
* @param The new query result type specified by the given class
* @param builder The object builder which transforms the result set into objects of type Y
* @return The query builder for chaining calls
*/
public FullQueryBuilder selectNew(ObjectBuilder builder);
}