Sfdcバッチ実装のポイント

# 要件
ある営業リストは論理上法人番号より、取引先と結び付けられる。毎日営業情報は別システムから連携され、バッチで最新データに取引先Idを付与する

# 分析
・取引先と営業リストのデータ量は５００万件を超えるので、実行効率を考えるが必要です。
　営業リストの更新日が指定日以内データだけを更新対象にする
・バッチサイズはディフォルトが２００件ですが、指定できるようにする
・利用されるデータ
　取引先のID、法人番号(Unique)
　営業店舗リストの法人番号、最新更新日時
　更新対象：営業リストの取引先ID　←　取引先のID
　条件：　取引先の法人番号　＝　営業リストの法人番号
　　　　　営業店舗リストの最新更新日　＞　指定日
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/1415cb9e-b0f8-f276-61a5-830583f5065e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/ceab3ae4-1fa9-986f-3853-ea09e6d03d59.png)


# 実装
①　Start
　毎回２００件の取引先を取得し、Executeに渡す
②　Execute
　②-1 渡された取引の法人番号とIdのマップを作成し、法人番号のリストも作成する
　②-2 営業リストの法人番号分かつ指定日以内のリストを取得する
　②-3 更新要の営業リストを選択し、取引先IDを付与し、更新リストに追加する
　②-4 更新リストをUpdateする
## ソース
```

global class AccountLinkRMList implements Schedulable, Database.Batchable<sObject> {
    private final Integer BATCH_SIZE;

    private Integer delayDay ;

    // テストのため、指定日時が変えるように該当メソッドを追加した。
    global void setDelayDay(Integer d){
        this.delayDay=d;
    }

    global Integer getDelayDay(){
        
        return this.delayDay;
    }


    // システムラベルから指定日数を取得し、数字以外の場合、全データが対象になる
    global AccountLinkRMList() {
        this(200);
        Boolean Test = Pattern.matches('^[0-9]+$', System.Label.AccountLinkRMListPeriod);
        if(Test==true){
            this.delayDay = -Integer.valueOf(System.Label.AccountLinkRMListPeriod);
        }else{
            this.delayDay =1;
        }
        
    }
    global AccountLinkRMList(Integer batchSize) {
        BATCH_SIZE = batchSize;
    }


    global void execute(SchedulableContext sc) {
        Database.executeBatch(this, BATCH_SIZE);
    }

    // 法人番号がNull以外のものは対象になる
    global Database.QueryLocator start(Database.BatchableContext bc) {

        return Database.getQueryLocator([SELECT Id, corporate_number__c 
        FROM Account 
        WHERE corporate_number__c != null]
        );
    }

    global void execute(Database.BatchableContext bc, List<sObject> scope) {
        // 法人番号と取引先IDのMap
        Map<String, Id> keyIdMainMap = new Map<String, Id>();
        for (Account sobj : (List<Account>)scope) {
            keyIdMainMap.put(sobj.corporate_number__c, sobj.Id);
        }
        System.debug(scope);
        System.debug('b'+System.Label.AccountLinkRMListPeriod+'a');
        
        DateTime myDate = System.today();
        DateTime datePeriod = myDate;
        Integer addHour = 9;

        //RMBusinessSectionList__c
       
        List<RMBusinessSectionList__c> updateList2 = New List<RMBusinessSectionList__c>();
        System.debug('keyIdMainMap.keySet -- ' + keyIdMainMap.keySet());
        
        

        if ( delayDay <= 0  ) {
            datePeriod = myDate.addDays(delayDay);
　　        // 日本時差　９時間
            datePeriod = datePeriod.addHours(addHour);
            System.debug('datePeriod -- ' + datePeriod);

            updateList2 = [SELECT Id, corporate_number__c, Account__c 
                                        FROM RMBusinessSectionList__c
                                        WHERE corporate_number__c IN :keyIdMainMap.keySet()
                                        AND lastModifiedDate >= :datePeriod
                                        ];
        }else{
            System.debug('delayDay -- ' + delayDay);
            updateList2 = [SELECT Id, corporate_number__c, Account__c 
                                        FROM RMBusinessSectionList__c
                                        WHERE corporate_number__c IN :keyIdMainMap.keySet()
                            ];

        }
        
        List<RMBusinessSectionList__c> updateList2Target =  new List<RMBusinessSectionList__c>();

        if (!updateList2.isEmpty()) {
            for (RMBusinessSectionList__c c : updateList2) {
                // 取引先IDがNull、また更新がある場合、更新対象になる
                if(c.Account__c == null || c.Account__c <> keyIdMainMap.get(c.corporate_number__c) ){
                    c.Account__c = keyIdMainMap.get(c.corporate_number__c);
                    updateList2Target.add(c);
                }
            }
            System.debug('updateList2Target -- '+updateList2Target);
            update updateList2Target;
        }
    }

    global void finish(Database.BatchableContext bc) {
    }
}
```