Skip to content

Commit 21d5d00

Browse files
committed
Documentation
1 parent 9e7bfa9 commit 21d5d00

File tree

1 file changed

+167
-21
lines changed

1 file changed

+167
-21
lines changed

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

Lines changed: 167 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,188 @@
1-
[[type-safe-property-references]]
2-
= Type-safe Property References
1+
[[property-paths]]
2+
= Property Paths
33

4-
Type-safe property references address a common source of friction in data access code: The reliance on literal, dot-separated property path strings.
5-
Such stringly-typed references are fragile during refactoring difficult to identify as they often lack context.
6-
Type-safe property paths favor explicitness and compiler validation by deriving property paths from Java method references.
4+
This chapter covers the concept of property paths.
5+
Property paths are a form of navigation through domain classes to apply certain aspects in the context of interacting with the model.
6+
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 its owning type and can consist of one to many segments.
78

8-
A property path is a simple, transportable representation of object navigation.
9-
When expressed as a method-reference the compiler participates in validation and IDEs provide meaningful refactoring support.
10-
The result is code that reads naturally, fails fast on renames, and integrates cleanly with existing query and sorting abstractions, for example:
9+
[TIP]
10+
====
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.
1113
12-
[source,java]
14+
Understanding how to navigate and reference these properties is essential for working with repositories and query operations.
15+
====
16+
17+
[[property-path-overview]]
18+
== Property Path Overview
19+
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.
22+
23+
.Domain model example
24+
[tabs]
25+
======
26+
Java::
27+
+
28+
[source,java,role="primary"]
1329
----
14-
TypedPropertyPath.of(Person::getAddress)
15-
.then(Address::getCity);
30+
class Person {
31+
String firstname, lastname;
32+
int age;
33+
Address address;
34+
List<Address> previousAddresses;
35+
36+
String getFirstname() { … }; // other property accessors omitted for brevity
37+
38+
}
39+
40+
class Address {
41+
String city, street;
42+
43+
// accessors omitted for brevity
44+
45+
}
1646
----
1747
18-
The expression above constructs a path equivalent to `address.city` while remaining resilient to refactoring.
19-
Property resolution is performed by inspecting the supplied method references; any mismatch becomes visible at compile time.
48+
Kotlin::
49+
+
50+
[source,kotlin,role="secondary"]
51+
----
52+
class Person {
53+
var firstname: String? = null
54+
var lastname: String? = null
55+
var age: Int = 0
56+
var address: Address? = null
57+
var previousAddresses: List<Address> = emptyList()
58+
}
59+
60+
class Address {
61+
var city: String? = null
62+
var street: String? = null
63+
}
64+
----
65+
======
2066

21-
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:
67+
Property paths use dot-notation to express property references throughout Spring Data operations, such as sorting and filtering:
2268

23-
.Stringly-typed programming
69+
.Dot-notation property references
2470
[source,java]
2571
----
26-
Sort.by("address.city", "address.street")
72+
Sort.by("firstname", "address.city")
2773
----
2874

29-
You can also use it inline for operations like sorting:
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.
3077

31-
.Type-safe Property Path
32-
[source,java]
78+
Collection and array properties support transparent traversal to their component type, enabling direct reference to nested properties:
79+
80+
----
81+
Sort.by("address.city") <1>
82+
83+
Sort.by("previousAddresses") <2>
84+
85+
Sort.by("previousAddresses.city") <3>
86+
----
87+
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.
91+
92+
String-based property paths offer simplicity and can be broadly applied but there are tradeoffs to consider:
93+
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.
98+
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.
102+
103+
NOTE: For implementation details, refer to <<property-path-internals>> for more information.
104+
105+
[[property-path-internals]]
106+
=== Property Path Internals
107+
108+
The `org.springframework.data.core` package is the basis for Spring Data's navigation across domain classes.
109+
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+
111+
Together they provide:
112+
113+
* Generic type resolution and introspection
114+
* Property path creation and validation
115+
* Actual type resolution for complex properties such as collections and maps
116+
117+
[[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.
122+
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.
125+
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:
127+
128+
[tabs]
129+
======
130+
Java::
131+
+
132+
[source,java,role="primary"]
133+
----
134+
TypedPropertyPath.of(Person::getAddress)
135+
.then(Address::getCity);
136+
----
137+
138+
Kotlin::
139+
+
140+
[source,kotlin,role="secondary"]
33141
----
142+
TypedPropertyPath.of<Person, Address>(Person::address)
143+
.then(Address::city)
144+
145+
// Kotlin Exension
146+
KTypedPropertyPath.of(Person::address).then(Address::city)
147+
----
148+
======
149+
150+
=== Building Type-safe Property Paths
151+
152+
Type-safe property paths compose method references to construct navigation expressions.
153+
The following examples demonstrate inline usage and composition:
154+
155+
.Type-safe Property Path Construction
156+
[tabs]
157+
======
158+
Java::
159+
+
160+
[source,java,role="primary"]
161+
----
162+
// Inline usage with Sort
34163
Sort.by(Person::getFirstName, Person::getLastName);
164+
165+
// Composed navigation
166+
TypedPropertyPath.of(Person::getAddress)
167+
.then(Address::getCity);
168+
----
169+
170+
Kotlin::
171+
+
172+
[source,kotlin,role="secondary"]
173+
----
174+
// Inline usage with Sort
175+
Sort.by(Person::firstName, Person::lastName);
176+
177+
// Kotlin extension with composed navigation
178+
KTypedPropertyPath.of(Person::address)
179+
.then(Address::city)
35180
----
181+
======
36182

37-
`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:
38184

39-
.Type-safe Property Path
185+
.Integration with Criteria API
40186
[source,java]
41187
----
42188
Criteria.where(Person::getAddress)

0 commit comments

Comments
 (0)