Skip to content

Commit bb4541d

Browse files
committed
Documentation
1 parent 8739779 commit bb4541d

File tree

1 file changed

+52
-55
lines changed

1 file changed

+52
-55
lines changed

src/main/antora/modules/ROOT/pages/property-paths.adoc

Lines changed: 52 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,23 @@
44
This chapter covers the concept of property paths.
55
Property paths are a form of navigation through domain classes to apply certain aspects in the context of interacting with the model.
66
Application code provides property paths to data access components to express intents such as selection of properties within a query, forming predicates, or applying sorting.
7-
A property path originates from a owning type and can consist of one to many segments.
8-
9-
In Spring Data, the classes that form the backbone of your persistent domain model and that are accessed through Spring Data called entities.
10-
An entry point for the object graph is called aggregate root in alignment with domain-driven design.
7+
A property path originates from its owning type and can consist of one to many segments.
118

129
[TIP]
1310
====
14-
Spring Data considers domain types to be entities, more specifically aggregates.
15-
So you will see the term "entity" used throughout the documentation that can be interchanged with the term "domain type" or "aggregate".
11+
Following domain-driven design principles the classes that form the backbone of your persistent domain model and that are accessed through Spring Data are called entities.
12+
An entry point to the object graph is called aggregate root.
1613
17-
As you might have noticed in the introduction it already hinted towards domain-driven concepts.
18-
We consider domain objects in the sense of DDD.
19-
Domain objects have identifiers (otherwise these would be identity-less value objects), and we somehow need to refer to identifiers when working with certain patterns to access data.
20-
Referring to identifiers will become more meaningful as we talk about repositories and query methods.
14+
Understanding how to navigate and reference these properties is essential for working with repositories and query operations.
2115
====
2216

2317
[[property-path-overview]]
2418
== Property Path Overview
2519

26-
Let's start from a domain model, consider the simple domain model consisting of `Person` and `Address` classes with a couple of properties each:
20+
Property paths provide a simple, text-based mechanism to navigate domain model properties.
21+
This section introduces the fundamentals of property path navigation and demonstrates trade-offs between string-based and type-safe approaches.
2722

