如何在Java中创建SqlQuerySpec实现Cosmos DB多ID查询
解决Azure Cosmos DB SQL API WHERE IN查询返回空的问题
我一眼就看出问题所在了——你用的是azure-documentdb 2.4.7这个旧版本SDK,它不支持直接将List集合作为IN子句的参数值。当你把List<String> ids传入SqlParameter时,SDK并没有把它解析成IN期望的多个离散值,而是把整个List当成了单个参数处理,自然匹配不到数据库里的id="1"文档。
下面给你两种正确的实现方式,优先推荐第一种(安全防注入):
方法一:动态生成参数与查询语句(推荐)
这种方式会为每个ID单独创建参数,既符合SDK的参数绑定规则,又能避免SQL注入风险:
List<String> ids = Lists.newArrayList("1"); // 1. 构建参数占位符和参数集合 SqlParameterCollection parameters = new SqlParameterCollection(); StringBuilder placeholders = new StringBuilder(); for (int i = 0; i < ids.size(); i++) { String paramName = String.format("@id%d", i); placeholders.append(paramName); if (i < ids.size() - 1) { placeholders.append(", "); } parameters.add(new SqlParameter(paramName, ids.get(i))); } // 2. 构建完整的SQL查询语句 String sql = String.format("SELECT * FROM MyLog c WHERE c.id IN (%s)", placeholders.toString()); SqlQuerySpec spec = new SqlQuerySpec(sql, parameters); // 3. 执行查询 FeedResponse<Document> documentFeedResponse = documentClient.queryDocuments(collectionLink, spec, queryOptions); List<Document> documents = documentFeedResponse.getQueryIterable().toList();
方法二:直接拼接SQL语句(不推荐,有注入风险)
如果你的ID列表是完全可信的(比如内部生成,没有用户输入),也可以直接拼接SQL字符串,但这种方式存在SQL注入风险,谨慎使用:
List<String> ids = Lists.newArrayList("1"); // 把ID转成带引号的字符串,比如"'1', '2'" String quotedIds = ids.stream().map(id -> "'" + id + "'").collect(Collectors.joining(", ")); String sql = String.format("SELECT * FROM MyLog c WHERE c.id IN (%s)", quotedIds); SqlQuerySpec spec = new SqlQuerySpec(sql); FeedResponse<Document> documentFeedResponse = documentClient.queryDocuments(collectionLink, spec, queryOptions); List<Document> documents = documentFeedResponse.getQueryIterable().toList();
为什么门户里的查询能正常工作?因为你在门户里直接写了离散的字符串值IN ("1"),而SDK旧版本不支持集合参数绑定,所以必须用上面的方式来适配。
内容的提问来源于stack exchange,提问作者fascynacja
相关产品推荐
相关产品推荐

