Apex代码优化01 - 避免Too many SOQL queries: 101

情景介绍:在项目的demo期,为了快速完成任务,有时候难免在项目上写出一些性能极差的代码,比如hard code(没有遵循可配置化的思想实施),再比如在for循环里面做查询。本节我们将针对在for循环里面做查询这个主题做优化分享。

Q1:什么是query 101错误?

A:通俗的讲,就是查询次数太多超出了API限制。

Q2:有代码实例来再现这个问题吗?

A:以促销为例展开说明。

描述:假设我们有一个促销,促销指对某一类产品,我们设置一个促销规则,然后推送给需要care的用户。这时,我们设计了促销,促销详细,促销产品这三个master-detail的关系对象。其中促销对象用来记录促销起止日期,促销的DM单,促销的状态和发布情况;促销详细记录某类产品的促销最小数量,折扣;促销产品是根据促销详细中产品类型过滤出来的产品中选择的具体产品项。

目标:为了避免选择的促销详细重复,我们需要在促销详细新建时提示已重复的促销详细所选的产品类型 - 用Trigger实现。

优化前的Code展示:

public class ACC_PromotionDetailTriggerHandler extends ACC_TriggerHandler {
    public override void beforeInsert() {
    	for(ACC_Promotion_Detail__c pd : (List<ACC_Promotion_Detail__c>)Trigger.New) {
    		Set<String> productTypeSet = new Set<String>();
    		List<ACC_Promotion_Detail__c> pdList = new List<ACC_Promotion_Detail__c>();
    		pdList = [SELECT ACC_Product_Group__c, ACC_Product_Subgroup__c FROM ACC_Promotion_Detail__c WHERE ACC_Promotion__c = :pd.ACC_Promotion__c];
			for(ACC_Promotion_Detail__c pd1 : pdList) {
				productTypeSet.add(pd1.ACC_Product_Group__c + pd1.ACC_Product_Subgroup__c);
			}
    		if(productTypeSet.size() > 0 && String.isNotBlank(pd.ACC_Product_Group__c) && String.isNotBlank(pd.ACC_Product_Subgroup__c)) {
    			String productType = pd.ACC_Product_Group__c + pd.ACC_Product_Subgroup__c;
    			if(productTypeSet.contains(productType)) {
    				pd.addError(Label.ACC_Promotion_Detail_Validation_Not_Duplicated);
    			}
    		}

    	}
    } 
}


分析:我们可以看出上述代码有两层遍历,之间加了一个select查询,如果数据量大的话,就可能出现query 101异常。

优化后的Code展示:

public class ACC_PromotionDetailTriggerHandler extends ACC_TriggerHandler {
    public override void beforeInsert() {
        Set<Id> promotionIdSet = new Set<Id>();
        for(ACC_Promotion_Detail__c pd : ((List<ACC_Promotion_Detail__c>)Trigger.New)) {
            promotionIdSet.add(pd.ACC_Promotion__c);
        }
        if(promotionIdSet.size() > 0) {
            ACC_PromotionDetailTriggerFunction.duplicatePDIValidation(promotionIdSet, Trigger.New);
        }
    }
}

public class ACC_PromotionDetailTriggerFunction {
    public static void duplicatePDIValidation(Set<Id> promotionIdSet, List<ACC_Promotion_Detail__c> pdList) {
    	Map<String, ACC_Promotion_Detail__c> productType2PDMap = new Map<String, ACC_Promotion_Detail__c>();
    	List<ACC_Promotion_Detail__c> promotionPDList = [SELECT ACC_Promotion__c, ACC_Product_Group__c, ACC_Product_Subgroup__c 
    													 FROM ACC_Promotion_Detail__c 
    													 WHERE ACC_Promotion__c IN :promotionIdSet];
    	System.debug('promotionPDList: ' + promotionPDList);
    	if(!promotionPDList.isEmpty()) {
    		for(ACC_Promotion_Detail__c ppd :promotionPDList) {
	    		productType2PDMap.put(ppd.ACC_Promotion__c+ppd.ACC_Product_Group__c+ppd.ACC_Product_Subgroup__c, ppd);
	    	}
	    	System.debug('productType2PDMap: ' + productType2PDMap);
    	}
    	if(productType2PDMap.size() > 0) {
    		for(ACC_Promotion_Detail__c pd :pdList) {
    			System.debug('mapValue: ' + productType2PDMap.get(pd.ACC_Promotion__c+pd.ACC_Product_Group__c+pd.ACC_Product_Subgroup__c));
	    		if(productType2PDMap.get(pd.ACC_Promotion__c+pd.ACC_Product_Group__c+pd.ACC_Product_Subgroup__c) != null) {
	    			pd.addError(Label.ACC_Promotion_Detail_Validation_Not_Duplicated);
	    		}
	    	}
    	}
    }
}

总结:优化后的代码,实现了代码分层,避免了for循环里面做查询。




相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页