Browse Source

DATACMNS-1291 - Documentation full editing pass.

Edited for spelling, punctuation, grammar, and corporate voice. Also added cross-references in a few places.

Original pull request: #281.
pull/285/merge
Jay Bryant 8 years ago committed by Mark Paluch
parent
commit
4da35a8f32
  1. 11
      index-multi.adoc
  2. 23
      src/main/asciidoc/auditing.adoc
  3. 21
      src/main/asciidoc/dependencies.adoc
  4. 17
      src/main/asciidoc/index.adoc
  5. 13
      src/main/asciidoc/preface.adoc
  6. 54
      src/main/asciidoc/query-by-example.adoc
  7. 546
      src/main/asciidoc/repositories.adoc
  8. 15
      src/main/asciidoc/repository-namespace-reference.adoc
  9. 82
      src/main/asciidoc/repository-projections.adoc
  10. 3
      src/main/asciidoc/repository-query-keywords-reference.adoc
  11. 29
      src/main/asciidoc/repository-query-return-types-reference.adoc

11
index-multi.adoc

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
= Spring Data Commons Reference Guide
The reference documentation consists of the following sections:
[horizontal]
link:preface.html[Preface] :: Project metadata (version control, bug tracker, and so on).
link:dependencies.html[Dependencies] :: Dependency Management with Spring Boot, Spring Framework.
link:repositories.html[Repositories] :: Core concepts, defining queries, repository interfaces, and more.
link:repository-projections.html[Projections] :: Interface-based projections, class-based projections, dynamic projections.
link:query-by-example.html[Query by Example] :: Usage, `Example`, `ExampleMatcher`.
link:auditing.html[Auditing] :: Annotation-based auditing metadata, interface-based auditing metadata, `AuditorAware`.

23
src/main/asciidoc/auditing.adoc

