APEX 教程:Apex 编程类和编码示例

什么是 Salesforce Apex?

Apex 是 Salesforce 开发的一种面向对象的、强类型编程语言,用于构建软件即服务 (SaaS) 和客户关系管理 (CRM)。Apex 通过提供后端数据库支持和客户端-服务器接口,帮助开发人员创建第三方 SaaS 应用程序,并在系统事件中添加业务逻辑。

Apex 帮助开发人员为按钮单击、相关记录更新和 Visualforce 页面等系统事件添加业务逻辑。Apex 的语法与 Java 类似。注册 Salesforce 了解 CRM 的工作原理。

Apex 编程语言的特点

以下是 Salesforce Apex 的重要功能

  • Apex 是一种不区分大小写的语言。
  • 您可以使用 Apex 执行 DML 操作,如 INSERT、UPDATE、UPSERT、DELETE,用于 sObject 记录。
  • 您可以在 Apex 中使用 SOQL(Salesforce 对象查询语言)和 SOSL(Salesforce 对象搜索语言)查询 sObject 记录。
  • 允许您创建单元测试并执行它们,以验证 Apex 中代码的代码覆盖率和效率。
  • Apex 在多租户环境中执行,Salesforce 定义了一些事务限制,以防止用户控制共享资源。任何超出 Salesforce 事务限制的代码都会失败并显示错误。
  • Salesforce 对象可以用作 Apex 中的数据类型。例如:
    Account acc = new Account();

    在此,Account 是标准的 Salesforce 对象。

  • Apex 会随每次 Salesforce 版本自动升级。

开发者何时应选择 Apex

只有当业务场景过于复杂,无法使用 Salesforce 提供的预构建功能来实现时,才应编写 Apex 代码。

以下是我们需要编写 Apex 代码的一些场景

  • 创建 Web 服务以将 Salesforce 与其他应用程序集成。
  • 在 sobjects 上实现自定义验证。
  • 在执行 DML 操作时执行自定义 Apex 逻辑。
  • 实现无法使用现有工作流、流程和 Process Builder 功能实现的功能。
  • 要设置电子邮件服务,您需要包含使用 Apex 代码处理电子邮件的内容、标头和附件。

Apex 的工作结构

现在,在本 Apex 教程中,我们将学习 Apex 的工作结构。

以下是 Apex 代码的操作流程

  • 开发者操作:开发者编写的所有 Apex 代码都将被编译成一组指令,当开发者将代码保存到平台时,Apex 运行时解释器可以理解这些指令,然后将这些指令作为元数据保存到平台。
  • 最终用户操作:当用户事件执行 Apex 代码时,平台服务器将从元数据中获取编译后的指令,并在返回结果之前通过 Apex 解释器运行它们。
Working Structure Of Apex
Apex 的工作结构

Apex 语法

变量声明

由于 Apex 是强类型语言,因此必须在 Apex 中声明带有数据类型的变量。

例如

contact con = new contact(); 

这里,变量 con 以 contact 作为数据类型声明。

SOQL 查询

SOQL 代表 Salesforce 对象查询语言。SOQL 用于从 Salesforce 数据库中提取 sObject 记录。例如:

Account acc = [select id, name from Account Limit 1]; 

上述查询从 Salesforce 数据库中提取了 Account 记录。

循环语句

循环语句用于迭代列表中的记录。迭代次数等于列表中的记录数。例如:

list<Account>listOfAccounts = [select id, name from account limit 100];
// iteration over the list of accounts
for(Account acc : listOfAccounts){
	//your logic
}

在上面的代码片段中,listOfAccounts 是一个列表数据类型的变量。

流程控制语句

当您想根据某些条件执行部分代码行时,流程控制语句非常有用。

例如

list<Account>listOfAccounts = [select id, name from account limit 100];
// execute the logic if the size of the account list is greater than zero
if(listOfAccounts.size() >0){
	//your logic
}

上面的代码片段正在从数据库中查询 Account 记录并检查列表大小。

DML 语句

DML 代表数据操作语言。DML 语句用于操作 Salesforce 数据库中的数据。例如:

Account acc = new Account(Name = ‘ Test Account’);
Insert acc; //DML statement to create account record.

