Skip to content

Commit 3f9bed2

Browse files
christophstroblmp911de
authored andcommitted
Support TypedPropertyPath for queries and update.
1 parent 60980b6 commit 3f9bed2

File tree

5 files changed

+123
-21
lines changed

5 files changed

+123
-21
lines changed

spring-data-r2dbc/src/test/java/org/springframework/data/r2dbc/query/CriteriaUnitTests.java

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
*/
3535
class CriteriaUnitTests {
3636

37-
@Test // gh-289
37+
@Test // GH-289
3838
void fromCriteria() {
3939

4040
Criteria nested1 = where("foo").isNotNull();
@@ -46,7 +46,7 @@ void fromCriteria() {
4646
assertThat(criteria.getPrevious()).isEqualTo(Criteria.empty());
4747
}
4848

49-
@Test // gh-289
49+
@Test // GH-289
5050
void fromCriteriaOptimized() {
5151

5252
Criteria nested = where("foo").is("bar").and("baz").isNotNull();
@@ -55,7 +55,7 @@ void fromCriteriaOptimized() {
5555
assertThat(criteria).isSameAs(nested);
5656
}
5757

58-
@Test // gh-289
58+
@Test // GH-289
5959
void isEmpty() {
6060

6161
SoftAssertions.assertSoftly(softly -> {
@@ -77,7 +77,7 @@ void isEmpty() {
7777
});
7878
}
7979

80-
@Test // gh-64
80+
@Test // GH-64
8181
void andChainedCriteria() {
8282

8383
Criteria criteria = where("foo").is("bar").and("baz").isNotNull();
@@ -95,7 +95,7 @@ void andChainedCriteria() {
9595
assertThat(criteria.getValue()).isEqualTo("bar");
9696
}
9797

98-
@Test // gh-289
98+
@Test // GH-289
9999
void andGroupedCriteria() {
100100

101101
Criteria criteria = where("foo").is("bar").and(where("foo").is("baz"));
@@ -113,7 +113,7 @@ void andGroupedCriteria() {
113113
assertThat(criteria.getValue()).isEqualTo("bar");
114114
}
115115

116-
@Test // gh-64
116+
@Test // GH-64
117117
void orChainedCriteria() {
118118

119119
Criteria criteria = where("foo").is("bar").or("baz").isNotNull();
@@ -128,7 +128,7 @@ void orChainedCriteria() {
128128
assertThat(criteria.getValue()).isEqualTo("bar");
129129
}
130130

131-
@Test // gh-289
131+
@Test // GH-289
132132
void orGroupedCriteria() {
133133

134134
Criteria criteria = where("foo").is("bar").or(where("foo").is("baz"));
@@ -146,7 +146,7 @@ void orGroupedCriteria() {
146146
assertThat(criteria.getValue()).isEqualTo("bar");
147147
}
148148

149-
@Test // gh-64
149+
@Test // GH-64
150150
void shouldBuildEqualsCriteria() {
151151

152152
Criteria criteria = where("foo").is("bar");
@@ -166,7 +166,7 @@ void shouldBuildEqualsIgnoreCaseCriteria() {
166166
assertThat(criteria.isIgnoreCase()).isTrue();
167167
}
168168

169-
@Test // gh-64
169+
@Test // GH-64
170170
void shouldBuildNotEqualsCriteria() {
171171

172172
Criteria criteria = where("foo").not("bar");
@@ -176,7 +176,7 @@ void shouldBuildNotEqualsCriteria() {
176176
assertThat(criteria.getValue()).isEqualTo("bar");
177177
}
178178

179-
@Test // gh-64
179+
@Test // GH-64
180180
void shouldBuildInCriteria() {
181181

182182
Criteria criteria = where("foo").in("bar", "baz");
@@ -186,7 +186,7 @@ void shouldBuildInCriteria() {
186186
assertThat(criteria.getValue()).isEqualTo(Arrays.asList("bar", "baz"));
187187
}
188188

189-
@Test // gh-64
189+
@Test // GH-64
190190
void shouldBuildNotInCriteria() {
191191

192192
Criteria criteria = where("foo").notIn("bar", "baz");
@@ -196,7 +196,7 @@ void shouldBuildNotInCriteria() {
196196
assertThat(criteria.getValue()).isEqualTo(Arrays.asList("bar", "baz"));
197197
}
198198

199-
@Test // gh-64
199+
@Test // GH-64
200200
void shouldBuildGtCriteria() {
201201

202202
Criteria criteria = where("foo").greaterThan(1);
@@ -206,7 +206,7 @@ void shouldBuildGtCriteria() {
206206
assertThat(criteria.getValue()).isEqualTo(1);
207207
}
208208

209-
@Test // gh-64
209+
@Test // GH-64
210210
void shouldBuildGteCriteria() {
211211

212212
Criteria criteria = where("foo").greaterThanOrEquals(1);
@@ -216,7 +216,7 @@ void shouldBuildGteCriteria() {
216216
assertThat(criteria.getValue()).isEqualTo(1);
217217
}
218218

219-
@Test // gh-64
219+
@Test // GH-64
220220
void shouldBuildLtCriteria() {
221221

222222
Criteria criteria = where("foo").lessThan(1);
@@ -226,7 +226,7 @@ void shouldBuildLtCriteria() {
226226
assertThat(criteria.getValue()).isEqualTo(1);
227227
}
228228

229-
@Test // gh-64
229+
@Test // GH-64
230230
void shouldBuildLteCriteria() {
231231

232232
Criteria criteria = where("foo").lessThanOrEquals(1);
@@ -236,7 +236,7 @@ void shouldBuildLteCriteria() {
236236
assertThat(criteria.getValue()).isEqualTo(1);
237237
}
238238

239-
@Test // gh-64
239+
@Test // GH-64
240240
void shouldBuildLikeCriteria() {
241241

242242
Criteria criteria = where("foo").like("hello%");
@@ -255,7 +255,7 @@ void shouldBuildNotLikeCriteria() {
255255
assertThat(criteria.getValue()).isEqualTo("hello%");
256256
}
257257

258-
@Test // gh-64
258+
@Test // GH-64
259259
void shouldBuildIsNullCriteria() {
260260

261261
Criteria criteria = where("foo").isNull();
@@ -264,7 +264,7 @@ void shouldBuildIsNullCriteria() {
264264
assertThat(criteria.getComparator()).isEqualTo(Comparator.IS_NULL);
265265
}
266266

267-
@Test // gh-64
267+
@Test // GH-64
268268
void shouldBuildIsNotNullCriteria() {
269269

270270
Criteria criteria = where("foo").isNotNull();
@@ -273,7 +273,7 @@ void shouldBuildIsNotNullCriteria() {
273273
assertThat(criteria.getComparator()).isEqualTo(Comparator.IS_NOT_NULL);
274274
}
275275

276-
@Test // gh-282
276+
@Test // GH-282
277277
void shouldBuildIsTrueCriteria() {
278278

279279
Criteria criteria = where("foo").isTrue();
@@ -282,7 +282,7 @@ void shouldBuildIsTrueCriteria() {
282282
assertThat(criteria.getComparator()).isEqualTo(Comparator.IS_TRUE);
283283
}
284284

285-
@Test // gh-282
285+
@Test // GH-282
286286
void shouldBuildIsFalseCriteria() {
287287

288288
Criteria criteria = where("foo").isFalse();

spring-data-relational/src/main/java/org/springframework/data/relational/core/query/Criteria.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import org.jspecify.annotations.Nullable;
2828
import org.springframework.dao.InvalidDataAccessApiUsageException;
29+
import org.springframework.data.core.TypedPropertyPath;
2930
import org.springframework.data.relational.core.sql.IdentifierProcessing;
3031
import org.springframework.data.relational.core.sql.SqlIdentifier;
3132
import org.springframework.data.util.Pair;
@@ -54,6 +55,7 @@
5455
* @author Oliver Drotbohm
5556
* @author Roman Chigvintsev
5657
* @author Jens Schauder
58+
* @author Christoph Strobl
5759
* @since 2.0
5860
*/
5961
public class Criteria implements CriteriaDefinition {
@@ -157,6 +159,17 @@ public static CriteriaStep where(String column) {
157159
return new DefaultCriteriaStep(SqlIdentifier.unquoted(column));
158160
}
159161

162+
/**
163+
* Static factory method to create a Criteria using the provided {@code path}.
164+
*
165+
* @param property Must not be {@literal null}.
166+
* @return a new {@link CriteriaStep} object to complete the first {@link Criteria}.
167+
* @since 4.1
168+
*/
169+
public static <T, P> CriteriaStep where(TypedPropertyPath<T,P> property) {
170+
return where(TypedPropertyPath.of(property).toDotPath());
171+
}
172+
160173
/**
161174
* Create a new {@link Criteria} and combine it with {@code AND} using the provided {@code column} name.
162175
*
@@ -177,6 +190,18 @@ protected Criteria createCriteria(Comparator comparator, @Nullable Object value)
177190
};
178191
}
179192

193+
/**
194+
* Create a new {@link Criteria} and combine it with {@code AND} using the provided {@code path}.
195+
*
196+
* @param property Must not be {@literal null}.
197+
* @return a new {@link CriteriaStep} object to complete the next {@link Criteria}.
198+
* @since 4.1
199+
*/
200+
@CheckReturnValue
201+
public <T,P> CriteriaStep and(TypedPropertyPath<T,P> property) {
202+
return and(TypedPropertyPath.of(property).toDotPath());
203+
}
204+
180205
/**
181206
* Create a new {@link Criteria} and combine it as group with {@code AND} using the provided {@link Criteria} group.
182207
*
@@ -227,6 +252,18 @@ protected Criteria createCriteria(Comparator comparator, @Nullable Object value)
227252
};
228253
}
229254

255+
/**
256+
* Create a new {@link Criteria} and combine it with {@code OR} using the provided {@code path}.
257+
*
258+
* @param property Must not be {@literal null}.
259+
* @return a new {@link CriteriaStep} object to complete the next {@link Criteria}.
260+
* @since 4.1
261+
*/
262+
@CheckReturnValue
263+
public <T,P> CriteriaStep or(TypedPropertyPath<T,P> property) {
264+
return or(TypedPropertyPath.of(property).toDotPath());
265+
}
266+
230267
/**
231268
* Create a new {@link Criteria} and combine it as group with {@code OR} using the provided {@link Criteria} group.
232269
*

spring-data-relational/src/main/java/org/springframework/data/relational/core/query/Query.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
import java.util.List;
2323
import java.util.Optional;
2424
import java.util.stream.Collectors;
25+
import java.util.stream.Stream;
2526

2627
import org.jspecify.annotations.Nullable;
28+
import org.springframework.data.core.TypedPropertyPath;
2729
import org.springframework.data.domain.Pageable;
2830
import org.springframework.data.domain.Sort;
2931
import org.springframework.data.relational.core.sql.SqlIdentifier;
@@ -35,6 +37,7 @@
3537
* class are designed to be used in a fluent style creating immutable objects.
3638
*
3739
* @author Mark Paluch
40+
* @author Christoph Strobl
3841
* @since 2.0
3942
* @see Criteria
4043
* @see Sort
@@ -114,7 +117,19 @@ public Query columns(Collection<String> columns) {
114117

115118
Assert.notNull(columns, "Columns must not be null");
116119

117-
return withColumns(columns.stream().map(SqlIdentifier::unquoted).collect(Collectors.toList()));
120+
return withColumns(columns.stream());
121+
}
122+
123+
/**
124+
* Add columns to the query.
125+
*
126+
* @param properties
127+
* @return a new {@link Query} object containing the former settings with {@code columns} applied.
128+
* @since 4.1
129+
*/
130+
@CheckReturnValue
131+
public <T> Query columnsOf(Collection<TypedPropertyPath<T,?>> properties) {
132+
return withColumns(properties.stream().map(TypedPropertyPath::of).map(TypedPropertyPath::toDotPath));
118133
}
119134

120135
/**
@@ -132,6 +147,10 @@ public Query columns(SqlIdentifier... columns) {
132147
return withColumns(Arrays.asList(columns));
133148
}
134149

150+
private Query withColumns(Stream<String> columns) {
151+
return withColumns(columns.map(SqlIdentifier::unquoted).collect(Collectors.toList()));
152+
}
153+
135154
/**
136155
* Add columns to the query.
137156
*

spring-data-relational/src/main/java/org/springframework/data/relational/core/query/Update.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.StringJoiner;
2222

2323
import org.jspecify.annotations.Nullable;
24+
import org.springframework.data.core.TypedPropertyPath;
2425
import org.springframework.data.relational.core.sql.IdentifierProcessing;
2526
import org.springframework.data.relational.core.sql.SqlIdentifier;
2627
import org.springframework.lang.CheckReturnValue;
@@ -32,6 +33,7 @@
3233
*
3334
* @author Mark Paluch
3435
* @author Oliver Drotbohm
36+
* @author Christoph Strobl
3537
* @since 2.0
3638
*/
3739
public class Update {
@@ -65,6 +67,18 @@ public static Update update(String column, @Nullable Object value) {
6567
return EMPTY.set(column, value);
6668
}
6769

70+
/**
71+
* Static factory method to create an {@link Update} using the provided path.
72+
*
73+
* @param property must not be {@literal null}.
74+
* @param value can be {@literal null}.
75+
* @return new instance of {@link Update}.
76+
* @since 4.1
77+
*/
78+
public static <T,P> Update update(TypedPropertyPath<T,P> property, @Nullable Object value) {
79+
return update(TypedPropertyPath.of(property).toDotPath(), value);
80+
}
81+
6882
/**
6983
* Update a column by assigning a value.
7084
*
@@ -80,6 +94,19 @@ public Update set(String column, @Nullable Object value) {
8094
return addMultiFieldOperation(SqlIdentifier.unquoted(column), value);
8195
}
8296

97+
/**
98+
* Update a path by assigning a value.
99+
*
100+
* @param property must not be {@literal null}.
101+
* @param value can be {@literal null}.
102+
* @return new instance of {@link Update}.
103+
* @since 4.1
104+
*/
105+
@CheckReturnValue
106+
public <T,P> Update set(TypedPropertyPath<T,P> property, @Nullable Object value) {
107+
return set(TypedPropertyPath.of(property).toDotPath(), value);
108+
}
109+
83110
/**
84111
* Update a column by assigning a value.
85112
*

spring-data-relational/src/test/java/org/springframework/data/relational/core/query/UpdateUnitTests.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
* Unit tests for {@link Update}.
2424
*
2525
* @author Mark Paluch
26+
* @author Christoph Strobl
2627
*/
2728
public class UpdateUnitTests {
2829

@@ -31,4 +32,22 @@ public void shouldRenderUpdateToString() {
3132

3233
assertThat(Update.update("foo", "baz").set("bar", 42)).hasToString("SET foo = 'baz', bar = 42");
3334
}
35+
36+
@Test // GH-2226
37+
public void shouldRenderUpdateWithTypedPropertyPathToString() {
38+
assertThat(Update.update(Person::getFirstName, "baz").set("bar", 42)).hasToString("SET firstName = 'baz', bar = 42");
39+
}
40+
41+
static class Person {
42+
private String firstName;
43+
private String lastName;
44+
45+
public String getFirstName() {
46+
return firstName;
47+
}
48+
49+
public String getLastName() {
50+
return lastName;
51+
}
52+
}
3453
}

0 commit comments

Comments
 (0)