专业编程基础技术教程

网站首页 > 基础教程 正文

关于Spring中MongoTemplate的一个奇异bug

ccvgpt 2024-10-29 13:19:52 基础教程 7 ℃

昨天在完成公司一个项目的时候用了mongoTemplate的aggregate,在使用Aggretaion.match(criteria)来筛选数据,其中criteria语句是Criteria.where("id").ne(xxxId),结果程序在执行的时候该条件一直没有起效果,但是其他的find和update等语句都是可以执行的,抱着满脑袋的疑惑翻看了它的源码实现后发现这里有一个很大的坑,具体是这个样子的:

在其他语句中,criteria查询条件最终都会包到Query对象里面,而template驱动在对Query进行解析的时候,以updateFirst为例,它的解析过程是这个样子的:

关于Spring中MongoTemplate的一个奇异bug

public WriteResult updateFirst(Query query, Update update, Class<?> entityClass, String collectionName) {

首先经过updateFirst方法,然后调用doUpdate:

protected WriteResult doUpdate(final String collectionName, final Query query, final Update update,

在这一步中,它对query的解析是这句:

DBObject queryObj = query == null ? new BasicDBObject() : queryMapper.getMappedObject(query.getQueryObject(),

我们跟入getMappedObject方法中,它的实现是:

public DBObject getMappedObject(DBObject query, MongoPersistentEntity<?> entity) {

在一个个地翻看每一条语句的源码之后,发现其对key进行解析的时候,getMappedObjectForfield方法负责对每一个约束key和查询值进行一一对应转换,具体实现是:

protected Entry<String, Object> getMappedObjectForField(Field field, Object rawValue) {

到了这儿的时候,其中一个条件引起了我的注意,就是field.isIdField,难道是这里对id进行了转换?

进一步跟进之后发现:

public boolean isIdField() {
private static final String ID_KEY = "_id";

原来其在此处对_id进行了特殊处理,既然有做特殊处理,那就得看看是怎么特殊处理的了,于是进一步跟进getMappedKeyword方法,发现其中没有进一步特殊处理,于是返回上一个方法,从第一个方法跟进,打开getMappedKey:

public String getMappedKey() {

原来在这里进行了特殊处理,随后进行了进一步查看之后发现template在Aggregation.match中没有对此进行转换,结果导致mongo查询条件一直没有正常工作,没办法,只能自行处理了,于是查询条件改为Criteria.where("_id").ne(new ObjectId(xxxId)),至此搞定。这个坑埋得有点深啊。

最近发表
标签列表