Salesforce: INVALID_QUERY_LOCATOR简析

Query locators某些情况下是由system生成的,如果在过期或发布后使用query locators,则可能会导致API integrations或Apex code抛出错误。

Query locators代表查询时服务器端的一个游标。通常,当查询中请求的并非所有记录都适合返回的数据集时,将返回query locator。这样,可以使用提供的query locator发出queryMore()以获取其他行。

例如,考虑一个query API调用,其中批量大小设置为2,000,并且该组织拥有2000+个accouts。在这种情况下,SELECT id FROM account将返回2,000条记录和一个query locator以检索剩余的记录。

每个Salesforce用户一次最多可以打开10个查询游标。这是一个硬编码的限制,不能增加。如果在客户端应用程序尝试打开一个新的游标时打开了10个query locator游标,则会释放最早的游标。如果尝试调用过期或释放的游标,则平台将返回“ INVALID_QUERY_LOCATOR”错误。为避免此错误,请确保客户端代码未保持打开状态超过10个query locator游标。如果多个进程使用同一user运行,请确保它们的组合query locator游标计数保持在10或以下。

此外,在Apex triggers或Apex controllers中,此错误消息可能在不同的情况下引发,但通常是由于将query与inner query一起使用而引起的。在这种情况下,系统可以对user透明地生成query locator,以便如果Apex code尝试检索由inner query选择的child records,则将使用queryMore()来检索它们。

例子:
List<Account> accountsAndCases= [SELECT id, name, (SELECT id, subject, description FROM Cases) FROM Account];
// Cases can be retrieved as follows:
List<Case> casesToUpdate = new List<Case>();
for(Account a : accountsAndCases) { // queryMore() will be used to retrieve child cases
casesToUpdate.addAll(a.Cases);
}

如果没有立即检索到child case,从而“消耗”了生成的query locators,则这些query locators将会
1. 15分钟后过期
2. 或被释放,因为可能需要根据自定义代码路径创建新的query locator。如果在生成query locator的点和使用它们的点之间插入了其他查询,则会发生这种情况。

注意:为避免query locators出现这个问题,应始终在生成child records的相同范围内检索child records。

要避免出现以下代码结构:
List<Account> accountsAndCases = Utilities.getAccountsAndCases();
List<Opportunity> opportunities = Utilities.getOpportunities(accountsAndCases);
Utilities.updateCases(accountsAndCases);

应该这么写:
List<Account> accounts = Utilities.getAccountsAndUpdateCases();
List<Opportunity> opportunities = Utilities.getOpportunities(accounts);

与前一种情况类似,如果在Batch Apex class的start()方法中使用了带有inner query的查询,则系统可能需要为child records生成query locators,直到batch nummber N才可以使用该child records时,它们可能已过期或由于在较早的batch中执行的其他自定义代码而被释放。

在这种情况下,请避免在Batch Apex类的start()方法中使用inner query,而只需在execute()方法中查询子记录

原文地址:https://www.cnblogs.com/clsriz/p/14030613.html