Browse Source

Accept TypedPropertyPath when creating Criteria entries.

Original Pull Request: #5148
pull/4763/merge
Jens Schauder 3 weeks ago committed by Christoph Strobl
parent
commit
a877ffebc6
No known key found for this signature in database
GPG Key ID: E6054036D0C37A4B
  1. 21
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java
  2. 23
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java
  3. 40
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaUnitTests.java
  4. 50
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaWithPropertyReferenceUnitTests.java

21
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java

@ -26,6 +26,7 @@ import java.util.stream.Stream; @@ -26,6 +26,7 @@ import java.util.stream.Stream;
import org.bson.Document;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.TypedPropertyPath;
import org.springframework.data.domain.KeysetScrollPosition;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Window;
@ -930,10 +931,14 @@ public interface MongoOperations extends FluentMongoOperations { @@ -930,10 +931,14 @@ public interface MongoOperations extends FluentMongoOperations {
* @return never {@literal null}.
* @since 2.1
*/
default <T> List<T> findDistinct(String field, Class<?> entityClass, Class<T> resultClass) {
default <R> List<R> findDistinct(String field, Class<?> entityClass, Class<R> resultClass) {
return findDistinct(new Query(), field, entityClass, resultClass);
}
default <R, E> List<R> findDistinct(TypedPropertyPath<E, ?> path) {
return findDistinct(new Query(), path.toDotPath(), path.getOwningType().getType(), (Class<R>) path.getType());
}
/**
* Finds the distinct values for a specified {@literal field} across a single {@link MongoCollection} or view and
* returns the results in a {@link List}.
@ -946,7 +951,11 @@ public interface MongoOperations extends FluentMongoOperations { @@ -946,7 +951,11 @@ public interface MongoOperations extends FluentMongoOperations {
* @return never {@literal null}.
* @since 2.1
*/
<T> List<T> findDistinct(Query query, String field, Class<?> entityClass, Class<T> resultClass);
<R> List<R> findDistinct(Query query, String field, Class<?> entityClass, Class<R> resultClass);
default <R, E> List<R> findDistinct(Query query, TypedPropertyPath<E, R> path){
return findDistinct(query, path.toDotPath(), path.getOwningType().getType(), (Class<R>) path.getType());
}
/**
* Finds the distinct values for a specified {@literal field} across a single {@link MongoCollection} or view and
@ -960,8 +969,12 @@ public interface MongoOperations extends FluentMongoOperations { @@ -960,8 +969,12 @@ public interface MongoOperations extends FluentMongoOperations {
* @return never {@literal null}.
* @since 2.1
*/
<T> List<T> findDistinct(Query query, String field, String collectionName, Class<?> entityClass,
Class<T> resultClass);
<R> List<R> findDistinct(Query query, String field, String collectionName, Class<?> entityClass,
Class<R> resultClass);
default <R, E> List<R> findDistinct(Query query, TypedPropertyPath<E, R> path, String collectionName){
return findDistinct(query, path.toDotPath(), collectionName, path.getOwningType().getType(), (Class<R>)path.getType());
}
/**
* Finds the distinct values for a specified {@literal field} across a single {@link MongoCollection} or view and

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

@ -35,6 +35,8 @@ import org.bson.Document; @@ -35,6 +35,8 @@ import org.bson.Document;
import org.bson.types.Binary;
import org.jspecify.annotations.Nullable;
import org.springframework.data.core.PropertyReference;
import org.springframework.data.core.TypedPropertyPath;
import org.springframework.data.domain.Example;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Point;
@ -91,8 +93,13 @@ public class Criteria implements CriteriaDefinition { @@ -91,8 +93,13 @@ public class Criteria implements CriteriaDefinition {
this.key = key;
}
public Criteria(TypedPropertyPath<?,?> propertyReference) {
this(propertyReference.toDotPath());
}
protected Criteria(List<Criteria> criteriaChain, String key) {
this.criteriaChain = criteriaChain;
this.criteriaChain = new ArrayList<>(criteriaChain);
this.criteriaChain.add(this);
this.key = key;
}
@ -107,6 +114,10 @@ public class Criteria implements CriteriaDefinition { @@ -107,6 +114,10 @@ public class Criteria implements CriteriaDefinition {
return new Criteria(key);
}
public static Criteria where(TypedPropertyPath<?,?> propertyReference) {
return where(propertyReference.toDotPath());
}
/**
* Static factory method to create a {@link Criteria} matching an example object.
*
@ -191,6 +202,16 @@ public class Criteria implements CriteriaDefinition { @@ -191,6 +202,16 @@ public class Criteria implements CriteriaDefinition {
return new Criteria(this.criteriaChain, key);
}
/**
* Static factory method to create a Criteria using the provided key
*
* @return new instance of {@link Criteria}.
*/
@Contract("_ -> new")
public Criteria and(PropertyReference<?,?> propertyReference) {
return and(propertyReference.getName());
}
/**
* Creates a criterion using equality
*

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

@ -105,12 +105,14 @@ class CriteriaUnitTests { @@ -105,12 +105,14 @@ class CriteriaUnitTests {
@Test
void testChainedCriteria() {
Criteria c = new Criteria("name").is("Bubba").and("age").lt(21);
assertThat(c.getCriteriaObject()).isEqualTo("{ \"name\" : \"Bubba\" , \"age\" : { \"$lt\" : 21}}");
}
@Test
void testCriteriaWithMultipleConditionsForSameKey() {
Criteria c = new Criteria("name").gte("M").and("name").ne("A");
assertThatExceptionOfType(InvalidMongoDbApiUsageException.class).isThrownBy(c::getCriteriaObject);
@ -458,12 +460,17 @@ class CriteriaUnitTests { @@ -458,12 +460,17 @@ class CriteriaUnitTests {
}
@Test // GH-3414
void shouldEqualForSamePatternAndFlags() {
void shouldEqualOnlyForSamePatternAndFlags() {
Criteria left = new Criteria("field").regex("foo", "iu");
Criteria right = new Criteria("field").regex("foo");
Criteria same = new Criteria("field").regex("foo", "iu");
assertThat(left).isNotEqualTo(right);
Criteria noOption = new Criteria("field").regex("foo");
Criteria differentRegex = new Criteria("field").regex("fox", "iu");
assertThat(left).isNotEqualTo(noOption);
assertThat(left).isNotEqualTo(differentRegex);
assertThat(left).isEqualTo(same);
}
@Test // GH-3414
@ -476,4 +483,31 @@ class CriteriaUnitTests { @@ -476,4 +483,31 @@ class CriteriaUnitTests {
assertThat(left).isEqualTo(right);
}
@Test // GH-5135
void equalsConsidersPartialCriteria() {
Criteria criteria = new Criteria("alpha").is("a");
Criteria partialCriteria = new Criteria("alpha");
assertThat(criteria).isNotEqualTo(partialCriteria);
}
@Test // GH-5135
void equalsConsidersPartialCriteriaChain() {
Criteria criteria = new Criteria("alpha").is("a").and("beta").is("b");
Criteria partialCriteria = new Criteria("alpha").is("a").and("beta");
assertThat(criteria).isNotEqualTo(partialCriteria);
}
@Test // GH-5135
void criteriaIsImmutable() {
Criteria base = new Criteria("alpha").is("a");
Criteria mutated = base.and("beta");
assertThat(base).isNotEqualTo(mutated);
}
}

50
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaWithPropertyReferenceUnitTests.java

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
package org.springframework.data.mongodb.core.query;
import static org.assertj.core.api.Assertions.*;
import java.util.List;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.FieldSource;
import org.springframework.data.core.TypedPropertyPath;
class CriteriaWithPropertyReferenceUnitTests {
static Criteria base = new Criteria("name").is("Bubba");
static List<Fixture> compare = List.of( //
new Fixture( //
"constructor", //
Criteria.where((TestEntity e) -> e.name), //
new Criteria("name") //
), //
new Fixture( //
"path", //
Criteria.where(TypedPropertyPath.ofReference((TestEntity e) -> e.referenced).then(r -> r.value)), //
new Criteria("referenced.value") //
), //
new Fixture( //
"where", //
Criteria.where((TestEntity e) -> e.name), //
new Criteria("name") //
), //
new Fixture( //
"and", //
base.and((TestEntity e) -> e.age), //
base.and("age") //
) //
);
@ParameterizedTest
@FieldSource
void compare(Fixture fixture) {
assertThat(fixture.underTest).describedAs(fixture.description).isEqualTo(fixture.expected);
}
record Fixture(String description, Criteria underTest, Criteria expected) {
}
record TestEntity(String name, Long age, Referenced referenced) {
}
record Referenced(String value) {}
}
Loading…
Cancel
Save