美文网首页程序员
InvalidMongoDbApiUsageException之

InvalidMongoDbApiUsageException之

作者: 清无色 | 来源:发表于2020-05-15 01:12 被阅读0次

1. 异常

org.springframework.data.mongodb.InvalidMongoDbApiUsageException: Due to limitations of the com.mongodb.BasicDocument, you can't add a second 'xxx' criteria. Query already contains...

2. 出现场景

  • 显性地使用了重复的字段(key)进行查询:
Query query = new Query();
query.addCriteria(Criteria.where("name").is(name)); 
query.addCriteria(Criteria.where("name").is(name)); // 与上一行重复使用了字段:name
UserVO user = mongoTemplate.findOne(query, UserVO.class, "QWS_TEST_TABLE");

抛出异常:...you can't add a second 'name' criteria.

  • 隐性地使用了重复的字段(key)进行查询
Query query = new Query();
query.addCriteria(new Criteria().andOperator(Criteria.where("name").is(name)));
query.addCriteria(new Criteria().andOperator(Criteria.where("age").is(age))); // 与上一行重复使用了字段:null
UserVO user = mongoTemplate.findOne(query, UserVO.class, "QWS_TEST_TABLE");

抛出异常:...you can't add a second 'null' criteria,为什么是null呢?请往下看。

3. 源码分析

首先查看addCriteria()方法,第一找到抛异常的源头:

public Query addCriteria(CriteriaDefinition criteriaDefinition) {
    // 查询当前字段是否存在设置了操作条件
    CriteriaDefinition existing = (CriteriaDefinition)this.criteria.get(criteriaDefinition.getKey());
    String key = criteriaDefinition.getKey();
    if (existing == null) { // 如果不存在,那么添加当前字段的操作条件
        this.criteria.put(key, criteriaDefinition);
        return this;
    } else { // 如果已经存在,那么抛出异常
        throw new InvalidMongoDbApiUsageException(String.format("Due to limitations of the com.mongodb.BasicDocument, you can't add a second '%s' criteria. Query already contains '%s'", key, SerializationUtils.serializeToJsonSafely(existing.getCriteriaObject())));
    }
}

通过源码知道:如果某个字段(key)已经存在了条件,那么第二次去重复设置条件时,会抛出异常。回到上述问题,为什么key为null?

通过查看where()方法和Criteria的构造函数源码:

// where方法
public static Criteria where(String key) {
    return new Criteria(key);
}

// 无参构造函数
public Criteria() {
    this.isValue = NOT_SET;
    this.criteriaChain = new ArrayList();
}

// 有参构造函数
public Criteria(String key) {
    this.isValue = NOT_SET;
    this.criteriaChain = new ArrayList();
    this.criteriaChain.add(this);
    this.key = key;
}

发现Criteria.where("name").is(name)最终调用了构造函数,设置了key等于“name”;而new Criteria().andOperator(Criteria.where("name").is(name))中的new Criteria()调用了无参的构造函数,因此key为null。

4. 如何避免出现InvalidMongoDbApiUsageException

根源在于query.addCriteria(Criteria c)每次调用都会设置一个类似key=value的条件,且不能重复地使用重复的字段(key)条件,所以对于比较复杂的业务,我们只要保证addCriteria()被调用一次即可。

直接上代码:

Query query = new Query();
Criteria c1 = Criteria.where("name").is("张三");
Criteria c2 = Criteria.where("name").is("李四");
Criteria c3 = new Criteria().andOperator(Criteria.where("name").is("王五"));
Criteria c4 = new Criteria().andOperator(Criteria.where("name").is("赵六"));
query.addCriteria(new Criteria().andOperator(c1, c2, c3, c4)); // 保证只调用一次addCriteria()
UserVO user = mongoTemplate.findOne(query, UserVO.class, "QWS_TEST_TABLE");

相关文章

  • InvalidMongoDbApiUsageException之

    1. 异常 org.springframework.data.mongodb.InvalidMongoDbApiU...

  • 十之

    博学之,审问之,慎思之,明辨之,笃行之。 励志之,健身之,涅槃之,弘毅之,自强之!

  • 读记|唐诗人:诗心煎红尘(二)

    愈之挫之 险之退之 借之济之 忠之犯之 勇之夺之 衰之立之 坚之韧之 载之言之 一代宗师 成之传之 字曰子厚 道解...

  • 《寄君归》

    思之念之 见之不忘 吾亦求之 求之不得 吾亦念之 兮之盼之 来之归之 欲予离之 得之兮之 心思念之 盼来归之 归之...

  • 飘零

    艾雪儿 难耐心中怦然之 抑之,控之,思之,忘之 能否任之,弃之,拥之,念之 山河为鉴 赴之,游之,悦之,相守之…

  • 《美》

    刚之美,软之美,善之美,心之美。 水之美,声之美,爱之美,景之美,笑之美,物之美,月之美。 仁之美,慈之美,德之美...

  • 众说纷云

    众说纷云 文‖曾之一 20200220 古人说 真之假之善之恶之美之丑之 今人说 真之假之善之恶之美之丑之 后人说...

  • 安沨

    博学之,审问之,慎思之,明辨之,笃行之。

  • 2019-01-13

    博学之、明辨之、慎思之、审问之、笃行之

  • 《道德经·第五十一章》

    原文 道生之,德蓄之,物形之,势成之。 是以万物莫不尊道而贵德。 道之尊,德之贵;长之育之;亭之毒之;养之覆之。 ...

网友评论

    本文标题:InvalidMongoDbApiUsageException之

    本文链接:https://www.haomeiwen.com/subject/gyxqohtx.html