@ -3,11 +3,11 @@ @@ -3,11 +3,11 @@
[[auditing.basics]]
== Basics
Spring Data provides sophisticated support to transparently keep track of who created or changed an entity and the point in time this happened. To benefit from that functionality you have to equip your entity classes with auditing metadata that can be defined either using annotations or by implementing an interface.
Spring Data provides sophisticated support to transparently keep track of who created or changed an entity and when the change happened. To benefit from that functionality, you have to equip your entity classes with auditing metadata that can be defined either using annotations or by implementing an interface.
[[auditing.annotations]]
=== Annotation based auditing metadata
We provide `@CreatedBy`, `@LastModifiedBy` to capture the user who created or modified the entity as well as `@CreatedDate` and `@LastModifiedDate` to capture the point in time this happened.
=== Annotation-based Auditing Metadata
We provide `@CreatedBy` and `@LastModifiedBy` to capture the user who created or modified the entity as well as `@CreatedDate` and `@LastModifiedDate` to capture when the change happened.
.An audited entity
====
@ -26,20 +26,20 @@ class Customer { @@ -26,20 +26,20 @@ class Customer {
----
====
As you can see, the annotations can be applied selectively, depending on which information you'd like to capture. For the annotations capturing the points in time can be used on properties of type JodaTimes `DateTime`, legacy Java `Date` and `Calendar`, JDK8 date/time types as well as `long`/`Long`.
As you can see, the annotations can be applied selectively, depending on which information you want to capture. The annotations capturing when changes were made can be used on properties of type Joda-Time, `DateTime`, legacy Java `Date` and `Calendar`, JDK8 date and time types, and `long` or `Long`.
[[auditing.interfaces]]
=== Interface-based auditing metadata
In case you don't want to use annotations to define auditing metadata you can let your domain class implement the `Auditable` interface. It exposes setter methods for all of the auditing properties.
=== Interface-based Auditing Metadata
In case you do not want to use annotations to define auditing metadata, you can let your domain class implement the `Auditable` interface. It exposes setter methods for all of the auditing properties.
There's also a convenience base class `AbstractAuditable` which you can extend to avoid the need to manually implement the interface methods. Be aware that this increases the coupling of your domain classes to Spring Data which might be something you want to avoid. Usually the annotation based way of defining auditing metadata is preferred as it is less invasive and more flexible.
There is also a convenience base class, `AbstractAuditable`, which you can extend to avoid the need to manually implement the interface methods. Doing so increases the coupling of your domain classes to Spring Data, which might be something you want to avoid. Usually, the annotation-based way of defining auditing metadata is preferred as it is less invasive and more flexible.
[[auditing.auditor-aware]]
=== AuditorAware
=== `AuditorAware`
In case you use either `@CreatedBy` or `@LastModifiedBy`, the auditing infrastructure somehow needs to become aware of the current principal. To do so, we provide an `AuditorAware<T>` SPI interface that you have to implement to tell the infrastructure who the current user or system interacting with the application is. The generic type `T` defines of what type the properties annotated with `@CreatedBy` or `@LastModifiedBy` have to be.
In case you use either `@CreatedBy` or `@LastModifiedBy`, the auditing infrastructure somehow needs to become aware of the current principal. To do so, we provide an `AuditorAware<T>` SPI interface that you have to implement to tell the infrastructure who the current user or system interacting with the application is. The generic type `T` defines what type the properties annotated with `@CreatedBy` or `@LastModifiedBy` have to be.
Here's an example implementation of the interface using Spring Security's `Authentication` object:
The following example shows an implementation of the interface that uses Spring Security's `Authentication` object:
.Implementation of AuditorAware based on Spring Security
====
@ -61,5 +61,4 @@ class SpringSecurityAuditorAware implements AuditorAware<User> { @@ -61,5 +61,4 @@ class SpringSecurityAuditorAware implements AuditorAware<User> {
----
====
The implementation is accessing the `Authentication` object provided by Spring Security and looks up the custom `UserDetails` instance from it that you have created in your `UserDetailsService` implementation. We're assuming here that you are exposing the domain user through that `UserDetails` implementation but you could also look it up from anywhere based on the `Authentication` found.
The implementation accesses the `Authentication` object provided by Spring Security and looks up the custom `UserDetails` instance that you have created in your `UserDetailsService` implementation. We assume here that you are exposing the domain user through the `UserDetails` implementation but that, based on the `Authentication` found, you could also look it up from anywhere.

21
src/main/asciidoc/dependencies.adoc

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
[[dependencies]]
= Dependencies
Due to different inception dates of individual Spring Data modules, most of them carry different major and minor version numbers. The easiest way to find compatible ones is by relying on the Spring Data Release Train BOM we ship with the compatible versions defined. In a Maven project you'd declare this dependency in the `<dependencyManagement />` section of your POM:
Due to the different inception dates of individual Spring Data modules, most of them carry different major and minor version numbers. The easiest way to find compatible ones is to rely on the Spring Data Release Train BOM that we ship with the compatible versions defined. In a Maven project, you would declare this dependency in the `<dependencyManagement />` section of your POM, as follows:
.Using the Spring Data release train BOM
====
@ -22,15 +22,15 @@ Due to different inception dates of individual Spring Data modules, most of them @@ -22,15 +22,15 @@ Due to different inception dates of individual Spring Data modules, most of them
====
[[dependencies.train-names]]
The current release train version is `{releasetrainVersion}`. The train names are ascending alphabetically and currently available ones are listed https://github.com/spring-projects/spring-data-commons/wiki/Release-planning[here]. The version name follows the following pattern: `${name}-${release}` where release can be one of the following:
The current release train version is `{releasetrainVersion}`. The train names ascend alphabetically and the currently available trains are listed https://github.com/spring-projects/spring-data-commons/wiki/Release-planning[here]. The version name follows the following pattern: `${name}-${release}`, where release can be one of the following:
* `BUILD-SNAPSHOT` - current snapshots
* `M1`, `M2` etc. - milestones
* `RC1`, `RC2` etc. - release candidates
* `RELEASE` - GA release
* `SR1`, `SR2` etc. - service releases
* `BUILD-SNAPSHOT`: Current snapshots
* `M1`, `M2`, and so on: Milestones
* `RC1`, `RC2`, and so on: Release candidates
* `RELEASE`: GA release
* `SR1`, `SR2`, and so on: Service releases
A working example of using the BOMs can be found in our https://github.com/spring-projects/spring-data-examples/tree/master/bom[Spring Data examples repository]. If that's in place declare the Spring Data modules you'd like to use without a version in the `<dependencies />` block.
A working example of using the BOMs can be found in our https://github.com/spring-projects/spring-data-examples/tree/master/bom[Spring Data examples repository]. With that in place, you can declare the Spring Data modules you would like to use without a version in the `<dependencies />` block, as follows:
.Declaring a dependency to a Spring Data module
====
@ -46,12 +46,11 @@ A working example of using the BOMs can be found in our https://github.com/sprin @@ -46,12 +46,11 @@ A working example of using the BOMs can be found in our https://github.com/sprin
====
[[dependencies.spring-boot]]
== Dependency management with Spring Boot
== Dependency Management with Spring Boot
Spring Boot already selects a very recent version of Spring Data modules for you. In case you want to upgrade to a newer version nonetheless, simply configure the property `spring-data-releasetrain.version` to the <<dependencies.train-names,train name and iteration>> you'd like to use.
Spring Boot selects a recent version of Spring Data modules for you. If you still want to upgrade to a newer version, configure the property `spring-data-releasetrain.version` to the <<dependencies.train-names,train name and iteration>> you would like to use.
[[dependencies.spring-framework]]
== Spring Framework
The current version of Spring Data modules require Spring Framework in version {springVersion} or better. The modules might also work with an older bugfix version of that minor version. However, using the most recent version within that generation is highly recommended.

17
src/main/asciidoc/index.adoc

@ -1,20 +1,24 @@ @@ -1,20 +1,24 @@
= Spring Data Commons - Reference Documentation
Oliver Gierke; Thomas Darimont; Christoph Strobl; Mark Pollack; Thomas Risberg; Mark Paluch;
Oliver Gierke; Thomas Darimont; Christoph Strobl; Mark Pollack; Thomas Risberg; Mark Paluch; Jay Bryant
:revnumber: {version}
:revdate: {localdate}
:toc:
:toc-placement!:
:linkcss:
:doctype: book
:docinfo: shared
:toc: left
:toclevels: 4
:source-highlighter: prettify
:icons: font
(C) 2008-2017 The original authors.
NOTE: Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
toc::[]
include::preface.adoc[]
[[reference-documentation]]
= Reference documentation
= Reference Documentation
:leveloffset: +1
include::dependencies.adoc[]
@ -34,4 +38,3 @@ include::repository-populator-namespace-reference.adoc[] @@ -34,4 +38,3 @@ include::repository-populator-namespace-reference.adoc[]
include::repository-query-keywords-reference.adoc[]
include::repository-query-return-types-reference.adoc[]
:leveloffset: -1

13
src/main/asciidoc/preface.adoc

@ -3,11 +3,10 @@ @@ -3,11 +3,10 @@
The Spring Data Commons project applies core Spring concepts to the development of solutions using many relational and non-relational data stores.
[[project]]
[preface]
== Project metadata
== Project Metadata
* Version control - http://github.com/spring-projects/spring-data-commons
* Bugtracker - https://jira.spring.io/browse/DATACMNS
* Release repository - https://repo.spring.io/libs-release
* Milestone repository - https://repo.spring.io/libs-milestone
* Snapshot repository - https://repo.spring.io/libs-snapshot
* Version control: http://github.com/spring-projects/spring-data-commons
* Bugtracker: https://jira.spring.io/browse/DATACMNS
* Release repository: https://repo.spring.io/libs-release
* Milestone repository: https://repo.spring.io/libs-milestone
* Snapshot repository: https://repo.spring.io/libs-snapshot

54
src/main/asciidoc/query-by-example.adoc

@ -4,33 +4,31 @@ @@ -4,33 +4,31 @@
[[query-by-example.introduction]]
== Introduction
This chapter will give you an introduction to Query by Example and explain how to use Examples.
This chapter provides an introduction to Query by Example and explains how to use it.
Query by Example (QBE) is a user-friendly querying technique with a simple interface. It allows dynamic query creation and does not require to write queries containing field names. In fact, Query by Example does not require to write queries using store-specific query languages at all.
Query by Example (QBE) is a user-friendly querying technique with a simple interface. It allows dynamic query creation and does not require you to write queries that contain field names. In fact, Query by Example does not require you to write queries by using store-specific query languages at all.
[[query-by-example.usage]]
== Usage
The Query by Example API consists of three parts:
* Probe: That is the actual example of a domain object with populated fields.
* 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.
Query by Example is suited for several use-cases but also comes with limitations:
Query by Example is well suited for several use cases:
**When to use**
* Querying your data store with a set of static or dynamic constraints.
* Frequent refactoring of the domain objects without worrying about breaking existing queries.
* Working independently from the underlying data store API.
* Querying your data store with a set of static or dynamic constraints
* Frequent refactoring of the domain objects without worrying about breaking existing queries
* Works independently from the underlying data store API
Query by Example also has several limitations:
**Limitations**
* No support for nested or grouped property constraints, such as `firstname = ?0 or (firstname = ?1 and lastname = ?2)`.
* Only supports starts/contains/ends/regex matching for strings and exact matching for other property types.
* No support for nested/grouped property constraints like `firstname = ?0 or (firstname = ?1 and lastname = ?2)`
* Only supports starts/contains/ends/regex matching for strings and exact matching for other property types
Before getting started with Query by Example, you need to have a domain object. To get started, simply create an interface for your repository:
Before getting started with Query by Example, you need to have a domain object. To get started, create an interface for your repository, as shown in the following example:
.Sample Person object
====
@ -49,7 +47,7 @@ public class Person { @@ -49,7 +47,7 @@ public class Person {
----
====
This is a simple domain object. You can use it to create an `Example`. By default, fields having `null` values are ignored, and strings are matched using the store specific defaults. Examples can be built by either using the `of` factory method or by using <<query-by-example.matchers,`ExampleMatcher`>>. `Example` is immutable.
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. Examples can be built by either using the `of` factory method or by using <<query-by-example.matchers,`ExampleMatcher`>>. `Example` is immutable. The following listing shows a simple Example:
.Simple Example
====
@ -60,12 +58,12 @@ person.setFirstname("Dave"); <2> @@ -60,12 +58,12 @@ person.setFirstname("Dave"); <2>
Example<Person> example = Example.of(person); <3>
----
<1> Create a new instance of the domain object
<2> Set the properties to query
<3> Create the `Example`
<1> Create a new instance of the domain object.
<2> Set the properties to query.
<3> Create the `Example`.
====
Examples are ideally be executed with repositories. To do so, let your repository interface extend `QueryByExampleExecutor<T>`. Here's an excerpt from the `QueryByExampleExecutor` interface:
Examples are ideally be executed with repositories. To do so, let your repository interface extend `QueryByExampleExecutor<T>`. The following listing shows an excerpt from the `QueryByExampleExecutor` interface:
.The `QueryByExampleExecutor`
====
@ -83,9 +81,9 @@ public interface QueryByExampleExecutor<T> { @@ -83,9 +81,9 @@ public interface QueryByExampleExecutor<T> {
====
[[query-by-example.matchers]]
== Example matchers
== Example Matchers
Examples are not limited to default settings. You can specify own defaults for string matching, null handling and property-specific settings using the `ExampleMatcher`.
Examples are not limited to default settings. You can specify your own defaults for string matching, null handling, and property-specific settings by using the `ExampleMatcher`, as shown in the following example:
.Example matcher with customized matching
====
@ -104,16 +102,16 @@ Example<Person> example = Example.of(person, matcher); <7> @@ -104,16 +102,16 @@ Example<Person> 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. It's usable at this stage even without further configuration.
<4> Construct a new `ExampleMatcher` to ignore the property path `lastname`.
<5> Construct a new `ExampleMatcher` to ignore the property path `lastname` and to include null values.
<6> Construct a new `ExampleMatcher` to ignore the property path `lastname`, to include null values, and use perform suffix string matching.
<3> Create an `ExampleMatcher` to expect all values to match. It is usable at this stage even without further configuration.
<4> Construct a new `ExampleMatcher` to ignore the `lastname` property path.
<5> Construct a new `ExampleMatcher` to ignore the `lastname` property path and to include null values.
<6> Construct a new `ExampleMatcher` to ignore the `lastname` property path, to include null values, and to perform suffix string matching.
<7> Create a new `Example` based on the domain object and the configured `ExampleMatcher`.
====
By default the `ExampleMatcher` will expect all values set on the probe to match. If you want to get results matching any of the predicates defined implicitly, use `ExampleMatcher.matchingAny()`.
By default, the `ExampleMatcher` expects all values set on the probe to match. If you want to get results matching any of the predicates defined implicitly, use `ExampleMatcher.matchingAny()`.
You can specify behavior for individual properties (e.g. "firstname" and "lastname", "address.city" for nested properties). You can tune it with matching options and case sensitivity.
You can specify behavior for individual properties (such as "firstname" and "lastname" or, for nested properties, "address.city"). You can tune it with matching options and case sensitivity, as shown in the following example:
.Configuring matcher options
====
@ -126,7 +124,7 @@ ExampleMatcher matcher = ExampleMatcher.matching() @@ -126,7 +124,7 @@ ExampleMatcher matcher = ExampleMatcher.matching()
----
====
Another style to configure matcher options is by using Java 8 lambdas. This approach is a callback that asks the implementor to modify the matcher. It's not required to return the matcher because configuration options are held within the matcher instance.
Another way to configure matcher options is to use lambdas (introduced in Java 8). This approach creates a callback that asks the implementor to modify the matcher. You need not return the matcher, because configuration options are held within the matcher instance. The following example shows a matcher that uses lambdas:
.Configuring matcher options with lambdas
====
@ -139,7 +137,7 @@ ExampleMatcher matcher = ExampleMatcher.matching() @@ -139,7 +137,7 @@ ExampleMatcher matcher = ExampleMatcher.matching()
----
====
Queries created by `Example` use a merged view of the configuration. Default matching settings can be set at `ExampleMatcher` level while individual settings can be applied to particular property paths. Settings that are set on `ExampleMatcher` are inherited by property path settings unless they are defined explicitly. Settings on a property patch have higher precedence than default settings.
Queries created by `Example` use a merged view of the configuration. Default matching settings can be set at the `ExampleMatcher` level, while individual settings can be applied to particular property paths. Settings that are set on `ExampleMatcher` are inherited by property path settings unless they are defined explicitly. Settings on a property patch have higher precedence than default settings. The following table describes the scope of the various `ExampleMatcher` settings:
[cols="1,2", options="header"]
.Scope of `ExampleMatcher` settings

546
src/main/asciidoc/repositories.adoc

File diff suppressed because it is too large Load Diff

15
src/main/asciidoc/repository-namespace-reference.adoc

@ -3,17 +3,16 @@ @@ -3,17 +3,16 @@
= Namespace reference
[[populator.namespace-dao-config]]
== The <repositories /> element
The `<repositories />` element triggers the setup of the Spring Data repository infrastructure. The most important attribute is `base-package` which defines the package to scan for Spring Data repository interfaces.footnote:[see <<repositories.create-instances.spring>>]
== The `<repositories />` Element
The `<repositories />` element triggers the setup of the Spring Data repository infrastructure. The most important attribute is `base-package`, which defines the package to scan for Spring Data repository interfaces. See "`<<repositories.create-instances.spring>>`". The following table describes the attributes of the `<repositories />` element:
.Attributes
[options="header", cols="1,3"]
|===============
|Name|Description
|`base-package`|Defines the package to be used to be scanned for repository interfaces extending *Repository (actual interface is determined by specific Spring Data module) in auto detection mode. All packages below the configured package will be scanned, too. Wildcards are allowed.
|`repository-impl-postfix`|Defines the postfix to autodetect custom repository implementations. Classes whose names end with the configured postfix will be considered as candidates. Defaults to `Impl`.
|`query-lookup-strategy`|Determines the strategy to be used to create finder queries. See <<repositories.query-methods.query-lookup-strategies>> for details. Defaults to `create-if-not-found`.
|`named-queries-location`|Defines the location to look for a Properties file containing externally defined queries.
|`consider-nested-repositories`|Controls whether nested repository interface definitions should be considered. Defaults to `false`.
|`base-package`|Defines the package to be scanned for repository interfaces that extend `*Repository` (the actual interface is determined by the specific Spring Data module) in auto-detection mode. All packages below the configured package are scanned, too. Wildcards are allowed.
|`repository-impl-postfix`|Defines the postfix to autodetect custom repository implementations. Classes whose names end with the configured postfix are considered as candidates. Defaults to `Impl`.
|`query-lookup-strategy`|Determines the strategy to be used to create finder queries. See "`<<repositories.query-methods.query-lookup-strategies>>`" for details. Defaults to `create-if-not-found`.
|`named-queries-location`|Defines the location to search for a Properties file containing externally defined queries.
|`consider-nested-repositories`|Whether nested repository interface definitions should be considered. Defaults to `false`.
|===============

82
src/main/asciidoc/repository-projections.adoc

@ -2,10 +2,10 @@ @@ -2,10 +2,10 @@
= Projections
Spring Data query methods usually return one or multiple instances of the aggregate root managed by the repository.
However, it might sometimes be desirable to rather project on certain attributes of those types.
Spring Data allows to model dedicated return types to more selectively retrieve partial views onto the managed aggregates.
However, it might sometimes be desirable to create projections based on certain attributes of those types.
Spring Data allows modeling dedicated return types, to more selectively retrieve partial views of the managed aggregates.
Imagine a sample repository and aggregate root type like this:
Imagine a repository and aggregate root type such as the following example:
.A sample aggregate and repository
====
@ -29,13 +29,13 @@ interface PersonRepository extends Repository<Person, UUID> { @@ -29,13 +29,13 @@ interface PersonRepository extends Repository<Person, UUID> {
----
====
Now imagine we'd want to retrieve the person's name attributes only.
What means does Spring Data offer to achieve this?
Now imagine that we want to retrieve the person's name attributes only.
What means does Spring Data offer to achieve this? The rest of this chapter answers that question.
[[projections.interfaces]]
== Interface-based projections
== Interface-based Projections
The easiest way to limit the result of the queries to expose the name attributes only is by declaring an interface that will expose accessor methods for the properties to be read:
The easiest way to limit the result of the queries to only the name attributes is by declaring an interface that exposes accessor methods for the properties to be read, as shown in the following example:
.A projection interface to retrieve a subset of attributes
====
@ -50,7 +50,7 @@ interface NamesOnly { @@ -50,7 +50,7 @@ interface NamesOnly {
====
The important bit here is that the properties defined here exactly match properties in the aggregate root.
This allows a query method to be added like this:
Doing so lets a query method be added as follows:
.A repository using an interface based projection with a query method
====
@ -63,10 +63,10 @@ interface PersonRepository extends Repository<Person, UUID> { @@ -63,10 +63,10 @@ interface PersonRepository extends Repository<Person, UUID> {
----
====
The query execution engine will create proxy instances of that interface at runtime for each element returned and forward calls to the exposed methods to the target object.
The query execution engine creates proxy instances of that interface at runtime for each element returned and forwards calls to the exposed methods to the target object.
[[projections.interfaces.nested]]
Projections can be used recursively. If you wanted to include some of the `Address` information as well, create a projection interface for that and return that interface from the declaration of `getAddress()`.
Projections can be used recursively. If you want to include some of the `Address` information as well, create a projection interface for that and return that interface from the declaration of `getAddress()`, as shown in the following example:
.A projection interface to retrieve a subset of attributes
====
@ -85,12 +85,12 @@ interface PersonSummary { @@ -85,12 +85,12 @@ interface PersonSummary {
----
====
On method invocation, the `address` property of the target instance will be obtained and wrapped into a projecting proxy in turn.
On method invocation, the `address` property of the target instance is obtained and wrapped into a projecting proxy in turn.
[[projections.interfaces.closed]]
=== Closed projections
=== Closed Projections
A projection interface whose accessor methods all match properties of the target aggregate are considered closed projections.
A projection interface whose accessor methods all match properties of the target aggregate is considered to be a closed projection. The following example (which we used earlier in this chapter, too) is a closed projection:
.A closed projection
====
@ -104,13 +104,13 @@ interface NamesOnly { @@ -104,13 +104,13 @@ interface NamesOnly {
----
====
If a closed projection is used, Spring Data modules can even optimize the query execution as we exactly know about all attributes that are needed to back the projection proxy.
For more details on that, please refer to the module specific part of the reference documentation.
If you use a closed projection, Spring Data can optimize the query execution, because we know about all the attributes that are needed to back the projection proxy.
For more details on that, see the module-specific part of the reference documentation.
[[projections.interfaces.open]]
=== Open projections
=== Open Projections
Accessor methods in projection interfaces can also be used to compute new values by using the `@Value` annotation on it:
Accessor methods in projection interfaces can also be used to compute new values by using the `@Value` annotation, as shown in the following example:
[[projections.interfaces.open.simple]]
.An Open Projection
@ -126,12 +126,12 @@ interface NamesOnly { @@ -126,12 +126,12 @@ interface NamesOnly {
----
====
The aggregate root backing the projection is available via the `target` variable.
A projection interface using `@Value` an open projection.
Spring Data won't be able to apply query execution optimizations in this case as the SpEL expression could use any attributes of the aggregate root.
The aggregate root backing the projection is available in the `target` variable.
A projection interface using `@Value` is an open projection.
Spring Data cannot apply query execution optimizations in this case, because the SpEL expression could use any attribute of the aggregate root.
The expressions used in `@Value` shouldn't become too complex as you'd want to avoid programming in ``String``s.
For very simple expressions, one option might be to resort to default methods:
The expressions used in `@Value` should not be too complex -- you want to avoid programming in `String` variables.
For very simple expressions, one option might be to resort to default methods (introduced in Java 8), as shown in the following example:
[[projections.interfaces.open.default]]
.A projection interface using a default method for custom logic
@ -151,7 +151,7 @@ interface NamesOnly { @@ -151,7 +151,7 @@ interface NamesOnly {
====
This approach requires you to be able to implement logic purely based on the other accessor methods exposed on the projection interface.
A second, more flexible option is to implement the custom logic in a Spring bean and then simply invoke that from the SpEL expression:
A second, more flexible, option is to implement the custom logic in a Spring bean and then invoke that from the SpEL expression, as shown in the following example:
[[projections.interfaces.open.bean-reference]]
.Sample Person object
@ -175,9 +175,9 @@ interface NamesOnly { @@ -175,9 +175,9 @@ interface NamesOnly {
----
====
Note, how the SpEL expression refers to `myBean` and invokes the `getFullName(…)` method forwarding the projection target as method parameter.
Methods backed by SpEL expression evaluation can also use method parameters which can then be referred to from the expression.
The method parameters are available via an `Object` array named `args`.
Notice how the SpEL expression refers to `myBean` and invokes the `getFullName(…)` method and forwards the projection target as a method parameter.
Methods backed by SpEL expression evaluation can also use method parameters, which can then be referred to from the expression.
The method parameters are available through an `Object` array named `args`. The following example shows how to get a method parameter from the `args` array:
.Sample Person object
====
@ -191,15 +191,17 @@ interface NamesOnly { @@ -191,15 +191,17 @@ interface NamesOnly {
----
====
Again, for more complex expressions rather use a Spring bean and let the expression just invoke a method as described <<projections.interfaces.open.bean-reference, above>>.
Again, for more complex expressions, you should use a Spring bean and let the expression invoke a method, as described <<projections.interfaces.open.bean-reference,earlier>>.
[[projections.dtos]]
== Class-based projections (DTOs)
== Class-based Projections (DTOs)
Another way of defining projections is using value type DTOs that hold properties for the fields that are supposed to be retrieved.
These DTO types can be used exactly the same way projection interfaces are used, except that no proxying is going on here and no nested projections can be applied.
Another way of defining projections is by using value type DTOs (Data Transfer Objects) that hold properties for the fields that are supposed to be retrieved.
These DTO types can be used in exactly the same way projection interfaces are used, except that no proxying happens and no nested projections can be applied.
In case the store optimizes the query execution by limiting the fields to be loaded, the ones to be loaded are determined from the parameter names of the constructor that is exposed.
If the store optimizes the query execution by limiting the fields to be loaded, the fields to be loaded are determined from the parameter names of the constructor that is exposed.
The following example shows a projecting DTO:
.A projecting DTO
====
@ -229,10 +231,10 @@ class NamesOnly { @@ -229,10 +231,10 @@ class NamesOnly {
====
[TIP]
.Avoiding boilerplate code for projection DTOs
.Avoid boilerplate code for projection DTOs
====
The code that needs to be written for a DTO can be dramatically simplified using https://projectlombok.org[Project Lombok], which provides an `@Value` annotation (not to mix up with Spring's `@Value` annotation shown in the interface examples above).
The sample DTO above would become this:
You can dramatically simplify the code for a DTO by using https://projectlombok.org[Project Lombok], which provides an `@Value` annotation (not to be confused with Spring's `@Value` annotation shown in the earlier interface examples).
If you use Project Lombok's `@Value` annotation, the sample DTO shown earlier would become the following:
[source, java]
----
@ -241,16 +243,16 @@ class NamesOnly { @@ -241,16 +243,16 @@ class NamesOnly {
String firstname, lastname;
}
----
Fields are private final by default, the class exposes a constructor taking all fields and automatically gets `equals(…)` and `hashCode()` methods implemented.
Fields are `private final` by default, and the class exposes a constructor that takes all fields and automatically gets `equals(…)` and `hashCode()` methods implemented.
====
[[projection.dynamic]]
== Dynamic projections
== Dynamic Projections
So far we have used the projection type as the return type or element type of a collection.
However, it might be desirable to rather select the type to be used at invocation time.
To apply dynamic projections, use a query method like this:
So far, we have used the projection type as the return type or element type of a collection.
However, you might want to select the type to be used at invocation time (which makes it dynamic).
To apply dynamic projections, use a query method such as the one shown in the following example:
.A repository using a dynamic projection parameter
====
@ -263,7 +265,7 @@ interface PersonRepository extends Repository<Person, UUID> { @@ -263,7 +265,7 @@ interface PersonRepository extends Repository<Person, UUID> {
----
====
This way the method can be used to obtain the aggregates as is, or with a projection applied:
This way, the method can be used to obtain the aggregates as is or with a projection applied, as shown in the following example:
.Using a repository with dynamic projections
====

3
src/main/asciidoc/repository-query-keywords-reference.adoc

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
= Repository query keywords
== Supported query keywords
The following table lists the keywords generally supported by the Spring Data repository query derivation mechanism. However, consult the store-specific documentation for the exact list of supported keywords, because some listed here might not be supported in a particular store.
The following table lists the keywords generally supported by the Spring Data repository query derivation mechanism. However, consult the store-specific documentation for the exact list of supported keywords, because some keywords listed here might not be supported in a particular store.
.Query keywords
[options="header", cols="1,3"]
@ -38,4 +38,3 @@ The following table lists the keywords generally supported by the Spring Data re @@ -38,4 +38,3 @@ The following table lists the keywords generally supported by the Spring Data re
|`TRUE`|`True`, `IsTrue`
|`WITHIN`|`Within`, `IsWithin`
|===============

29
src/main/asciidoc/repository-query-return-types-reference.adoc

@ -2,10 +2,10 @@ @@ -2,10 +2,10 @@
[[repository-query-return-types]]
= Repository query return types
== Supported query return types
The following table lists the return types generally supported by Spring Data repositories. However, consult the store-specific documentation for the exact list of supported return types, because some listed here might not be supported in a particular store.
== Supported Query Return Types
The following table lists the return types generally supported by Spring Data repositories. However, consult the store-specific documentation for the exact list of supported return types, because some types listed here might not be supported in a particular store.
NOTE: Geospatial types like (`GeoResult`, `GeoResults`, `GeoPage`) are only available for data stores that support geospatial queries.
NOTE: Geospatial types (such as `GeoResult`, `GeoResults`, and `GeoPage`) are available only for data stores that support geospatial queries.
.Query return types
[options="header", cols="1,3"]
@ -14,20 +14,19 @@ NOTE: Geospatial types like (`GeoResult`, `GeoResults`, `GeoPage`) are only avai @@ -14,20 +14,19 @@ NOTE: Geospatial types like (`GeoResult`, `GeoResults`, `GeoPage`) are only avai
|`void`|Denotes no return value.
|Primitives|Java primitives.
|Wrapper types|Java wrapper types.
|`T`|An unique entity. Expects the query method to return one result at most. In case no result is found `null` is returned. More than one result will trigger an `IncorrectResultSizeDataAccessException`.
|`T`|An unique entity. Expects the query method to return one result at most. If no result is found, `null` is returned. More than one result triggers an `IncorrectResultSizeDataAccessException`.
|`Iterator<T>`|An `Iterator`.
|`Collection<T>`|A `Collection`.
|`List<T>`|A `List`.
|`Optional<T>`|A Java 8 or Guava `Optional`. Expects the query method to return one result at most. In case no result is found `Optional.empty()`/`Optional.absent()` is returned. More than one result will trigger an `IncorrectResultSizeDataAccessException`.
|`Option<T>`|An either Scala or JavaSlang `Option` type. Semantically same behavior as Java 8's `Optional` described above.
|`Optional<T>`|A Java 8 or Guava `Optional`. Expects the query method to return one result at most. If no result is found, `Optional.empty()` or `Optional.absent()` is returned. More than one result triggers an `IncorrectResultSizeDataAccessException`.
|`Option<T>`|Either a Scala or Javaslang `Option` type. Semantically the same behavior as Java 8's `Optional`, described earlier.
|`Stream<T>`|A Java 8 `Stream`.
|`Future<T>`|A `Future`. Expects method to be annotated with `@Async` and requires Spring's asynchronous method execution capability enabled.
|`CompletableFuture<T>`|A Java 8 `CompletableFuture`. Expects method to be annotated with `@Async` and requires Spring's asynchronous method execution capability enabled.
|`ListenableFuture`|A `org.springframework.util.concurrent.ListenableFuture`. Expects method to be annotated with `@Async` and requires Spring's asynchronous method execution capability enabled.
|`Slice`|A sized chunk of data with information whether there is more data available. Requires a `Pageable` method parameter.
|`Page<T>`|A `Slice` with additional information, e.g. the total number of results. Requires a `Pageable` method parameter.
|`GeoResult<T>`|A result entry with additional information, e.g. distance to a reference location.
|`GeoResults<T>`|A list of `GeoResult<T>` with additional information, e.g. average distance to a reference location.
|`GeoPage<T>`|A `Page` with `GeoResult<T>`, e.g. average distance to a reference location.
|`Future<T>`|A `Future`. Expects a method to be annotated with `@Async` and requires Spring's asynchronous method execution capability to be enabled.
|`CompletableFuture<T>`|A Java 8 `CompletableFuture`. Expects a method to be annotated with `@Async` and requires Spring's asynchronous method execution capability to be enabled.
|`ListenableFuture`|A `org.springframework.util.concurrent.ListenableFuture`. Expects a method to be annotated with `@Async` and requires Spring's asynchronous method execution capability to be enabled.
|`Slice`|A sized chunk of data with an indication of whether there is more data available. Requires a `Pageable` method parameter.
|`Page<T>`|A `Slice` with additional information, such as the total number of results. Requires a `Pageable` method parameter.
|`GeoResult<T>`|A result entry with additional information, such as the distance to a reference location.
|`GeoResults<T>`|A list of `GeoResult<T>` with additional information, such as the average distance to a reference location.
|`GeoPage<T>`|A `Page` with `GeoResult<T>`, such as the average distance to a reference location.
|===============

Loading…
Cancel
Save