Browse Source

Support TypedPropertyPath for queries and update.

Closes #2226
Original pull request: #2227
main
Christoph Strobl 2 weeks ago committed by Mark Paluch
parent
commit
ed2ea4aa1e
No known key found for this signature in database
GPG Key ID: 55BC6374BAA9D973
  1. 40
      spring-data-r2dbc/src/test/java/org/springframework/data/r2dbc/query/CriteriaUnitTests.java
  2. 37
      spring-data-relational/src/main/java/org/springframework/data/relational/core/query/Criteria.java
  3. 21
      spring-data-relational/src/main/java/org/springframework/data/relational/core/query/Query.java
  4. 27
      spring-data-relational/src/main/java/org/springframework/data/relational/core/query/Update.java
  5. 19
      spring-data-relational/src/test/java/org/springframework/data/relational/core/query/UpdateUnitTests.java

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

@ -34,7 +34,7 @@ import org.springframework.data.relational.core.sql.SqlIdentifier; @@ -34,7 +34,7 @@ import org.springframework.data.relational.core.sql.SqlIdentifier;
*/
class CriteriaUnitTests {
@Test // gh-289
@Test // GH-289
void fromCriteria() {
Criteria nested1 = where("foo").isNotNull();
@ -46,7 +46,7 @@ class CriteriaUnitTests { @@ -46,7 +46,7 @@ class CriteriaUnitTests {
assertThat(criteria.getPrevious()).isEqualTo(Criteria.empty());
}
@Test // gh-289
@Test // GH-289
void fromCriteriaOptimized() {
Criteria nested = where("foo").is("bar").and("baz").isNotNull();
@ -55,7 +55,7 @@ class CriteriaUnitTests { @@ -55,7 +55,7 @@ class CriteriaUnitTests {
assertThat(criteria).isSameAs(nested);
}
@Test // gh-289
@Test // GH-289
void isEmpty() {
SoftAssertions.assertSoftly(softly -> {
@ -77,7 +77,7 @@ class CriteriaUnitTests { @@ -77,7 +77,7 @@ class CriteriaUnitTests {
});
}
@Test // gh-64
@Test // GH-64
void andChainedCriteria() {
Criteria criteria = where("foo").is("bar").and("baz").isNotNull();
@ -95,7 +95,7 @@ class CriteriaUnitTests { @@ -95,7 +95,7 @@ class CriteriaUnitTests {
assertThat(criteria.getValue()).isEqualTo("bar");
}
@Test // gh-289
@Test // GH-289
void andGroupedCriteria() {
Criteria criteria = where("foo").is("bar").and(where("foo").is("baz"));
@ -113,7 +113,7 @@ class CriteriaUnitTests { @@ -113,7 +113,7 @@ class CriteriaUnitTests {
assertThat(criteria.getValue()).isEqualTo("bar");
}
@Test // gh-64
@Test // GH-64
void orChainedCriteria() {
Criteria criteria = where("foo").is("bar").or("baz").isNotNull();
@ -128,7 +128,7 @@ class CriteriaUnitTests { @@ -128,7 +128,7 @@ class CriteriaUnitTests {
assertThat(criteria.getValue()).isEqualTo("bar");
}
@Test // gh-289
@Test // GH-289
void orGroupedCriteria() {
Criteria criteria = where("foo").is("bar").or(where("foo").is("baz"));
@ -146,7 +146,7 @@ class CriteriaUnitTests { @@ -146,7 +146,7 @@ class CriteriaUnitTests {
assertThat(criteria.getValue()).isEqualTo("bar");
}
@Test // gh-64
@Test // GH-64
void shouldBuildEqualsCriteria() {
Criteria criteria = where("foo").is("bar");
@ -166,7 +166,7 @@ class CriteriaUnitTests { @@ -166,7 +166,7 @@ class CriteriaUnitTests {
assertThat(criteria.isIgnoreCase()).isTrue();
}
@Test // gh-64
@Test // GH-64
void shouldBuildNotEqualsCriteria() {
Criteria criteria = where("foo").not("bar");
@ -176,7 +176,7 @@ class CriteriaUnitTests { @@ -176,7 +176,7 @@ class CriteriaUnitTests {
assertThat(criteria.getValue()).isEqualTo("bar");
}
@Test // gh-64
@Test // GH-64
void shouldBuildInCriteria() {
Criteria criteria = where("foo").in("bar", "baz");
@ -186,7 +186,7 @@ class CriteriaUnitTests { @@ -186,7 +186,7 @@ class CriteriaUnitTests {
assertThat(criteria.getValue()).isEqualTo(Arrays.asList("bar", "baz"));
}
@Test // gh-64
@Test // GH-64
void shouldBuildNotInCriteria() {
Criteria criteria = where("foo").notIn("bar", "baz");
@ -196,7 +196,7 @@ class CriteriaUnitTests { @@ -196,7 +196,7 @@ class CriteriaUnitTests {
assertThat(criteria.getValue()).isEqualTo(Arrays.asList("bar", "baz"));
}
@Test // gh-64
@Test // GH-64
void shouldBuildGtCriteria() {
Criteria criteria = where("foo").greaterThan(1);
@ -206,7 +206,7 @@ class CriteriaUnitTests { @@ -206,7 +206,7 @@ class CriteriaUnitTests {
assertThat(criteria.getValue()).isEqualTo(1);
}
@Test // gh-64
@Test // GH-64
void shouldBuildGteCriteria() {
Criteria criteria = where("foo").greaterThanOrEquals(1);
@ -216,7 +216,7 @@ class CriteriaUnitTests { @@ -216,7 +216,7 @@ class CriteriaUnitTests {
assertThat(criteria.getValue()).isEqualTo(1);
}
@Test // gh-64
@Test // GH-64
void shouldBuildLtCriteria() {
Criteria criteria = where("foo").lessThan(1);
@ -226,7 +226,7 @@ class CriteriaUnitTests { @@ -226,7 +226,7 @@ class CriteriaUnitTests {
assertThat(criteria.getValue()).isEqualTo(1);
}
@Test // gh-64
@Test // GH-64
void shouldBuildLteCriteria() {
Criteria criteria = where("foo").lessThanOrEquals(1);
@ -236,7 +236,7 @@ class CriteriaUnitTests { @@ -236,7 +236,7 @@ class CriteriaUnitTests {
assertThat(criteria.getValue()).isEqualTo(1);
}
@Test // gh-64
@Test // GH-64
void shouldBuildLikeCriteria() {
Criteria criteria = where("foo").like("hello%");
@ -255,7 +255,7 @@ class CriteriaUnitTests { @@ -255,7 +255,7 @@ class CriteriaUnitTests {
assertThat(criteria.getValue()).isEqualTo("hello%");
}
@Test // gh-64
@Test // GH-64
void shouldBuildIsNullCriteria() {
Criteria criteria = where("foo").isNull();
@ -264,7 +264,7 @@ class CriteriaUnitTests { @@ -264,7 +264,7 @@ class CriteriaUnitTests {
assertThat(criteria.getComparator()).isEqualTo(Comparator.IS_NULL);
}
@Test // gh-64
@Test // GH-64
void shouldBuildIsNotNullCriteria() {
Criteria criteria = where("foo").isNotNull();
@ -273,7 +273,7 @@ class CriteriaUnitTests { @@ -273,7 +273,7 @@ class CriteriaUnitTests {
assertThat(criteria.getComparator()).isEqualTo(Comparator.IS_NOT_NULL);
}
@Test // gh-282
@Test // GH-282
void shouldBuildIsTrueCriteria() {
Criteria criteria = where("foo").isTrue();
@ -282,7 +282,7 @@ class CriteriaUnitTests { @@ -282,7 +282,7 @@ class CriteriaUnitTests {
assertThat(criteria.getComparator()).isEqualTo(Comparator.IS_TRUE);
}
@Test // gh-282
@Test // GH-282
void shouldBuildIsFalseCriteria() {
Criteria criteria = where("foo").isFalse();

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

@ -26,6 +26,7 @@ import java.util.StringJoiner; @@ -26,6 +26,7 @@ import java.util.StringJoiner;
import org.jspecify.annotations.Nullable;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.core.TypedPropertyPath;
import org.springframework.data.relational.core.sql.IdentifierProcessing;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.data.util.Pair;
@ -54,6 +55,7 @@ import org.springframework.util.Assert; @@ -54,6 +55,7 @@ import org.springframework.util.Assert;
* @author Oliver Drotbohm
* @author Roman Chigvintsev
* @author Jens Schauder
* @author Christoph Strobl
* @since 2.0
*/
public class Criteria implements CriteriaDefinition {
@ -157,6 +159,17 @@ public class Criteria implements CriteriaDefinition { @@ -157,6 +159,17 @@ public class Criteria implements CriteriaDefinition {
return new DefaultCriteriaStep(SqlIdentifier.unquoted(column));
}
/**
* Static factory method to create a Criteria using the provided {@code path}.
*
* @param property Must not be {@literal null}.
* @return a new {@link CriteriaStep} object to complete the first {@link Criteria}.
* @since 4.1
*/
public static <T, P> CriteriaStep where(TypedPropertyPath<T,P> property) {
return where(property.toDotPath());
}
/**
* Create a new {@link Criteria} and combine it with {@code AND} using the provided {@code column} name.
*
@ -177,6 +190,18 @@ public class Criteria implements CriteriaDefinition { @@ -177,6 +190,18 @@ public class Criteria implements CriteriaDefinition {
};
}
/**
* Create a new {@link Criteria} and combine it with {@code AND} using the provided {@code path}.
*
* @param property Must not be {@literal null}.
* @return a new {@link CriteriaStep} object to complete the next {@link Criteria}.
* @since 4.1
*/
@CheckReturnValue
public <T,P> CriteriaStep and(TypedPropertyPath<T,P> property) {
return and(TypedPropertyPath.of(property).toDotPath());
}
/**
* Create a new {@link Criteria} and combine it as group with {@code AND} using the provided {@link Criteria} group.
*
@ -227,6 +252,18 @@ public class Criteria implements CriteriaDefinition { @@ -227,6 +252,18 @@ public class Criteria implements CriteriaDefinition {
};
}
/**
* Create a new {@link Criteria} and combine it with {@code OR} using the provided {@code path}.
*
* @param property Must not be {@literal null}.
* @return a new {@link CriteriaStep} object to complete the next {@link Criteria}.
* @since 4.1
*/
@CheckReturnValue
public <T,P> CriteriaStep or(TypedPropertyPath<T,P> property) {
return or(TypedPropertyPath.of(property).toDotPath());
}
/**
* Create a new {@link Criteria} and combine it as group with {@code OR} using the provided {@link Criteria} group.
*

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

@ -22,8 +22,10 @@ import java.util.Collections; @@ -22,8 +22,10 @@ import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.TypedPropertyPath;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.relational.core.sql.SqlIdentifier;
@ -35,6 +37,7 @@ import org.springframework.util.Assert; @@ -35,6 +37,7 @@ import org.springframework.util.Assert;
* class are designed to be used in a fluent style creating immutable objects.
*
* @author Mark Paluch
* @author Christoph Strobl
* @since 2.0
* @see Criteria
* @see Sort
@ -114,7 +117,19 @@ public class Query { @@ -114,7 +117,19 @@ public class Query {
Assert.notNull(columns, "Columns must not be null");
return withColumns(columns.stream().map(SqlIdentifier::unquoted).collect(Collectors.toList()));
return withColumns(columns.stream());
}
/**
* Add columns to the query.
*
* @param properties
* @return a new {@link Query} object containing the former settings with {@code columns} applied.
* @since 4.1
*/
@CheckReturnValue
public <T> Query columnsOf(Collection<TypedPropertyPath<T,?>> properties) {
return withColumns(properties.stream().map(TypedPropertyPath::of).map(TypedPropertyPath::toDotPath));
}
/**
@ -132,6 +147,10 @@ public class Query { @@ -132,6 +147,10 @@ public class Query {
return withColumns(Arrays.asList(columns));
}
private Query withColumns(Stream<String> columns) {
return withColumns(columns.map(SqlIdentifier::unquoted).collect(Collectors.toList()));
}
/**
* Add columns to the query.
*

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

@ -21,6 +21,7 @@ import java.util.Map; @@ -21,6 +21,7 @@ import java.util.Map;
import java.util.StringJoiner;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.TypedPropertyPath;
import org.springframework.data.relational.core.sql.IdentifierProcessing;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.lang.CheckReturnValue;
@ -32,6 +33,7 @@ import org.springframework.util.Assert; @@ -32,6 +33,7 @@ import org.springframework.util.Assert;
*
* @author Mark Paluch
* @author Oliver Drotbohm
* @author Christoph Strobl
* @since 2.0
*/
public class Update {
@ -65,6 +67,18 @@ public class Update { @@ -65,6 +67,18 @@ public class Update {
return EMPTY.set(column, value);
}
/**
* Static factory method to create an {@link Update} using the provided path.
*
* @param property must not be {@literal null}.
* @param value can be {@literal null}.
* @return new instance of {@link Update}.
* @since 4.1
*/
public static <T,P> Update update(TypedPropertyPath<T,P> property, @Nullable Object value) {
return update(property.toDotPath(), value);
}
/**
* Update a column by assigning a value.
*
@ -80,6 +94,19 @@ public class Update { @@ -80,6 +94,19 @@ public class Update {
return addMultiFieldOperation(SqlIdentifier.unquoted(column), value);
}
/**
* Update a path by assigning a value.
*
* @param property must not be {@literal null}.
* @param value can be {@literal null}.
* @return new instance of {@link Update}.
* @since 4.1
*/
@CheckReturnValue
public <T,P> Update set(TypedPropertyPath<T,P> property, @Nullable Object value) {
return set(property.toDotPath(), value);
}
/**
* Update a column by assigning a value.
*

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

@ -23,6 +23,7 @@ import static org.assertj.core.api.Assertions.*; @@ -23,6 +23,7 @@ import static org.assertj.core.api.Assertions.*;
* Unit tests for {@link Update}.
*
* @author Mark Paluch
* @author Christoph Strobl
*/
public class UpdateUnitTests {
@ -31,4 +32,22 @@ public class UpdateUnitTests { @@ -31,4 +32,22 @@ public class UpdateUnitTests {
assertThat(Update.update("foo", "baz").set("bar", 42)).hasToString("SET foo = 'baz', bar = 42");
}
@Test // GH-2226
public void shouldRenderUpdateWithTypedPropertyPathToString() {
assertThat(Update.update(Person::getFirstName, "baz").set("bar", 42)).hasToString("SET firstName = 'baz', bar = 42");
}
static class Person {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
}

Loading…
Cancel
Save