刚接触 salesforce 和 Apex,我收到了一项家庭任务,要求在插入后对案例创建 20000 个案例评论。 caseComments 和 Case 是不同的对象,但它们是关联的。我以为这会很简单,但当达到每笔交易 10k 的 DML 限制时,问题就开始了。
我尝试更改批处理中的内部和外部循环,但没有任何效果,我可以创建 9800 个新的 CaseComments,如果我无法将循环值增加 1,因为它将超过限制。
触发点:
trigger CommentsOnCaseInsert on Case (after insert) {
System.debug('Triggered');
if (Trigger.isAfter && Trigger.isInsert && Trigger.new.size() == 1) {
CreateCaseCommentsBatch batch = new CreateCaseCommentsBatch(Trigger.new[0].Id);
Database.executeBatch(batch);
}
}
批处理作业:
public class CreateCaseCommentsBatch implements Database.Batchable<SObject> {
private Id caseId;
public CreateCaseCommentsBatch(Id caseId) {
this.caseId = caseId;
}
public Database.QueryLocator start(Database.BatchableContext context) {
return Database.getQueryLocator([SELECT Id FROM Case WHERE Id = :caseId]);
}
// Execute method to create case comments
public void execute(Database.BatchableContext context, List<Case> scope) {
List<CaseComment> caseCommentsToInsert = new List<CaseComment>();
for (Integer i = 0; i < 150; i++) {
for (Integer j = 0; j < 66; j++) {
Integer commentNumber = i * 66 + j + 1;
CaseComment caseComment = new CaseComment(
ParentId = caseId,
CommentBody = 'Dummy Comment ' + commentNumber + ' - Of Case: ' + caseId
);
caseCommentsToInsert.add(caseComment);
}
insert caseCommentsToInsert;
caseCommentsToInsert.clear();
}
}
// Finish method `your text`
public void finish(Database.BatchableContext context) {
}
}
你所拥有的将不起作用,因为你的批处理作业仍然只会调用
execute()
一次。它将把上下文从主案例触发器中分离出来,并带有一组新的限制——但仍然只有一个。因此同样适用 10K DML。
您可以通过在
start()
、execute()
和 finish()
中插入 6666 来作弊。有点弱,扩展解决方案,但是嘿。
您可以研究以菊花链方式连接批次(在
Database.executeBatch()
内调用 finish()
)。如果你将它与像 5K did 这样传递的一些计数器变量配对,则执行下一个块,它可以很好地工作。如果您认为需要这样的计数器,也许可以阅读有关 Database.Stateful
的内容。
另一个选项是
Queueable
,适合类似的“我们到了吗”工作。
最后但并非最不重要的一点是,可以选择使用“Iterable”调用批处理(
start()
方法返回不必来自数据库的事物列表,可以完全在内存中创建......那就太好了因为它会一次调用多个execute() 200 或其他...但我不知道如果您要在内存中创建 20K 案例注释并将执行降级为仅插入它们,那么您的内存使用情况会如何。