如何在Salesforce Apex中手动创建事务以规避DML限制?
解决方案:用Queueable Apex替代@Future处理独立事务
Salesforce不允许从@Future方法中调用另一个@Future方法,但Queueable Apex支持从@Future方法中调用,且每个Queueable任务会在独立事务中执行,刚好能解决DML语句超限的问题。
1. 把数据处理类改成Queueable
将原来的ProcessClass修改为实现Queueable接口的类,让每条数据的处理都在单独事务中运行:
public class ProcessQueueable implements Queueable { private String data; // 构造方法传入需要处理的数据 public ProcessQueueable(String data) { this.data = data; } public void execute(QueueableContext context) { // 保留原有的处理逻辑:先插入父对象,再插入子对象 // 每个Queueable的execute方法是独立事务,DML计数不会和其他任务累计 Parent__c parent = new Parent__c(Name = '外部数据父记录'); insert parent; Child__c child = new Child__c(Name = '子记录', Parent__c = parent.Id); insert child; // 其他需要的DML操作... } }
2. 修改Client类,提交Queueable任务
在Client的@Future方法中,遍历从外部WSDL获取的每条数据,创建ProcessQueueable实例并提交到异步队列:
public class Client { @future(callout = true) public static void call() { // 调用外部WSDL获取响应数据列表 List<String> responseDataList = fetchExternalData(); // 替换为实际获取数据的逻辑 // 为每条数据单独提交一个Queueable任务 for(String singleData : responseDataList) { System.enqueueJob(new ProcessQueueable(singleData)); } } // 模拟获取外部数据的方法,实际替换为你的WSDL调用逻辑 private static List<String> fetchExternalData() { return new List<String>{'数据1', '数据2', '数据3'}; } }
3. 调度类保持不变
原调度类无需修改,继续调用Client.call()即可:
global class HourlySchedule implements Schedulable { global void execute(SchedulableContext SC) { Client.call(); } }
注意点
- 每个Queueable任务的
execute方法在独立事务中运行,所以每个事务内的DML语句计数是独立的,不会触发「Too Many DML statements」错误。 - Queueable Apex支持从@Future方法中调用,完美规避了「无法从Future方法中调用Future方法」的限制。
- 如果数据量极大(比如上万条),可以先将外部数据存入中间对象,再用Batch Apex处理,但几百条数据直接提交Queueable完全可行。
内容的提问来源于stack exchange,提问作者DALJIT SINGH
相关产品推荐
相关产品推荐

