have uncommitted work pending. Please commit or ro

2019-07-12 03:21发布

问题:

i have a batch class

 public class BatchCreateGCalendars implements Database.Batchable<SObject>, Database.Stateful, Database.AllowsCallouts {

        private String query;
        private String pageToken ;
        private String accessToken;
        private String CalendarId;

        public BatchCreateGCalendars(){

            this.query = 'Select Id, Name, CalendarId__c from CalendarSettings__c'; // Query to get the CalendardID (Google ID)

        }

        public Database.Querylocator start(Database.BatchableContext BC){

            return Database.getQueryLocator(query);

        }

        public void execute(Database.BatchableContext BC, List<sObject> scope){

            GoogleForce__c gApp           = GoogleForce__c.getAll().values()[0];        
            GCalendarUtil.Calendar cal    = new GCalendarUtil.Calendar();
            GCalendarUtil.GResponse gResp = new GCalendarUtil.GResponse();  


            String endPoint = GCalendarUtil.CALENDAR_BASE + GCalendarUtil.CAL_URL; // Calendar Endpoint

            // Iterate over the records, delete each calendar and create the calendar again.

            for(CalendarSettings__c c : (List<CalendarSettings__c>)scope){



                String delEndpoint = endpoint + '/' + c.CalendarId__c;

                if(gApp.ExpiresIn__c < system.now()){
                    gResp               = GCalendarUtil.getNewToken(gApp);
                    accessToken         = gResp.access_token;
                    gApp.AccessToken__c = gResp.access_token;
                    gApp.ExpiresIn__c   = System.now().addSeconds(gResp.expires_in);

                }else{
                    accessToken = gApp.AccessToken__c;
                    System.debug('Calendar Id  is '+ c.CalendarId__c);
                }
              String re=  GCalendarUtil.doApiCall(null,'GET','https://www.googleapis.com/calendar/v3/calendars/'+c.CalendarId__c+'/events',accessToken);

            re = re.replaceAll('"end":','"end1":');
    re = re.replaceAll('"dateTime":','"dateTime1":');  
              System.debug('response is' +re);
               JSON2Apex1 aa = JSON2Apex1.parse(re);

               List<JSON2Apex1.Items> ii = aa.items ;
                        System.debug('next token is'+ aa.nextPageToken);
               List<String> event_id =new List<String>();
               if(ii!= null){
               for(JSON2Apex1.Items i: ii){
               event_id.add(i.id);
               }
               }
           for(String s:event_id)
           {GCalendarUtil.doApiCall(null,'DELETE','https://www.googleapis.com/calendar/v3/calendars/'+c.CalendarId__c+'/events/'+s,accessToken);

           }
       pageToken = aa.nextPageToken;
       CalendarId=c.CalendarId__c;

               if(pageToken!=null)
               deleteEvents(accessToken , pageToken,c.CalendarId__c);

            }

            update gApp;
        }

        /*
            After the batch job is finished, trigger the other batch jobs where the Campaigns are sent as Events to the calendars. 
            Use the CalendarQuery field on the each calendarSettings record.
        */

        public void finish(Database.BatchableContext BC){   

        BatchDeleteEvents bjob1 = new BatchDeleteEvents(CalendarId,accessToken);
                Database.executeBatch(bjob1,9); 


            for(CalendarSettings__c c  : [Select Id, Name, CalendarQuery__c, CalendarId__c,FieldToDisplay__c from CalendarSettings__c WHERE Name IN ('Public Calendar', 'Internal marketing Calendar')]){

                BatchPublicCampaignsToGoogle bjob = new BatchPublicCampaignsToGoogle(c.CalendarQuery__c,c.CalendarId__c,c.FieldToDisplay__c);
                Database.executeBatch(bjob,9); // This is set to process 9 records, allowing 1 extra callout for refresh token in case needed.

            }


        }

        public static void deleteEvents(String accessToken,String pageToken,String CalendarId){
         List<Event__c> event_id =new List<Event__c>();

        while(pageToken != null)
    {   String re = GCalendarUtil.doApiCall(null,'GET','https://www.googleapis.com/calendar/v3/calendars/'+CalendarId+'/events?pageToken='+pageToken,accessToken);
                    System.debug('next page response is'+ re);
                     re = re.replaceAll('"end":','"end1":');
    re = re.replaceAll('"dateTime":','"dateTime1":');  
      JSON2Apex1 aa = JSON2Apex1.parse(re);
       List<JSON2Apex1.Items> ii = aa.items ;
      System.debug('size of ii'+ii.size());
      pageToken = aa.nextPageToken ;

               if(ii!= null){
               for(JSON2Apex1.Items i: ii){
               event_id.add(new Event__c(name = i.id));
               }
               }



     }   
     insert event_id;


        }

    }

in this code i am getting error at this line

String re=  GCalendarUtil.doApiCall(null,'GET','https://www.googleapis.com/calendar/v3/calendars/'+c.CalendarId__c+'/events',accessToken);

error is

You have uncommitted work pending. Please commit or rollback before calling out

why i am facing this error please help and one more doubt is when i call this code in finish method

 BatchDeleteEvents bjob1 = new BatchDeleteEvents(CalendarId,accessToken);
                    Database.executeBatch(bjob1,9); 

it will execute this code synchronously na means all objects in batch of 9 processed and then control will come on this code

BatchPublicCampaignsToGoogle bjob = new BatchPublicCampaignsToGoogle(c.CalendarQuery__c,c.CalendarId__c,c.FieldToDisplay__c);
                    Database.executeBatch(bjob,9);

回答1:

you can't make Callouts in Salesforce/Apex along with DML statements.

You could first perform CallOut based on the Callout Status you can invoke DML Statments.