【问题标题】:please help me to convert trigger to batch apex请帮我将触发器转换为批处理顶点
【发布时间】:2014-12-29 19:20:56
【问题描述】:

请帮助我将后触发器转换为批处理顶点。 此触发器在机会阶段更改为获胜时触发。 它遍历订单项并检查该客户是否存在预测(自定义对象)。如果存在,则链接到它们。如果不存在,它将创建一个新的预测。

我的触发器对某些记录工作正常。但是要进行大规模更新,我遇到了超时错误。所以选择批处理顶点,但我从未编写过它。请帮助我。

trigger Accountforecast on Opportunity (after insert,after update) {
    List<Acc_c> AccproductList =new List<Acc_c>();
    List<Opportunitylineitem> opplinitemlist =new List<Opportunitylineitem>();
    list<opportunitylineitem > oppdate=  new list<opportunitylineitem >();
    List<Acc__c> accquery =new List<Acc__c>();
    List<date> dt =new List<date>();
    Set<Id> sProductIds = new Set<Id>();
    Set<Id> sAccountIds = new Set<Id>();
    Set<id> saccprodfcstids =new set<Id>();
    Acc__c accpro =new Acc__c();
    string aname;
    Integer i;
    Integer myIntMonth;
    Integer myIntyear;
    Integer myIntdate;

    opplinitemlist=[select Id,PricebookEntry.Product2.Name,opp_account__c,Opp_account_name__c,PricebookEntry.Product2.id, quantity,ServiceDate,Acc_Product_Fcst__c  from Opportunitylineitem                      WHERE Opportunityid IN :Trigger.newMap.keySet() AND Acc__c=''];

    for(OpportunityLineItem oli:opplinitemlist) {
    sProductIds.add(oli.PricebookEntry.Product2.id);
    sAccountIds.add(oli.opp_account__c);
    }
    accquery=[select id,Total_Qty_Ordered__c,Last_Order_Qty__c,Last_Order_Date__c,Fcst_Days_Period__c  from Acc__c where Acc__c.product__c In :sproductids and Acc__c.Account__c in :saccountids]; 

  for(Acc__c apf1 :accquery){
    saccprodfcstids.add(apf1.id);
    }        
    if(saccprodfcstids!=null){
    oppdate=[select servicedate from opportunitylineitem where Acc__c IN :saccprodfcstids ];

    i =[select count() from  Opportunitylineitem where acc_product_fcst__c in :saccprodfcstids];
    }


     for(Opportunity opp :trigger.new)
     {
         if(opp.Stagename=='Closed Won')
         {
                 for(opportunitylineitem opplist:opplinitemlist)
                 {
                     if(!accquery.isempty())
                     {
                         for(opportunitylineitem opldt :oppdate)
                         {
                             string myDate = String.valueOf(opldt);
                             myDate = myDate.substring(myDate.indexof('ServiceDate=')+12);
                             myDate = myDate.substring(0,10);                                    
                             String[] strDate = myDate.split('-');
                             myIntMonth = integer.valueOf(strDate[1]);
                             myIntYear = integer.valueOf(strDate[0]);
                             myIntDate = integer.valueOf(strDate[2]);
                             Date d = Date.newInstance(myIntYear, myIntMonth, myIntDate);
                             dt.add(d);
                         }  
                             dt.add(opp.closedate);
                             dt.sort();                   
                             integer TDays=0;
                             system.debug('*************dt:'+dt.size());
                                 for(integer c=0;c<dt.size()-1;c++)
                                 {
                                     TDays=TDays+dt[c].daysBetween(dt[c+1]);

                                 }
                                 for(Acc_product_fcst__c apf:accquery)
                                 {
                                     apf.Fcst_Days_Period__c = TDays/i;
                                     apf.Total_Qty_Ordered__c =apf.Total_Qty_Ordered__c +opplist.quantity;
                                     apf.Last_Order_Qty__c=opplist.quantity;
                                     apf.Last_Order_Date__c=opp.CloseDate ;
                                     apf.Fcst_Qty_Avg__c=apf.Total_Qty_Ordered__c/(i+1);
                                     Opplist.Acc__c =apf.Id;  
                                 }
                                                    }

                                 else{
                                 accpro.Account__c=opplist.opp_account__c;
                                 accpro.product__c=opplist.PricebookEntry.Product2.Id;
                                 accpro.opplineitemid__c=opplist.id;
                                 accpro.Total_Qty_Ordered__c =opplist.quantity;
                                 accpro.Last_Order_Qty__c=opplist.quantity;
                                 accpro.Last_Order_Date__c=opp.CloseDate;
                                 accpro.Fcst_Qty_Avg__c=opplist.quantity;
                                 accpro.Fcst_Days_Period__c=7;
                                 accproductList.add(accpro);



                                 }
                                 }

             }
         }
         if(!accproductlist.isempty()){
         insert accproductlist;
         }
         update opplinitemlist;
         update accquery;         
     }

【问题讨论】:

  • 这是我写的,但不确定这是否有效以及如何测试。请指导我

标签: triggers salesforce apex-code apex


【解决方案1】:

首先,你应该看看这个:Apex Batch Processing

一旦您对批处理的工作原理有了更好的了解,我们需要考虑以下几点:

  1. 确定需要更多处理的对象。帐户?机会?
  2. 是否应该跨批处理调用维护数据?有状态?
  3. 在性能方面使用正确的数据结构。地图、列表?

  4. 从您的代码中,我们可以看到您拥有三个对象:OpportunityLineItems、Accounts 和 Opportunities。看来您的帐户对象在这里使用的处理最多。

  5. 看来您只是在跟踪日期而不进行任何聚合。因此,您不需要跨批处理调用维护状态。

  6. 您的代码有可能达到调控器限制,尤其是堆上的内存限制。你有一个四嵌套循环。我们的建议是在地图而不是列表中维护与机会相关的机会行项目。另外,我们可以通过如下重构代码来摆脱那些不必要的 for 循环:

注意:这只是您需要构建的批次的模板。

globalglobal Database.QueryLocator start(Database.BatchableContext BC) class AccountforecastBatch implements Database.Batchable<sObject>
{
    global Database.QueryLocator start(Database.BatchableContext BC)
    {
       // 1. Do some initialization here: (i.e. for(OpportunityLineItem oli:opplinitemlist) {sProductIds.add(oli.PricebookEntry.Product2.id)..}
       // 2. return Opportunity object here:  return Database.getQueryLocator([select id,Total_Qty_Ordered__c,Last_Order_Qty ....]);
    }

    global void execute(Database.BatchableContext BC, List<sObject> scope)
    {
       // 1. Traverse your scope which at this point will be a list of Accounts
       // 2. You're adding dates inside the process for Opportunity Line Items. See if you can isolate this process outside the for loops with a Map data structure.
       // 3. You have 3 potential database transactions here (insert accproductlist;update opplinitemlist; update accquery; ). Ideally, you will only need one DB transaction per batch.If you can complete step 2 above, you might only need to update your opportunity line items. Otherwise, you're trying to do more than one thing in a method and you will need to redesign your solution           
    }

    global void finish(Database.BatchableContext BC) 
    {
       // send email or do some other tasks here
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-13
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多