Apex計划作業框架的實現
在本文中,我們實現一個簡單的“計划作業框架”,用於實現數據的定時自動處理。
Apex相關接口
Apex中提供了一組接口用來實現數據的處理。我們主要使用以下兩個:
- Schedulable:數據的定時處理
- Batchable:數據的批量處理
示例情景
本文以如下情景為例,實現計划作業框架。
-
數據模型:在Salesforce中有一個銀行賬號對象,API名稱為“BankAccount__c”。在此對象中有字段“到期日期”,API名稱為“ExpireDate__c”,和字段“狀態”,API名稱為“Status__c”。
-
業務流程:
- 每天夜里的固定時間,系統需要自動檢查銀行賬號,並將“到期日期”和當前日期作比較
- 如果銀行賬號到期,則將“狀態”字段的值更新為“過期”
- 業務邏輯代碼:在Salesforce中已經相應的業務邏輯,存放在Apex類“BankAccount_Status_Handler”中,對應的函數是“updateExpireStatus()”
框架組成部分
計划作業框架要實現的功能是定時對大批量的數據進行處理,由兩個Apex類組成:
- BankAccount_Batch_Status_Handler:實現了Batchable接口,查詢並提取批量數據,並調用Apex類“BankAccount_Status_Handler”中的函數對銀行賬號對象進行處理
- BankAccount_Batch_Status_SCH:實現了Schedulable接口,用於在Salesforce的設置界面中設置定時的任務,執行“BankAccount_Batch_Status”類的功能
代碼
BankAccount_Status_Handler類:
public class BankAccount_Status_Handler {
public static void updateExpireStatus(Set<Id> bankAccountIds) {
// 業務邏輯
// ...
}
}
BankAccount_Batch_Status_Handler類:
global class BankAccount_Batch_Status_Handler implements Database.Batchable<sObject> {
public Database.QueryLocator start(Database.BatchableContext bc) {
// 初始化,得到需要處理的數據
return Database.getQueryLocator([SELECT Id, ExpireDate__c FROM BankAccount__c]);
}
public void execute(Database.BatchableContext bc, List<SObject> scope) {
// 得到需要處理的數據的Id集合
Set<Id> scopeIds = new Map<Id, SObject>(scope).keySet();
// 進行處理
BankAccount_Status_Handler.updateExpireStatus(scopeIds);
}
public void finish(Database.BatchableContext bc) {}
}
BankAccount_Batch_Status_SCH類:
global class BankAccount_Batch_Status_SCH implements Schedulable {
public void execute(SchedulableContext sc) {
// 初始化 BankAccount_Batch_Status_Handler 類
BankAccount_Batch_Status_Handler batch = new BankAccount_Batch_Status_Handler();
// 執行批處理操作
Database.executebatch( batch, 200 );
}
}
設置Job的執行
“BankAccount_Batch_Status_SCH”類實現了“Schedulable”接口,所以可以被設定為自動執行。
在Salesforce的設置界面,查找“Apex”,點擊“Apex 類”鏈接,進入Apex類的一覽表。
點擊“計划Apex”按鈕,在其中的“Apex 類”部分選擇“BankAccount_Batch_Status_SCH”類,然后設定其他的屬性。
這樣,計划作業框架就建立完成了。代碼中的邏輯會在固定的時間自動執行。
優化
上述的代碼是由兩個分別實現了Schedulable和Batchable接口的類所組成,其中直接寫死了調用銀行賬戶對象相關的類和邏輯。
我們可以將它們擴展為通用的框架,增加復用性。
停用已經計划的Apex類
在重構代碼之前,因為“BankAccount_Batch_Status_SCH”類已經被設定了計划執行,所以“BankAccount_Batch_Status_SCH”類和其調用的類都不能被修改。
要想進行代碼重構,必須先停止已經計划的Apex類。
在設置界面搜索“計划的作業”,點擊“計划的作業”鏈接,進入“所有計划的作業”一覽表。在表中可以直接刪除“BankAccount_Batch_Status_SCH”類的計划。
對Batchable相關的類進行擴展
新建一個Apex類,名叫“Job_Batch_Handler_Abstract”,代碼如下:
public abstract class Job_Batch_Handler_Abstract implements Database.Batchable<sObject> {
protected abstract Database.QueryLocator getQueryLocator(); // 抽象函數,用於得到需要處理的數據
protected abstract void executeLogic(Set<Id> scopeIds); // 抽象函數,用於執行具體的邏輯
public Database.QueryLocator start(Database.BatchableContext bc) {
return getQueryLocator(); // 動態得到需要處理的數據
}
public void execute(Database.BatchableContext bc, List<SObject> scope) {
// 得到需要處理的數據的Id集合
Set<Id> scopeIds = new Map<Id, SObject>(scope).keySet();
// 進行處理,具體的邏輯需要具體實現
executeLogic(scopeIds);
}
public void finish(Database.BatchableContext bc) {}
}
將之前的“BankAccount_Batch_Status_Handler”類改為繼承了“Job_Batch_Handler_Abstract”類:
global class BankAccount_Batch_Status_Handler extends Job_Batch_Handler_Abstract {
protected override Database.QueryLocator getQueryLocator() {
// 初始化,得到需要處理的數據
return Database.getQueryLocator([SELECT Id, ExpireDate__c FROM BankAccount__c]);
}
protected override void executeLogic(Set<Id> scopeIds) {
// 具體的處理邏輯
BankAccount_Status_Handler.updateExpireStatus(scopeIds);
}
}
這樣,“Job_Batch_Handler_Abstract”類就可以作為通用的類,被其他的類所繼承和使用。
對Schedulable相關的類進行擴展
新建一個Apex類,名叫“Job_Batch_SCH_Abstract”,代碼如下:
public abstract class Job_Batch_SCH_Abstract implements Schedulable {
protected abstract String getHandlerName(); // 抽象函數,用於得到具體的類名字
public void execute(SchedulableContext sc) {
// 根據開發者定義的類名,新建相應類的實例
Object o = Type.forName( getHandlerName() ).newInstance();
Job_Batch_Handler_Abstract batch;
// 檢查新的實例是否是Job_Batch_Handler_Abstract抽象類的子類。如果是,則執行批量處理
if ( o != null && o instanceof Job_Batch_Handler_Abstract) {
batch = (Job_Batch_Handler_Abstract) o;
Database.executebatch( batch, 200 );
}
}
}
將之前的“BankAccount_Batch_Status_SCH”類改為繼承了“Job_Batch_SCH_Abstract”類:
global class BankAccount_Batch_Status_SCH extends Job_Batch_SCH_Abstract {
protected override String getHandlerName(){
return 'BankAccount_Batch_Status_Handler';
}
}
這樣,“Job_Batch_SCH_Abstract”類就可以作為通用的類,被其他的類所繼承和使用。
完成了這兩個通用類的實現,就可以在Salesforce的設置界面為“BankAccount_Batch_Status_SCH”類重新設定自動執行。