Apex 开发环境

现在,在本 Apex 编程教程中,我们将学习 Apex 开发环境。

Apex 代码可以在 Salesforce 的沙箱和开发者版本中进行开发。

最佳实践是在沙箱环境中开发代码,然后将其部署到生产环境。

Apex Development Environment

Apex 代码开发工具:在 Salesforce 的所有版本中,有以下三种工具可用于开发 Apex 代码。

  • Force.com Developer Console
  • Force.com IDE
  • Salesforce 用户界面中的代码编辑器

Apex 中的数据类型

以下是 Apex 支持的数据类型

原始类型

Integer、Double、Long、Date、DateTime、String、ID 和 Boolean 被视为原始数据类型。所有原始数据类型都按值传递,而不是按引用传递。

集合

Apex 中有三种集合可用

  • List:它是原始类型、sObjects、集合或 Apex 对象的有序集合,基于索引。
  • Set:它是唯一的原始类型的无序集合。
  • Map:它是唯一的、原始键的集合,映射到单个值,这些值可以是原始类型、sObjects、集合或 Apex 对象。

sObject

这是 Salesforce 中的一种特殊数据类型。它类似于 SQL 中的表,并包含类似于 SQL 列的字段。

Enums

Enum 是一种抽象数据类型,用于存储有限的指定标识符集中的一个值。

Objects

它指的是 Apex 中支持的任何数据类型。

Interfaces

Apex 访问修饰符

以下是 Apex 支持的访问修饰符

公共链

此访问修饰符允许在命名空间内的 Apex 中使用类、方法、变量。

私有链

此访问修饰符允许在本地或代码的某个部分(在其定义位置)使用类、方法、变量。所有未定义任何访问修饰符的方法和变量,其默认访问修饰符均为 private。

Protected

此访问修饰符允许在定义 Apex 类的任何内部类中使用方法、变量。

Global

此访问修饰符允许在命名空间内以及命名空间外的 Apex 中使用类、方法、变量。除非必要,否则不建议使用 global 关键字。

Apex 中的关键字

With sharing

如果一个类使用此关键字定义,则会强制执行当前用户的所有共享规则;如果缺少此关键字,则代码将在系统上下文中执行。

例如

public with sharing class MyApexClass{
// sharing rules enforced when code in this class execute
}

Without sharing

如果一个类使用此关键字定义,则不会强制执行当前用户的所有共享规则。

例如

public without sharing class MyApexClass{
// sharing rules is not enforced when code in this class execute
}

静态

用 static 关键字定义的变量、方法只初始化一次,并与类相关联。可以直接通过类名调用静态变量、方法,而无需创建类的实例。

Final

用 final 关键字定义的常量、方法不能被覆盖。例如:

public class myCls {
static final Integer INT_CONST = 10;
}

如果您尝试覆盖此 INT_CONST 变量的值,您将收到一个异常:System.FinalException: Final variable has already been initialized。

退货

此关键字从方法返回一个值。例如:

public String getName() {
return  'Test' ;
}

Null

它定义了一个 null 常量,可以分配给变量。例如:

 Boolean b = null;

Virtual

如果一个类用 virtual 关键字定义,它可以被扩展和覆盖。

Abstract

如果一个类用 abstract 关键字定义,它必须至少包含一个 abstract 关键字的方法,并且该方法只能有签名。

例如

public abstract class MyAbstrtactClass {
abstract Integer myAbstractMethod1();
}

Apex String

字符串是一组字符,没有字符限制。例如:

String name = 'Test';

Salesforce 中的 String 类提供了许多内置方法。以下是一些最常用和最常用的函数:

abbreviate(maxWidth)

此方法将字符串截断为指定的长度并返回它,如果给定字符串的长度大于指定长度;否则,它将返回原始字符串。如果 maxWidth 变量的值小于 4,此方法将返回一个运行时异常:System.StringException: Minimum abbreviation width is 4。

例如

String s = 'Hello World';
String s2 = s.abbreviate(8);
System.debug('s2'+s2); //Hello...

capitalize()

此方法将字符串的第一个字母转换为标题大小写并返回它。

例如

