前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Salesforce Future method in salesforce – @future

Salesforce Future method in salesforce – @future

原创
作者头像
repick
修改2021-11-23 21:42:45
8180
修改2021-11-23 21:42:45
举报
文章被收录于专栏:Salesforce

future方法用于在系统资源可用时在单独的线程中运行进程,我们可以将future方法用于任何我们希望在其自己的线程中异步运行的操作。

1.一般用于以下2种场景:

·external Web services callout

·Trigger中DML实行后,再次CallOut操作。

2.方法构成

·在方法前指定@future标签

·必须时static方法并且返回值时void

·引数必须是基本数据类型或基本数据类型的集合

·引数不能使用标准的Object类型或者sObject类型

·引数一般使用List record IDs来传递数据

构成例:

代码语言:javascript
复制
global class SomeClass {
    @future
    public static void someFutureMethod(List<Id> recordIds) {
      List<Account> accounts = [Select Id, Name from Account Where Id IN :recordIds];
      // process account records to do awesome stuff
    }
}  

3.注意:

·引数不能使用标准的Object类型或者sObject类型的理由,future方法执行中需要等待的时间,这个过程中Object中的值有变化的可能,容易造成不好的影响。

·future方法不能保证执行顺序,2个future方法很容易同时执行,如果同时更新一条数据,容易造成锁表,发生error。

·future方法不能调用另一个同为future的方法

4.例:

现做成两个方法,一个不指定@future,另一个指定@future,并验证结果正确与否。

代码语言:javascript
复制
public with sharing class ExampleFuture {
    public static void methodNoFuture(Set<Id> idsSet) {
        String sql = 'SELECT Id,Name FROM Opportunity where Id in :idsSet';
        List<Opportunity> opps = Database.query(sql);
        List<Opportunity> newOppList = new List<Opportunity>();
        for(Opportunity opp : opps) {
            opp.stageName = 'Closed Won';
            newOppList.add(opp);
        }
        update newOppList;
        System.debug('>>>>>>>>methodNoFuture::'+System.isQueueable());
    }

    @future
    public static void methodFuture(Set<Id> idsSet) {
        String sql = 'SELECT Id,Name FROM Opportunity where Id in :idsSet';
        List<Opportunity> opps = Database.query(sql);
        List<Opportunity> newOppList = new List<Opportunity>();
        for(Opportunity opp : opps) {
            opp.stageName = 'Closed Won';
            newOppList.add(opp);
        }
        update newOppList;
        System.debug('>>>>>>>>methodFuture::'+System.isQueueable());
    }
}

下边是测试类,区别是调用future方法时,调用的地方必须在【Test.startTest();】和【Test.stopTest();】之间,否则调用不成功。

代码语言:javascript
复制
@isTest
public with sharing class ExampleFutureTest {
    static testMethod void FutureTest001() {
        List<Opportunity> oppList = new List<Opportunity>();
        for(integer i = 0; i<200; i++){
            Opportunity oppItem = new Opportunity(Name='methodNoFutureOpportunity'+ i,
                                StageName='Perception Analysis',
                                CloseDate = Date.Today(),
                                DeleteFlg__c = true);
            oppList.add(oppItem);
        }
        insert oppList;
        Map<Id, Opportunity> oppsMap = new Map<Id, Opportunity>(oppList);
        ExampleFuture.methodNoFuture(oppsMap.keySet());

        List<Opportunity> oppUpdateList = [SELECT Id,StageName FROM Opportunity WHERE DeleteFlg__c = true];
        System.assertEquals(200, oppUpdateList.size());
        if (oppUpdateList != null && oppUpdateList.size() >0) {
            for (Opportunity oppUpdate : oppUpdateList) {
                System.assertEquals('Closed Won', oppUpdate.StageName);
            }
        }
    }
    static testMethod void FutureTest002() {
        List<Opportunity> oppList = new List<Opportunity>();
        for(integer i = 0; i<200; i++){
            Opportunity oppItem = new Opportunity(Name='methodFutureOpportunity'+ i,
                                StageName='Perception Analysis',
                                CloseDate = Date.Today(),
                                DeleteFlg__c = true);
            oppList.add(oppItem);
        }
        insert oppList;
        Map<Id, Opportunity> oppsMap = new Map<Id, Opportunity>(oppList);

        Test.startTest();
        ExampleFuture.methodFuture(oppsMap.keySet());
        Test.stopTest();

        List<Opportunity> oppUpdateList = [SELECT Id,StageName FROM Opportunity WHERE DeleteFlg__c = true];
        System.assertEquals(200, oppUpdateList.size());
        if (oppUpdateList != null && oppUpdateList.size() >0) {
            for (Opportunity oppUpdate : oppUpdateList) {
                System.assertEquals('Closed Won', oppUpdate.StageName);
            }
        }
    }
}

