diff --git a/pom.xml b/pom.xml index 2f40cd66af..545f81bfff 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-commons - 3.0.0-SNAPSHOT + 3.0.0-2654-QBE-docs-SNAPSHOT Spring Data Core Core Spring concepts underpinning every Spring Data module. diff --git a/src/main/asciidoc/query-by-example.adoc b/src/main/asciidoc/query-by-example.adoc index 7d3033818f..5e2c97a713 100644 --- a/src/main/asciidoc/query-by-example.adoc +++ b/src/main/asciidoc/query-by-example.adoc @@ -13,13 +13,15 @@ In fact, Query by Example does not require you to write queries by using store-s [[query-by-example.usage]] == Usage -The Query by Example API consists of three parts: +The Query by Example API consists of four parts: * Probe: The actual example of a domain object with populated fields. * `ExampleMatcher`: The `ExampleMatcher` carries details on how to match particular fields. It can be reused across multiple Examples. * `Example`: An `Example` consists of the probe and the `ExampleMatcher`. It is used to create the query. +* `FetchableFluentQuery`: A `FetchableFluentQuery` offers a fluent API, that allows further customization of a query derived from an `Example`. + Using the fluent API allows you to specify ordering, projection and result processing for your query. Query by Example is well suited for several use cases: @@ -56,7 +58,8 @@ The preceding example shows a simple domain object. You can use it to create an `Example`. By default, fields having `null` values are ignored, and strings are matched by using the store specific defaults. -NOTE: Inclusion of properties into a Query by Example criteria is based on nullability. Properties using primitive types (`int`, `double`, …) are always included unless <>. +NOTE: Inclusion of properties into a Query by Example criteria is based on nullability. +Properties using primitive types (`int`, `double`, …) are always included unless <>. Examples can be built by either using the `of` factory method or by using <>. `Example` is immutable. The following listing shows a simple Example: @@ -70,6 +73,7 @@ person.setFirstname("Dave"); <2> Example example = Example.of(person); <3> ---- + <1> Create a new instance of the domain object. <2> Set the properties to query. <3> Create the `Example`. @@ -115,6 +119,7 @@ ExampleMatcher matcher = ExampleMatcher.matching() <3> Example example = Example.of(person, matcher); <7> ---- + <1> Create a new instance of the domain object. <2> Set properties. <3> Create an `ExampleMatcher` to expect all values to match. @@ -186,3 +191,28 @@ The following table describes the scope of the various `ExampleMatcher` settings | Property path |=== + +[[query-by-example.fluent]] +== Fluent API + +`QueryByExampleExecutor` offers one more method, which we did not mention so far: ` R findBy(Example example, Function, R> queryFunction)`. +As with other methods it executes a query derived from an `Example`. +But with the second argument you can control aspects of that execution, that you can't control dynamically otherwise. +You do so by invoking the various methods of the `FetchableFluentQuery` in the second argument. +`sortBy` allows you to specify an ordering for your result. +`as` allows you to specify the type to which you want the result to be transformed. +`project` limits the attributes queried. +`first`, `firstValue`, `one`, `oneValue`, `all`, `page`, `stream`, `count`, `exists` define what kind of result you'll get and also how the query behaves when more than the expected number of results are available. + + +.Use the fluent API to get the last of potentially many results, ordered by lastname. +==== +[source,java] +---- +Optional match = repository.findBy(example, + q -> q + .sortBy(Sort.by("lastname").descending()) + .first() +); +---- +====