EntityQuery infrastructure
EntityModule provides an abstraction layer for querying entities.
This abstraction is built around the concept of an EntityQuery
.
What is an EntityQuery?
Much like a SQL statement, an EntityQuery
represents a query to perform on a list of entities (which can in theory be any collection of objects).
An EntityQuery
can specify one or more predicates that the entities must match, as well as one or more ordering clauses for sorting the resulting items.
An EntityQueryExecutor
can execute the EntityQuery
and return the collection of entities that match the query.
EntityQuery and entity views
A lot of the default views generated by EntityModule require the presence of an EntityQueryExecutor
to function correctly.
For example association views use EntityQuery
to retrieve the entities associated with another item.
An executor is automatically registered if one can be determined based on the backing data repository, see default support.
EntityQuery Language
EQL is an SQL-like syntax for defining EntityQueries
.
It is converted to an EntityQuery
for execution.
EntityQuery query = EntityQuery.parse( "name = 'john' order by birthday desc, registrationDate asc" );
Behind the scenes specific EntityQueryParser
implementations can be used to convert an EQL statement to an EntityQuery
.
Executing a query
An EntityQuery
is executed by an EntityQueryExecutor
.
List<Item> items = entityQueryExecutor.findAll( query );
Page<Item> itemsOnPage = entityQueryExecutor.findAll( query, pageable );
Default support
Support for EntityQuery
is added automatically for any Spring Data repository.
Depending on the actual repository implementation, some query operations may or may not be supported.
Adding EntityQuery support
The minimum action required for enabling EntityQuery
support on an entity, is registering an EntityQueryExecutor
attribute on the entity configuration.
EntityQueryExecutor
The EntityQueryExecutor
is responsible for executing an EntityQuery
and returning the entities requested.
An EntityConfiguration
can have a single EntityQueryExecutor.class
attribute holding the executor instance.
The presence of the EntityQueryExecutor
is a requirement for the default entity views.
An EntityQueryExecutor
is registered automatically for supported Spring Data Repository
implementations.
Default implementations
The supported EntityQuery
features depend on the specific implementation of the EntityQueryExecutor
.
The following implementations are available by default:
EntityQueryQueryDslExecutor
-
Automatically registered for any repository implementing
QueryDslPredicateExecutor
. Executes queries directly against the repository as QueryDsl predicates. EntityQueryJpaExecutor
-
Automatically registered for any repository implementing
JpaSpecificationExecutor
. Executes queries directly against the repository as JPA specifications. CollectionEntityQueryExecutor
-
Automatically registered for any repository implementing
CrudRepository
. The repository is only used to fetch all items, the filter query is performed by the application code.Using a specific (repository-aware) query executor will usually yield much better performance.
Registering an EntityQueryExecutor
Any EntityQueryExecutor
implementation can be registered simply be setting the EntityQueryExecutor.class
attribute on the EntityConfiguration
.
Utility class EntityConfigurationCustomizers
contains several helper methods for easy registration of an executor during configuration building.
entities.withType( Category.class )
.and( EntityConfigurationCustomizers.registerEntityQueryExecutor( categoryClient::fetchAll ) );
The CollectionEntityQueryExecutor
(used behind the scenes in the above example) is useful to activate in-memory EntityQuery
support for any collection of items.
This implementation also supports manually registered properties that not necessarily correspond with single properties in the data store.
AssociatedEntityQueryExecutor
Like EntityQueryExecutor
that is registered on the EntityConfiguration
, every EntityAssociation
can have an AssociatedEntityQueryExecutor
registered.
The AssociatedEntityQueryExecutor
allows executing queries in the context of a single parent object.
Like the EntityQueryExecutor
, the AssociatedEntityQueryExecutor
is usually added automatically.
The presence of the AssociatedEntityQueryExecutor
is a requirement for the default association views.
Performance
As EntityQuery
is an abstraction layer it is usually somewhat less performant than native repository implementations.
The actual performance greatly depends on the specific EntityQueryExecutor
being used.
By default repositories implemented as JpaSpecificationExecutor
or QueryDslPredicateExecutor
yield best performance, as they allow queries to be executed directly on the datastore using either JPA or QueryDsl as go-between.