From 7d25edfb8b02ba7e866acecb73140dc166b6c116 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Wed, 13 Jul 2022 14:42:49 +0200 Subject: [PATCH 1/2] 2654-QBE-docs - Prepare branch --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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. From 6c510879015b72858d794fa63cd0adb43d593de5 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Wed, 13 Jul 2022 15:19:20 +0200 Subject: [PATCH 2/2] Add documentation for the fluent API for Query By Example. Closes #2654 See #2228 --- src/main/asciidoc/query-by-example.adoc | 34 +++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) 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() +); +---- +====