From 018fe623c0d62b8c7af725e24e23a5ba05937ed4 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 23 May 2022 14:07:54 +0200 Subject: [PATCH] Improve exception message when deriving collection name from type. We now provide a better worded exception message when trying to derive the collection name for a type that is not considered a user types (such as org.bson.Document). Update the Javadoc to hint to the error. Closes #4061 Original pull request: #4062. --- .../data/mongodb/core/EntityOperations.java | 6 ++- .../data/mongodb/core/MongoOperations.java | 37 +++++++++++++++-- .../mongodb/core/ReactiveMongoOperations.java | 41 ++++++++++++++++++- 3 files changed, 79 insertions(+), 5 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java index 02186505a..0da27dc20 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/EntityOperations.java @@ -138,7 +138,11 @@ class EntityOperations { "No class parameter provided, entity collection can't be determined!"); } - return context.getRequiredPersistentEntity(entityClass).getCollection(); + MongoPersistentEntity persistentEntity = context.getPersistentEntity(entityClass); + if(persistentEntity == null) { + throw new MappingException(String.format("Collection name cannot be derived for type %s. Is it a store native type?", entityClass)); + } + return persistentEntity.getCollection(); } public Query getByIdInQuery(Collection entities) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java index 5aa554771..f56aaea6f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java @@ -80,6 +80,7 @@ public interface MongoOperations extends FluentMongoOperations { * * @param entityClass must not be {@literal null}. * @return never {@literal null}. + * @throws org.springframework.data.mapping.MappingException if the collection name cannot be derived from the type. */ String getCollectionName(Class entityClass); @@ -968,6 +969,8 @@ public interface MongoOperations extends FluentMongoOperations { * fields specification. Must not be {@literal null}. * @param replacement the replacement document. Must not be {@literal null}. * @return the converted object that was updated or {@literal null}, if not found. + * @throws org.springframework.data.mapping.MappingException if the collection name cannot be + * {@link #getCollectionName(Class) derived} from the given replacement value. * @since 2.1 */ @Nullable @@ -1009,6 +1012,8 @@ public interface MongoOperations extends FluentMongoOperations { * @return the converted object that was updated or {@literal null}, if not found. Depending on the value of * {@link FindAndReplaceOptions#isReturnNew()} this will either be the object as it was before the update or * as it is after the update. + * @throws org.springframework.data.mapping.MappingException if the collection name cannot be + * {@link #getCollectionName(Class) derived} from the given replacement value. * @since 2.1 */ @Nullable @@ -1082,6 +1087,8 @@ public interface MongoOperations extends FluentMongoOperations { * @return the converted object that was updated or {@literal null}, if not found. Depending on the value of * {@link FindAndReplaceOptions#isReturnNew()} this will either be the object as it was before the update or * as it is after the update. + * @throws org.springframework.data.mapping.MappingException if the collection name cannot be + * {@link #getCollectionName(Class) derived} from the given replacement value. * @since 2.1 */ @Nullable @@ -1171,6 +1178,8 @@ public interface MongoOperations extends FluentMongoOperations { * {@literal null}. * @param entityClass class that determines the collection to use. Must not be {@literal null}. * @return the count of matching documents. + * @throws org.springframework.data.mapping.MappingException if the collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. */ long count(Query query, Class entityClass); @@ -1205,6 +1214,8 @@ public interface MongoOperations extends FluentMongoOperations { * * @param entityClass must not be {@literal null}. * @return the estimated number of documents. + * @throws org.springframework.data.mapping.MappingException if the collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. * @since 3.1 */ default long estimatedCount(Class entityClass) { @@ -1265,6 +1276,8 @@ public interface MongoOperations extends FluentMongoOperations { * @param objectToSave the object to store in the collection. Must not be {@literal null}. * @return the inserted object. * @throws IllegalArgumentException in case the {@code objectToSave} is collection-like. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given object type. */ T insert(T objectToSave); @@ -1291,6 +1304,8 @@ public interface MongoOperations extends FluentMongoOperations { * @param batchToSave the batch of objects to save. Must not be {@literal null}. * @param entityClass class that determines the collection to use. Must not be {@literal null}. * @return the inserted objects that. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. */ Collection insert(Collection batchToSave, Class entityClass); @@ -1309,6 +1324,8 @@ public interface MongoOperations extends FluentMongoOperations { * * @param objectsToSave the list of objects to save. Must not be {@literal null}. * @return the inserted objects. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} for the given objects. */ Collection insertAll(Collection objectsToSave); @@ -1330,6 +1347,8 @@ public interface MongoOperations extends FluentMongoOperations { * @param objectToSave the object to store in the collection. Must not be {@literal null}. * @return the saved object. * @throws IllegalArgumentException in case the {@code objectToSave} is collection-like. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given object type. */ T save(T objectToSave); @@ -1366,9 +1385,11 @@ public interface MongoOperations extends FluentMongoOperations { * the existing object. Must not be {@literal null}. * @param entityClass class that determines the collection to use. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 3.0 * @see Update * @see AggregationUpdate + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. + * @since 3.0 */ UpdateResult upsert(Query query, UpdateDefinition update, Class entityClass); @@ -1420,9 +1441,11 @@ public interface MongoOperations extends FluentMongoOperations { * the existing. Must not be {@literal null}. * @param entityClass class that determines the collection to use. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 3.0 * @see Update * @see AggregationUpdate + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. + * @since 3.0 */ UpdateResult updateFirst(Query query, UpdateDefinition update, Class entityClass); @@ -1474,9 +1497,11 @@ public interface MongoOperations extends FluentMongoOperations { * the existing. Must not be {@literal null}. * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @since 3.0 + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. * @see Update * @see AggregationUpdate + * @since 3.0 */ UpdateResult updateMulti(Query query, UpdateDefinition update, Class entityClass); @@ -1524,6 +1549,8 @@ public interface MongoOperations extends FluentMongoOperations { * * @param object must not be {@literal null}. * @return the {@link DeleteResult} which lets you access the results of the previous delete. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given object type. */ DeleteResult remove(Object object); @@ -1547,6 +1574,8 @@ public interface MongoOperations extends FluentMongoOperations { * @param entityClass class that determines the collection to use. * @return the {@link DeleteResult} which lets you access the results of the previous delete. * @throws IllegalArgumentException when {@literal query} or {@literal entityClass} is {@literal null}. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. */ DeleteResult remove(Query query, Class entityClass); @@ -1594,6 +1623,8 @@ public interface MongoOperations extends FluentMongoOperations { * @param query the query document that specifies the criteria used to find and remove documents. * @param entityClass class of the pojo to be operated on. * @return the {@link List} converted objects deleted by this operation. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. * @since 1.5 */ List findAllAndRemove(Query query, Class entityClass); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java index 72a7253a7..ed319a088 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java @@ -756,6 +756,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * fields specification. Must not be {@literal null}. * @param replacement the replacement document. Must not be {@literal null}. * @return the converted object that was updated or {@link Mono#empty()}, if not found. + * @throws org.springframework.data.mapping.MappingException if the collection name cannot be + * {@link #getCollectionName(Class) derived} from the given replacement value. * @since 2.1 */ default Mono findAndReplace(Query query, T replacement) { @@ -795,6 +797,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * @return the converted object that was updated or {@link Mono#empty()}, if not found. Depending on the value of * {@link FindAndReplaceOptions#isReturnNew()} this will either be the object as it was before the update or * as it is after the update. + * @throws org.springframework.data.mapping.MappingException if the collection name cannot be + * {@link #getCollectionName(Class) derived} from the given replacement value. * @since 2.1 */ default Mono findAndReplace(Query query, T replacement, FindAndReplaceOptions options) { @@ -865,6 +869,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * @return the converted object that was updated or {@link Mono#empty()}, if not found. Depending on the value of * {@link FindAndReplaceOptions#isReturnNew()} this will either be the object as it was before the update or * as it is after the update. + * @throws org.springframework.data.mapping.MappingException if the collection name cannot be + * {@link #getCollectionName(Class) derived} from the given replacement value. * @since 2.1 */ default Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions options, Class entityType, @@ -951,6 +957,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * {@literal null}. * @param entityClass class that determines the collection to use. Must not be {@literal null}. * @return the count of matching documents. + * @throws org.springframework.data.mapping.MappingException if the collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. */ Mono count(Query query, Class entityClass); @@ -1007,6 +1015,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * * @param entityClass must not be {@literal null}. * @return a {@link Mono} emitting the estimated number of documents. + * @throws org.springframework.data.mapping.MappingException if the collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. * @since 3.1 */ default Mono estimatedCount(Class entityClass) { @@ -1045,6 +1055,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * @param objectToSave the object to store in the collection. Must not be {@literal null}. * @return the inserted object. * @throws IllegalArgumentException in case the {@code objectToSave} is collection-like. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given object type. */ Mono insert(T objectToSave); @@ -1070,7 +1082,9 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * * @param batchToSave the batch of objects to save. Must not be {@literal null}. * @param entityClass class that determines the collection to use. Must not be {@literal null}. - * @return the inserted objects . + * @return the inserted objects. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. */ Flux insert(Collection batchToSave, Class entityClass); @@ -1089,6 +1103,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * * @param objectsToSave the list of objects to save. Must not be {@literal null}. * @return the saved objects. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} for the given objects. */ Flux insertAll(Collection objectsToSave); @@ -1116,6 +1132,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * @param batchToSave the publisher which provides objects to save. Must not be {@literal null}. * @param entityClass class that determines the collection to use. Must not be {@literal null}. * @return the inserted objects. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} for the type. */ Flux insertAll(Mono> batchToSave, Class entityClass); @@ -1155,6 +1173,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * @param objectToSave the object to store in the collection. Must not be {@literal null}. * @return the saved object. * @throws IllegalArgumentException in case the {@code objectToSave} is collection-like. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given object type. */ Mono save(T objectToSave); @@ -1191,6 +1211,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * * @param objectToSave the object to store in the collection. Must not be {@literal null}. * @return the saved object. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given object type. */ Mono save(Mono objectToSave); @@ -1224,6 +1246,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * the existing object. Must not be {@literal null}. * @param entityClass class that determines the collection to use. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. * @since 3.0 * @see Update * @see AggregationUpdate @@ -1278,6 +1302,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * the existing. Must not be {@literal null}. * @param entityClass class that determines the collection to use. * @return the {@link UpdateResult} which lets you access the results of the previous write. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. * @since 3.0 * @see Update * @see AggregationUpdate @@ -1333,6 +1359,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 3.0 + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. * @see Update * @see AggregationUpdate */ @@ -1379,6 +1407,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * * @param object must not be {@literal null}. * @return the {@link DeleteResult} which lets you access the results of the previous delete. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given object type. */ Mono remove(Object object); @@ -1396,6 +1426,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * * @param objectToRemove must not be {@literal null}. * @return the {@link DeleteResult} which lets you access the results of the previous delete. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given object type. */ Mono remove(Mono objectToRemove); @@ -1415,6 +1447,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * @param query the query document that specifies the criteria used to remove a record. * @param entityClass class that determines the collection to use. * @return the {@link DeleteResult} which lets you access the results of the previous delete. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. */ Mono remove(Query query, Class entityClass); @@ -1458,6 +1492,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * @param query the query document that specifies the criteria used to find and remove documents. * @param entityClass class of the pojo to be operated on. * @return the {@link Flux} converted objects deleted by this operation. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. */ Flux findAllAndRemove(Query query, Class entityClass); @@ -1489,6 +1525,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * specification. * @param entityClass the parametrized type of the returned {@link Flux}. * @return the {@link Flux} of converted objects. + * @throws org.springframework.data.mapping.MappingException if the target collection name cannot be + * {@link #getCollectionName(Class) derived} from the given type. */ Flux tail(Query query, Class entityClass); @@ -1633,6 +1671,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * * @param entityClass must not be {@literal null}. * @return never {@literal null}. + * @throws org.springframework.data.mapping.MappingException if the collection name cannot be derived from the type. * @since 2.1 */ String getCollectionName(Class entityClass);