spring data mongo @Field 失效问题
问题
@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(上面的 uid
、 favoriteStickers.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<?>)