执行结果:

sObjects That Cannot Be Used Together in DML Operations

某些 sObject 上的 DML 操作不能与同一事务中其他 sObject 上的 DML 混合执行,例如以下当插入Account表数据时,需要同时插入带有Role的User,这时插入user方法需指定@future

代码语言:javascript
复制
public with sharing class ExampleMixedDMLFuture {
    public static void useFutureMethod() {
        // First DML operation
        Account a = new Account(Name='Acme');
        insert a;
        System.debug('>>>>>>>>useFutureMethod11::'+System.isQueueable());
        // This next operation (insert a user with a role)
        // can't be mixed with the previous insert unless
        // it is within a future method.
        // Call future method to insert a user with a role.
        ExampleInsertUserFuture.insertUserWithRole(
            'xiang@awcomputing.com', 'xiang',
            'yu@awcomputing.com', 'yu');
        System.debug('>>>>>>>>useFutureMethod22::'+System.isQueueable());
    }
}
代码语言:javascript
复制
public with sharing class ExampleInsertUserFuture {
    @future
    public static void insertUserWithRole(String uname, String al, String em, String lname) {
        System.debug('>>>>>>>>insertUserWithRole111::'+System.isQueueable());
        Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
        UserRole r = [SELECT Id FROM UserRole WHERE Name='COO'];
        // Create new user with a non-null user role ID
        User u = new User(alias = al, email=em,
            emailencodingkey='UTF-8', lastname=lname,
            languagelocalekey='en_US',
            localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
            timezonesidkey='America/Los_Angeles',
            username=uname);
        insert u;
        System.debug('>>>>>>>>insertUserWithRole222::'+System.isQueueable());
    }
}

测试类:

代码语言:javascript
复制
@isTest
public with sharing class ExampleMixedDMLFutureTest {
    @isTest static void test1() {
        User thisUser = [SELECT Id FROM User WHERE Id = :UserInfo.getUserId()];
       // System.runAs() allows mixed DML operations in test context
        System.runAs(thisUser) {
            // startTest/stopTest block to run future method synchronously
            Test.startTest();
            ExampleMixedDMLFuture.useFutureMethod();
            Test.stopTest();
        }
        // The future method will run after Test.stopTest();

        // Verify account is inserted
        Account[] accts = [SELECT Id from Account WHERE Name='Acme'];
        System.assertEquals(1, accts.size());
        // Verify user is inserted
        User[] users = [SELECT Id from User where username='xiang@awcomputing.com'];
        System.assertEquals(1, users.size());
    }
}

执行结果:

在同一事务中执行 DML 操作时,不能将以下 sObject 与其他 sObject 一起使用

  • FieldPermissions
  • Group
  • GroupMember
  • ObjectPermissions
  • PermissionSet
  • PermissionSetAssignment
  • QueueSObject
  • ObjectTerritory2AssignmentRule
  • ObjectTerritory2AssignmentRuleItem
  • RuleTerritory2Association
  • SetupEntityAccess
  • Territory2
  • Territory2Model
  • UserTerritory2Association
  • User

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.一般用于以下2种场景:
  • 2.方法构成
  • 构成例:
  • 3.注意:
  • 4.例:
  • sObjects That Cannot Be Used Together in DML Operations
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档