String s = 'hello;
String s2 = s.capitalize();
System.assertEquals('Hello', s2);

contains(substring)

如果调用方法的字符串包含指定的子字符串,则此方法返回 true。

String name1 = 'test1';
String name2 = 'test2';
Boolean flag = name.contains(name2);
System.debug('flag::',+flag); //true

equals(stringOrId)

如果传递的参数不为 null,并且表示与调用方法的字符串相同的字符二进制序列,则此方法返回 true。

在比较 Id 值时,Id 的长度可能不相等。例如:如果一个代表 15 位 Id 的字符串与一个代表 18 位 Id 的对象进行比较,此方法将返回 true。例如:

Id idValue15 = '001D000000Ju1zH';
Id idValue18 = '001D000000Ju1zHIAR';
Boolean result4 = stringValue15.equals(IdValue18);
System.debug('result4', +result4); //true

在上面的示例中,equals 方法正在比较 15 位对象 Id 和 18 位对象 Id,如果这两个 Id 代表相同的二进制序列,它将返回 true。

使用此方法进行区分大小写的比较。

escapeSingleQuotes(stringToEscape)

此方法在字符串中的任何单引号前添加转义字符 (\) 并返回它。此方法在创建动态 SOQL 查询时可防止 SOQL 注入。此方法确保所有单引号都被视为包含字符串,而不是数据库命令。

例如

String s = 'Hello Tom';
system.debug(s); // Outputs 'Hello Tom'
String escapedStr = String.escapeSingleQuotes(s);
// Outputs \'Hello Tom\'

remove(substring)

此方法从调用方法的字符串中删除指定子字符串的所有出现,并返回结果字符串。

例如

String s1 = 'Salesforce and force.com';
String s2 = s1.remove('force');
System.debug( 's2'+ s2);// 'Sales and .com'

substring(startIndex)

此方法从 startIndex 处的字符开始返回一个子字符串,该子字符串一直延伸到字符串的末尾。

例如

String s1 = 'hamburger';
String s2 = s1.substring(3);
System.debug('s2'+s2); //burger

reverse()

此方法反转字符串的所有字符并返回它。例如:

String s = 'Hello';
String s2 = s.reverse();
System.debug('s2::::'+s2);// olleH  // Hello

trim(): 此方法删除字符串中的所有前导空格并返回它。

valueOf(toConvert)

此方法返回传入对象的字符串表示形式。

Apex 事务限制

Apex 事务限制是 Apex 运行时引擎强制执行的限制,以确保任何失控的 Apex 代码和进程不会控制共享资源,并且不会违反多租户环境中其他用户的处理。这些限制会针对每个 Apex 事务进行验证。以下是 Salesforce 对每个 Apex 事务定义的事务限制:

描述 限制
同步事务中可以进行的 SOQL 查询数 100
异步事务中可以进行的 SOQL 查询数 200
SOQL 查询可以检索的记录数 50000
Database.getQueryLocator 可以检索的记录数 10000
Apex 事务中可以进行的 SOSL 查询数 20
SOSL 查询可以检索的记录数 2000
Apex 事务中可以进行的 DML 语句数 150
作为 DML 语句、Approval.process 或 database.emptyRecycleBin 结果可以处理的记录数 10000
Apex 事务中可以进行的 Callout 数。 100
Apex 事务中执行的所有 Callout 的累积超时限制 120 秒
通过 System.enqueueJob 可以添加到队列的 Apex 作业数限制 50
每个 Apex 事务的执行时间限制 10 分钟
Apex 类和触发器中可以使用的字符数限制 100 万
同步事务的 CPU 时间限制 10,000 毫秒
异步事务的 CPU 时间限制 60,000 毫秒

Apex Getters and Setters

Apex 属性类似于 Apex 变量。Getter 和 Setter 对于 Apex 属性是必需的。Getter 和 Setter 可用于在访问或更改属性值之前执行代码。get 访问器中的代码在读取属性值时执行。set 访问器中的代码在更改属性值时运行。任何具有 get 访问器的属性都被视为只读,任何具有 set 访问器的属性被视为只写,任何同时具有 get 和 set 访问器的属性都被视为读写。Apex 属性的语法:

