问题

@Field("fs")
public Map<String, Integer> favoriteStickers = new LinkedHashMap<>();

使用MongoTemplate直接为favoriteStickers字段添加新值key为STICKER@10002,value为1时,@Field配置的别名不会被成功映射。

mongoTemplate.upsert(query(where("uid").is(1), new Update().set("favoriteStickers.STICKER@10002", 1), UserSticker.class);

原因

MongoTemplate会将执行语句中的key(上面的 uidfavoriteStickers.STICKER@10002 )映射成MongoDB中对应的字段,如果在UserSticker类的定义中有相应的配置则会按配置映射。例如问题字段使用的@Field就是用来配置别名的。

对于favoriteStickers.12 , 会当作favoriteStickers是个数组,12为被操作的秩,favoriteStickers属性在UserSticker中有定义可以成功映射。
对于favoriteStickers.STICKER@10002,会当作是有层级关系。即当作favoriteStickers是一个对象,该对象的定义中有一个STICKER@10002属性,如果没有不做映射。favoriteStickers是一个map所以无法映射。

重要源码

org.springframework.data.mongodb.core.convert.QueryMapper#getMappedObject(org.bson.conversions.Bson, org.springframework.data.mongodb.core.mapping.MongoPersistentEntity<?>)方法就是直接用来映射对象的,在这个方法中的代码Field field = createPropertyField(entity, key, mappingContext);是用来构建字段的映射关系。

最终会指向org.springframework.data.mongodb.core.convert.QueryMapper.MetadataBackedField#getPath(java.lang.String)这个方法中出问题的就是PropertyPath path = PropertyPath.from(pathExpression.replaceAll("\\.\\d+", ""), entity.getTypeInformation());这行代码又会调用org.springframework.data.mapping.PropertyPath#from(java.lang.String, org.springframework.data.util.TypeInformation<?>)


等灯的邓
19 声望0 粉丝