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 entity 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.