28-
.Domain model
23+
.Domain model example
2924
[tabs]
3025
======
3126
Java::
@@ -69,18 +64,18 @@ class Address {
6964
----
7065
======
7166

72-
Property paths let you express references to properties using dot-path notation, for example when declaring sort orders:
67+
Property paths use dot-notation to express property references throughout Spring Data operations, such as sorting and filtering:
7368

74-
.Sorting
69+
.Dot-notation property references
7570
[source,java]
7671
----
77-
Sort.by("firstname", "lastname")
72+
Sort.by("firstname", "address.city")
7873
----
7974

80-
Dot-path notation addresses individual properties that are separated by a dot `.`.
81-
Methods accepting a `String` property path typically allow usage of single-segment property paths (i.e. reference to a top-level property) or multi-segment properties unless otherwise indicated.
75+
A property path consists of one or more segments separated by a dot (`.`).
76+
Methods accepting property paths support single-segment references (top-level properties) and multi-segment navigation unless otherwise indicated.
8277

83-
Dot-path traversal into properties considers the component type of array and collection properties allowing references into the actual type for a simple navigation across collection-like types.
78+
Collection and array properties support transparent traversal to their component type, enabling direct reference to nested properties:
8479

8580
----
8681
Sort.by("address.city") <1>
@@ -90,44 +85,45 @@ Sort.by("previousAddresses") <2>
9085
Sort.by("previousAddresses.city") <3>
9186
----
9287

93-
<1> Sort by the `city` of the `address` object.
94-
<2> Sort by the `Person.previousAddresses` collection.
95-
Applicable for technologies that support sorting by arrays or lists
96-
<3> Sort by the `city` of any previous address.
88+
<1> Navigate from the top-level `address` property to the `city` field.
89+
<2> Reference the entire `previousAddresses` collection (supported by certain technologies for collection-based sorting).
90+
<3> Navigate through the collection to sort by the `city` field of each address.
9791

98-
String-based property paths are simple and widely applicable because they do not require additional dependencies.
99-
There are various tradeoffs to consider:
92+
String-based property paths offer simplicity and can be broadly applied but there are tradeoffs to consider:
10093

101-
* Simple and flexible: Generalized and simple usage by expressing a property reference as string literal or constant.
102-
* Untyped: String paths do not carry compile-time type information and do not have a dependency on the underlying domain type.
103-
* Context-less: Without the associated domain type, string literals are easy to miss when renaming or refactoring the model.
94+
* **Flexibility**: Property paths are flexible and can be constructed from constant string, configuration or as result of user input.
95+
* **Untyped**: String paths do not carry compile-time type information.
96+
Typed as textual content they do not have a dependency on the underlying domain type.
97+
* **Refactoring risk**: Renaming domain properties requires often manual updates to string literals; IDEs cannot reliably track these references.
10498

105-
For better refactoring safety and stronger type consistency, prefer type-safe property references that associate property paths with type information, enabling IDE refactoring and compiler validation.
106-
<<type-safe-property-references>> shows how to use method references to express property paths in a type-safe manner.
99+
To improve refactoring safety and type consistency, prefer type-safe property references using method references.
100+
This approach associates property paths with compile-time type information and enables compiler validation and IDE-driven refactoring.
101+
See <<type-safe-property-references>> for details.
107102

108-
NOTE: For advanced usage: Property paths are translated to javadoc:org.springframework.data.core.PropertyPath[], read more about <<property-path-internals>>.
103+
NOTE: For implementation details, refer to <<property-path-internals>> for more information.
109104

110105
[[property-path-internals]]
111106
=== Property Path Internals
112107

113108
The `org.springframework.data.core` package is the basis for Spring Data's navigation across domain classes.
114109
The javadoc:org.springframework.data.core.TypeInformation[] inteface provides type introspection capable of resolving the type of a property. javadoc:org.springframework.data.core.PropertyPath[] represents a textual navigation path through a domain class.
110+
115111
Together they provide:
116112

117-
* Type introspection and resolution of generics
118-
* Creation and validation of property paths
119-
* Actual type resolution for properties that hold a objects of an actual type such as collections and maps
113+
* Generic type resolution and introspection
114+
* Property path creation and validation
115+
* Actual type resolution for complex properties such as collections and maps
120116

121117
[[type-safe-property-references]]
122-
== Type-safe Property References
118+
== Type-safe Property-References
119+
120+
Type-safe property-references eliminate a common source of errors in data access code: Brittle, string-based property references.
121+
This section explains how method references can be used to express refactoring-safe property paths.
123122

124-
Type-safe property references address a common source of friction in data access code: The reliance on literal, dot-separated property path strings.
125-
Such stringly-typed references are fragile during refactoring difficult to identify as they often lack context.
126-
Type-safe property paths favor explicitness and compiler validation by deriving property paths from Java method references.
123+
While a property path is a simple representation of object navigation, String-based property paths are inherently fragile during refactoring as they can be easily missed with an increasing distance between the property definition and its usage.
124+
Type-safe alternatives derive property paths from method references, enabling the compiler to validate property names and IDEs to support refactoring operations.
127125

128-
A property path is a simple, transportable representation of object navigation.
129-
When expressed as a method-reference the compiler participates in validation and IDEs provide meaningful refactoring support.
130-
The result is code that reads naturally, fails fast on renames, and integrates cleanly with existing query and sorting abstractions, for example:
126+
Consider the practical difference: The following examples express the same intent - sorting by `address.city` - but only the type-safe version benefits from compiler validation and IDE support:
131127

132128
[tabs]
133129
======
@@ -144,48 +140,49 @@ Kotlin::
144140
[source,kotlin,role="secondary"]
145141
----
146142
TypedPropertyPath.of<Person, Address>(Person::address)
147-
.then(Address::city);
143+
.then(Address::city)
148144
149145
// Kotlin Exension
150146
KTypedPropertyPath.of(Person::address).then(Address::city)
151147
----
152148
======
153149

154-
The expression above constructs a path equivalent to `address.city` while remaining resilient to refactoring.
155-
Property resolution is performed by inspecting the supplied method references; any mismatch becomes visible at compile time.
150+
=== Building Type-safe Property Paths
156151

157-
By comparing a literal-based approach as the following example you can immediately spot the same intent while the mechanism of using strings removes any type context:
152+
Type-safe property paths compose method references to construct navigation expressions.
153+
The following examples demonstrate inline usage and composition:
158154

159-
.Stringly-typed programming
160-
[source,java]
161-
----
162-
Sort.by("address.city", "address.street")
163-
----
164-
165-
You can also use it inline for operations like sorting:
166-
167-
.Type-safe Property Path
155+
.Type-safe Property Path Construction
168156
[tabs]
169157
======
170158
Java::
171159
+
172160
[source,java,role="primary"]
173161
----
162+
// Inline usage with Sort
174163
Sort.by(Person::getFirstName, Person::getLastName);
175164
165+
// Composed navigation
166+
TypedPropertyPath.of(Person::getAddress)
167+
.then(Address::getCity);
176168
----
177169
178170
Kotlin::
179171
+
180172
[source,kotlin,role="secondary"]
181173
----
174+
// Inline usage with Sort
182175
Sort.by(Person::firstName, Person::lastName);
176+
177+
// Kotlin extension with composed navigation
178+
KTypedPropertyPath.of(Person::address)
179+
.then(Address::city)
183180
----
184181
======
185182

186-
`TypedPropertyPath` can integrate seamlessly with query abstractions or criteria builders:
183+
Type-safe property paths integrate seamlessly with query abstractions and criteria builders, enabling declarative query construction without string-based property references:
187184

188-
.Type-safe Property Path
185+
.Integration with Criteria API
189186
[source,java]
190187
----
191188
Criteria.where(Person::getAddress)

0 commit comments

Comments
 (0)