美文网首页
Apex计划作业框架的实现

Apex计划作业框架的实现

作者: 程程哥 | 来源:发表于2017-11-15 19:57 被阅读0次

    在本文中,我们实现一个简单的“计划作业框架”,用于实现数据的定时自动处理。

    Apex相关接口

    Apex中提供了一组接口用来实现数据的处理。我们主要使用以下两个:

    • Schedulable:数据的定时处理
    • Batchable:数据的批量处理

    示例情景

    本文以如下情景为例,实现计划作业框架。

    • 数据模型:在Salesforce中有一个银行账号对象,API名称为“BankAccount__c”。在此对象中有字段“到期日期”,API名称为“ExpireDate__c”,和字段“状态”,API名称为“Status__c”。

    • 业务流程:

    1. 每天夜里的固定时间,系统需要自动检查银行账号,并将“到期日期”和当前日期作比较
    2. 如果银行账号到期,则将“状态”字段的值更新为“过期”
    • 业务逻辑代码:在Salesforce中已经相应的业务逻辑,存放在Apex类“BankAccount_Status_Handler”中,对应的函数是“updateExpireStatus()”

    框架组成部分

    计划作业框架要实现的功能是定时对大批量的数据进行处理,由两个Apex类组成:

    1. BankAccount_Batch_Status_Handler:实现了Batchable接口,查询并提取批量数据,并调用Apex类“BankAccount_Status_Handler”中的函数对银行账号对象进行处理
    2. 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”类重新设定自动执行。

    相关文章

      网友评论

          本文标题:Apex计划作业框架的实现

          本文链接:https://www.haomeiwen.com/subject/ivbhvxtx.html