public class myApexClass {
// Property declaration
	access_modifierreturn_typeproperty_name {
	get {
			//code  
		}
		set{
			//code
		}
	}

在此,access_modifier 是属性的访问修饰符。return_type 是属性的数据类型。property_name 是属性的名称。

下面是一个同时具有 get 和 set 访问器的 Apex 属性示例。

public class myApex{
	public String name{
		get{ return name;}
		set{ name = 'Test';}
	}
}

在此,属性名称为 name,它是公共属性,并且返回一个字符串数据类型。

get 和 set 块不一定必须包含代码。这些块可以留空以定义自动属性。例如:

public double MyReadWriteProp{ get; set; } 

Get 和 set 访问器也可以用它们的访问修饰符来定义。如果访问器用修饰符定义,则它会覆盖属性的访问修饰符。例如:

public String name{private get; set;}// name is private for read and public to write.

Apex 类

Apex 类是对象的蓝图或模板。对象是类的实例。

Salesforce 中创建 Apex 类有三种方式:

Developer Console

Force.com IDE

Apex 类详细信息页面。

在 Apex 中,您可以定义一个外部类(也称为顶级类),您也可以在外部类内定义类(称为内部类)。

在外部类的声明中必须使用 global 或 public 等访问修饰符。

在内部类的声明中不一定需要使用访问修饰符。

Apex 类使用 class 关键字后跟类名来定义。

Extends 关键字用于 Apex 类扩展现有类,implements 关键字用于 Apex 类实现接口。

Salesforce Apex 不支持多重继承,一个 Apex 类只能扩展一个现有 Apex 类,但可以实现多个接口。

Apex 类可以包含用户定义的构造函数,如果用户定义的构造函数不可用,则使用默认构造函数。构造函数中的代码在创建类的实例时执行。

Apex 类示例语法

public class myApexClass{
// variable declaration
//constructor
	public myApexClass{
	}
//methods declaration
}

new 关键字用于创建 Apex 类的实例。下面是创建 Apex 类实例的语法。

myApexClass obj = new myApexClass();

Apex Trigger

Apex 触发器允许您在执行 DML 操作之前和之后执行自定义 Apex。

Apex 支持以下两种类型的触发器:

Before 触发器:这些触发器用于在记录保存到数据库之前验证和更新字段值。

After 触发器:这些触发器用于访问记录提交到数据库后由系统设置的字段(记录 ID、LastModifiedDate 字段)。这些字段值可用于修改其他记录。触发 after 触发器的记录是只读的。

编写批量触发器是最佳实践。批量触发器可以一次处理单个记录和多个记录。

Apex 触发器语法

trigger TriggerName on ObjectName (trigger_events) {
	//Code_block
 }

在此,TriggerName 是触发器的名称,ObjectName 是要编写触发器的对象名称,trigger_events 是逗号分隔的事件列表。

Apex 触发器支持的事件包括:before insert、before update、before delete、after insert、after update、after delete、after undelete。

Static 关键字不能在 Apex 触发器中使用。适用于内部类的所有关键字都可以用于 Apex 触发器。

每个触发器都有预定义的隐式变量,用于返回运行时上下文。这些变量定义在 System.Trigger 类中。这些变量称为上下文变量。下图显示了 Apex 触发器支持的上下文变量。

Apex Trigger

Apex Trigger

以下是 Apex 触发器中上下文变量的注意事项:

  • 请勿在 DML 操作中使用 trigger.new 和 trigger.old。
  • 不能删除 Trigger.new。
  • Trigger.new 是只读的。
  • 在 before 触发器中,Trigger.new 可用于修改同一对象字段的值。

以下截图列出了不同触发器事件中特定操作的注意事项。

Apex Trigger

Apex Trigger

Apex 中的批处理类

Salesforce 中的 Batch 类用于处理大量记录,如果正常处理,这些记录将超出 Apex 事务限制。Batch 类异步执行代码。

以下是 Batch 类的优点:

