diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index b1a7b0604..af93fdd63 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -1170,7 +1170,7 @@ public class QueryMapper { if (sourceProperty != null && sourceProperty.getOwner().equals(entity)) { return mappingContext - .getPersistentPropertyPath(PropertyPath.from(sourceProperty.getName(), entity.getTypeInformation())); + .getPersistentPropertyPath(PropertyPath.from(Pattern.quote(sourceProperty.getName()), entity.getTypeInformation())); } PropertyPath path = forName(rawPath); @@ -1229,6 +1229,13 @@ public class QueryMapper { return forName(path.substring(0, path.length() - 3) + "id"); } + // Ok give it another try quoting + try { + return PropertyPath.from(Pattern.quote(path), entity.getTypeInformation()); + } catch (PropertyReferenceException | InvalidPersistentPropertyPath ex) { + + } + return null; } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 3bdd99d55..e2f69260b 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -1191,6 +1191,72 @@ public class QueryMapperUnitTests { assertThat(document).isEqualTo(new org.bson.Document("stringValue", 1)); } + @Test // GH-3601 + void resolvesFieldnameWithUnderscoresCorrectly() { + + Query query = query(where("fieldname_with_underscores").exists(true)); + + org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), + context.getPersistentEntity(WithPropertyUsingUnderscoreInName.class)); + + assertThat(document).isEqualTo(new org.bson.Document("fieldname_with_underscores", new org.bson.Document("$exists", true))); + } + + @Test // GH-3601 + void resolvesMappedFieldnameWithUnderscoresCorrectly() { + + Query query = query(where("renamed_fieldname_with_underscores").exists(true)); + + org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), + context.getPersistentEntity(WithPropertyUsingUnderscoreInName.class)); + + assertThat(document).isEqualTo(new org.bson.Document("renamed", new org.bson.Document("$exists", true))); + } + + @Test // GH-3601 + void resolvesSimpleNestedFieldnameWithUnderscoresCorrectly() { + + Query query = query(where("simple.fieldname_with_underscores").exists(true)); + + org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), + context.getPersistentEntity(WrapperAroundWithPropertyUsingUnderscoreInName.class)); + + assertThat(document).isEqualTo(new org.bson.Document("simple.fieldname_with_underscores", new org.bson.Document("$exists", true))); + } + + @Test // GH-3601 + void resolvesSimpleNestedMappedFieldnameWithUnderscoresCorrectly() { + + Query query = query(where("simple.renamed_fieldname_with_underscores").exists(true)); + + org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), + context.getPersistentEntity(WrapperAroundWithPropertyUsingUnderscoreInName.class)); + + assertThat(document).isEqualTo(new org.bson.Document("simple.renamed", new org.bson.Document("$exists", true))); + } + + @Test // GH-3601 + void resolvesFieldNameWithUnderscoreOnNestedFieldnameWithUnderscoresCorrectly() { + + Query query = query(where("double_underscore.fieldname_with_underscores").exists(true)); + + org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), + context.getPersistentEntity(WrapperAroundWithPropertyUsingUnderscoreInName.class)); + + assertThat(document).isEqualTo(new org.bson.Document("double_underscore.fieldname_with_underscores", new org.bson.Document("$exists", true))); + } + + @Test // GH-3601 + void resolvesFieldNameWithUnderscoreOnNestedMappedFieldnameWithUnderscoresCorrectly() { + + Query query = query(where("double_underscore.renamed_fieldname_with_underscores").exists(true)); + + org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), + context.getPersistentEntity(WrapperAroundWithPropertyUsingUnderscoreInName.class)); + + assertThat(document).isEqualTo(new org.bson.Document("double_underscore.renamed", new org.bson.Document("$exists", true))); + } + class WithDeepArrayNesting { List level0; @@ -1408,4 +1474,17 @@ public class QueryMapperUnitTests { String transientValue; } + static class WrapperAroundWithPropertyUsingUnderscoreInName { + + WithPropertyUsingUnderscoreInName simple; + WithPropertyUsingUnderscoreInName double_underscore; + } + + static class WithPropertyUsingUnderscoreInName { + + String fieldname_with_underscores; + + @Field("renamed") + String renamed_fieldname_with_underscores; + } }