  • Batch 类分块处理数据,如果一个块处理失败,所有已成功处理的块都不会回滚。
  • Batch 类中的每个数据块都以新的事务限制集进行处理,这确保了代码在事务执行限制内运行。
  • Apex 类必须实现 Database.Batchable 接口才能用作 Batch 类。它提供了三个必须由 Batch 类实现的方法。

以下是 Database.Batchable 接口提供的三个方法:

1. start()

此方法生成接口方法 execute 要处理的记录或对象的范围。在批处理执行期间,它只调用一次。此方法返回 Database.QueryLocator 对象或 Iterable。使用 Database.QueryLocator 对象通过 SQL 查询检索的记录数为 5000 万条,但使用可迭代对象,通过 SQL 查询检索的记录总数为 50,000 条。Iterable 用于为批处理类生成复杂的范围。

start 方法的语法

global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContextbc) {}

2. execute()

此方法用于处理每个数据块。对于每批记录,都会调用 execute 方法。默认批处理大小为 200 条记录。Execute 方法接受两个参数:

对 Database.BatchableContext 对象的引用,

sObjects 的列表,例如 List<sObject>,或参数化类型的列表。execute 方法的语法:

global void execute(Database.BatchableContext BC, list<P>){}

3. finish()

finish 方法在批处理类执行期间调用一次。后处理操作可以在 finish 方法中执行。例如:发送确认电子邮件。此方法在所有批处理完成处理后调用。Finish 方法的语法:

global void finish(Database.BatchableContext BC){}

Database.BatchableContext 对象

Database.Batchable 接口的每个方法都有一个对 Database.BatchableContext 对象的引用。

此对象用于跟踪批处理作业的进度。

以下是 BatchableContext 提供的实例方法:

  • getChildJobId(): 此方法返回当前处理的批处理作业的 ID。
  • getJobId(): 此方法返回批处理作业的 ID。

以下是批处理类的语法:

global class MyBatchClass implements Database.Batchable<sObject> {
	global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContextbc) {
// collect the batches of records or objects to be passed to execute
}
global void execute(Database.BatchableContextbc, List<P> records){
// process each batch of records
}
global void finish(Database.BatchableContextbc){
// execute any post-processing operations
}
}

Database.executeBatch 方法

Database.executeBatch 方法用于执行批处理类。

此方法接受两个参数:要处理的批处理类的实例,Options 参数用于指定批处理大小,如果未指定,则默认为 200。

Database.executeBatch 的语法:

Database.executeBatch(myBatchObject,scope)

执行名为 MyBatchClass 的批处理类。

MyBatchClassmyBatchObject = new MyBatchClass(); 
Id batchId = Database.executeBatch(myBatchObject,100);

Database.stateful

Batch 类默认是无状态的。每次调用 execute 方法时,都会接收一个新对象副本,类的所有变量都会被初始化。

实现 Database.stateful 以使批处理类具有状态。

如果您的批处理类实现了Database, stateful 接口,则所有实例变量都会保留其值,但静态变量会在事务之间重置。

摘要

  • Apex 是一种强类型、面向对象的编程语言,可在 Force.com 平台上编译和运行。
  • Apex 编程语言是一种不区分大小写的语言。
  • Apex 有两种操作流程:1)开发者操作 2)最终用户操作。
  • Apex 帮助您创建 Web 服务以将 Salesforce 与其他应用程序集成。
  • Apex 支持的数据类型包括:1)原始类型 2)集合 3)sObject、Enums、4)类、5)对象和接口。
  • Apex 支持 Public、Private、Protected 和 Global 修饰符。
  • Apex 中使用的关键字包括:1)With Sharing、2)Without sharing、3)Static、4)Final 5)Return、6)Null、7)Virtual、8)Abstract。
  • 字符串是一组字符,没有字符限制。
  • Apex 事务限制是 Apex 运行时引擎强制执行的限制,以确保任何失控的 Apex 代码和进程。
  • Getter 和 Setter 可用于在访问或更改属性值之前执行代码。
  • Salesforce 中创建 Apex 类有三种方式:1)Developer Console 2)Force.com IDE 和 3)Apex 类详细信息页面。
  • Apex 触发器允许您在执行 DML 操作之前和之后执行自定义 Apex。
  • Salesforce 中的 Batch 类用于处理大量记录,这些记录如果正常处理将超出 Apex 事务限制。