Hướng dẫn sử dụng Salesforce Apex dành cho người mới bắt đầu

⚡ Tóm tắt thông minh

Lập trình Apex cung cấp cho các nhà phát triển Salesforce một ngôn ngữ hướng đối tượng, kiểu dữ liệu mạnh mẽ để thêm logic nghiệp vụ tùy chỉnh vào CRM. Nó hỗ trợ các lớp, trình kích hoạt và các tác vụ xử lý hàng loạt, trong khi các giới hạn quản trị giúp duy trì sự ổn định của nền tảng đa người dùng được chia sẻ.

  • 🧱 Foundation: Apex là một ngôn ngữ không phân biệt chữ hoa chữ thường. Java-Cú pháp tương tự chạy trực tiếp trên nền tảng Salesforce Lightning.
  • 🗃️ Truy cập dữ liệu: Các truy vấn SOQL và câu lệnh DML cho phép mã của bạn đọc và ghi trực tiếp các bản ghi sObject trong cơ sở dữ liệu Salesforce.
  • 🛠️ Thực hiện: Các lớp, thuộc tính và trình kích hoạt gắn logic tùy chỉnh để ghi lại các thao tác thêm, cập nhật, xóa và các sự kiện hệ thống khác.
  • 📦 Tỉ lệ: Batch Apex và các tùy chọn bất đồng bộ khác xử lý hàng triệu bản ghi theo từng khối mà không vượt quá giới hạn của nền tảng.
  • 🚦 Giới hạn của Thống đốc: Các giới hạn cho mỗi giao dịch, chẳng hạn như 100 truy vấn SOQL đồng bộ và 150 câu lệnh DML, giúp bảo vệ các tài nguyên dùng chung.
  • Chất lượng: Các bài kiểm thử đơn vị phải bao phủ ít nhất 75% mã Apex trước khi triển khai vào môi trường sản xuất.

Tổng quan về lập trình APEX Salesforce

Apex trong Salesforce là gì?

Đỉnh Apex là một ngôn ngữ lập trình hướng đối tượng và có kiểu dữ liệu mạnh, được phát triển bởi Salesforce để xây dựng các ứng dụng Phần mềm dưới dạng dịch vụ (SaaS) và Quản lý quan hệ khách hàng (CRM). Apex giúp các nhà phát triển tạo ra các ứng dụng SaaS của bên thứ ba và thêm logic nghiệp vụ vào các sự kiện hệ thống bằng cách cung cấp hỗ trợ cơ sở dữ liệu phía máy chủ và giao diện máy khách-máy chủ.

Apex giúp các nhà phát triển thêm logic nghiệp vụ vào các sự kiện hệ thống như nhấp chuột vào nút, cập nhật bản ghi liên quan và trang Visualforce. Cú pháp của Apex tương tự như... Java. Đăng ký Salesforce để tìm hiểu cách thức hoạt động của hệ thống CRM.

Các tính năng của ngôn ngữ lập trình Apex

Dưới đây là các tính năng quan trọng của Salesforce Apex:

  • Apex là một ngôn ngữ không phân biệt chữ hoa chữ thường.
  • Bạn có thể thực hiện các thao tác DML như INSERT, UPDATE, UPSERT và DELETE trên các bản ghi sObject bằng Apex.
  • Bạn có thể truy vấn các bản ghi sObject bằng SOQL (Ngôn ngữ truy vấn đối tượng Salesforce) và SOSL (Ngôn ngữ tìm kiếm đối tượng Salesforce) trong Apex.
  • Cho phép bạn tạo một kiểm tra đơn vị và thực thi nó để xác minh mã số bảo hiểm và hiệu quả của mã trong Apex.
  • Apex thực thi trong môi trường nhiều người thuê và Salesforce Salesforce đã thiết lập các giới hạn quản trị nhằm ngăn người dùng độc chiếm các tài nguyên dùng chung. Bất kỳ đoạn mã nào vượt quá giới hạn quản trị của Salesforce đều sẽ thất bại và hiển thị lỗi.
  • Một đối tượng Salesforce có thể được sử dụng như một kiểu dữ liệu trong Apex. Ví dụ:
    Account acc = new Account();

    Ở đây, Account là một đối tượng chuẩn của Salesforce.

  • Apex tự động nâng cấp với mỗi bản phát hành Salesforce.

Khi nào nhà phát triển nên chọn Apex?

Chỉ nên viết mã Apex nếu kịch bản nghiệp vụ quá phức tạp để có thể triển khai bằng các chức năng có sẵn, thao tác nhấp chuột đơn giản do Salesforce cung cấp.

Dưới đây là một vài trường hợp bạn cần viết mã Apex:

  • Để tạo các dịch vụ web tích hợp Salesforce với các ứng dụng khác.
  • Để triển khai tính năng xác thực tùy chỉnh trên sObjects.
  • Để thực thi logic Apex tùy chỉnh khi thực hiện thao tác DML.
  • Để triển khai các chức năng không thể xây dựng bằng các công cụ tự động hóa khai báo hiện có như Flow.
  • Để thiết lập dịch vụ email Quá trình này xử lý nội dung, tiêu đề và tệp đính kèm của email đến.

Khi bạn đã biết khi nào Apex là lựa chọn phù hợp, bước tiếp theo là hiểu điều gì xảy ra với mã của bạn sau khi bạn lưu nó.

Cấu trúc hoạt động của Apex

Sau đây là trình tự các thao tác trong mã Apex:

  • Hành động của nhà phát triển: Khi nhà phát triển lưu mã vào nền tảng, toàn bộ mã Apex được biên dịch thành một tập hợp các lệnh mà trình thông dịch thời gian chạy Apex có thể hiểu được, và các lệnh này sau đó được lưu dưới dạng siêu dữ liệu trên nền tảng.
  • Hành động của người dùng cuối: Khi một sự kiện người dùng thực thi mã Apex, máy chủ nền tảng sẽ truy xuất các lệnh đã biên dịch từ siêu dữ liệu và chạy chúng thông qua trình thông dịch Apex trước khi trả về kết quả.

Sơ đồ dưới đây minh họa cách các hành động của nhà phát triển và người dùng cuối tương tác với máy chủ ứng dụng Lightning Platform:

Cơ cấu làm việc của Apex

Môi trường phát triển Apex

Mã Apex có thể được phát triển trong môi trường thử nghiệm (sandbox) hoặc trong môi trường Developer Edition của Salesforce.

Cách tốt nhất là phát triển mã nguồn trong môi trường thử nghiệm (sandbox) rồi mới triển khai lên môi trường sản xuất, như minh họa bên dưới:

Môi trường phát triển Apex

Công cụ phát triển mã Apex: Sau đây là ba công cụ có sẵn để phát triển mã Apex trong tất cả các phiên bản của Salesforce:

  • Ban điêu khiển cải tiên hơn
  • Visual Studio Code Với Gói mở rộng Salesforce (gói này thay thế cho IDE Force.com đã ngừng hoạt động)
  • Code trình chỉnh sửa trong giao diện người dùng Thiết lập Salesforce

Sau khi đã chuẩn bị môi trường, chúng ta hãy cùng xem xét các thành phần cơ bản của ngôn ngữ lập trình, bắt đầu từ các kiểu dữ liệu.

Các kiểu dữ liệu trong Apex

Dưới đây là các kiểu dữ liệu được Apex hỗ trợ:

Ban sơ

Số nguyên, DoubleCác kiểu dữ liệu nguyên thủy như Long, Date, Datetime, Decimal, Time, Blob, String, ID và Boolean được xem là các kiểu dữ liệu cơ bản. Tất cả các kiểu dữ liệu cơ bản đều được truyền theo giá trị, không phải theo tham chiếu.

Các hạng mục

Apex cung cấp ba loại bộ sưu tập khác nhau:

  • Danh sách: Nó là một tập hợp được sắp xếp gồm các phần tử cơ bản, sObject, tập hợp hoặc đối tượng Apex dựa trên chỉ mục.
  • Thiết lập: Một tập hợp các phần tử độc nhất, không được sắp xếp theo thứ tự và không chứa phần tử trùng lặp.
  • Bản đồ: Nó là một tập hợp các khóa duy nhất ánh xạ tới các giá trị đơn lẻ, có thể là các kiểu dữ liệu nguyên thủy, sObject, tập hợp hoặc đối tượng Apex.

sĐối tượng

Đây là loại dữ liệu đặc biệt trong Salesforce. Nó tương tự như một bảng trong SQL và chứa các trường tương tự như các cột trong SQL.

liệt kê

Enum là một kiểu dữ liệu tuyệt đối.tracKiểu dữ liệu t lưu trữ một giá trị trong một tập hợp hữu hạn các định danh được chỉ định.

Lớp, Đối tượng và Giao diện

Các lớp và giao diện Apex do người dùng định nghĩa cũng có thể được sử dụng làm kiểu dữ liệu. Một đối tượng đề cập đến một thể hiện của bất kỳ kiểu dữ liệu nào được hỗ trợ trong Apex.

Cú pháp đỉnh

Sự định nghĩa biến

Vì Apex là một ngôn ngữ có kiểu dữ liệu mạnh, nên việc khai báo kiểu dữ liệu cho biến là bắt buộc trong Apex.

Ví dụ:

Contact con = new Contact();

Ở đây, biến con được khai báo với kiểu dữ liệu là Contact.

Truy vấn SOQL

SOQL là viết tắt của Salesforce Object Query Language (Ngôn ngữ truy vấn đối tượng Salesforce). SOQL được sử dụng để truy xuất các bản ghi sObject từ cơ sở dữ liệu Salesforce. Ví dụ:

Account acc = [SELECT Id, Name FROM Account LIMIT 1];

Truy vấn trên lấy một bản ghi tài khoản từ cơ sở dữ liệu Salesforce.

Tuyên bố vòng lặp

Câu lệnh vòng lặp được sử dụng để lặp qua các bản ghi trong một danh sách. Số lần lặp bằng với số bản ghi trong danh sách. Ví dụ:

List<Account> listOfAccounts = [SELECT Id, Name FROM Account LIMIT 100];
// iteration over the list of accounts
for(Account acc : listOfAccounts){
	//your logic
}

Trong đoạn mã trên, listOfAccounts là một biến thuộc kiểu dữ liệu List.

Tuyên bố kiểm soát luồng

Câu lệnh điều khiển luồng rất hữu ích khi bạn muốn thực thi một số dòng mã dựa trên các điều kiện nhất định.

Ví dụ:

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
}

Đoạn mã trên truy vấn các bản ghi tài khoản từ cơ sở dữ liệu và kiểm tra kích thước của danh sách.

Tuyên bố DML

DML là viết tắt của Data Manipulation Language (Ngôn ngữ thao tác dữ liệu). Các câu lệnh DML được sử dụng để thao tác dữ liệu trong cơ sở dữ liệu Salesforce. Ví dụ:

Account acc = new Account(Name = 'Test Account');
insert acc; //DML statement to create account record.

Bộ chỉ định truy cập Apex

Sau đây là các bộ chỉ định quyền truy cập được Apex hỗ trợ:

Public

Bộ chỉ định quyền truy cập này cho phép Apex sử dụng một lớp, phương thức hoặc biến trong một không gian tên cụ thể.

Riêng

Bộ chỉ định quyền truy cập này cho phép truy cập vào một lớp, phương thức hoặc biến để sử dụng cục bộ, hoặc trong phần mã nơi nó được định nghĩa. Tất cả các phương thức và biến không có bộ chỉ định quyền truy cập được định nghĩa sẽ sử dụng bộ chỉ định quyền truy cập mặc định là private.

bảo vệ

Bộ chỉ định quyền truy cập này cho phép truy cập vào một phương thức hoặc biến được sử dụng bởi bất kỳ lớp con nào trong lớp Apex định nghĩa nó.

Toàn cầu

Bộ chỉ định quyền truy cập này cho phép Apex truy cập vào một lớp, phương thức hoặc biến trong cùng một không gian tên cũng như bên ngoài không gian tên đó. Tốt nhất là không nên sử dụng từ khóa global trừ khi thực sự cần thiết.

Từ khóa trong Apex

Với sự chia sẻ

Nếu một lớp được định nghĩa với từ khóa này, thì tất cả các quy tắc chia sẻ áp dụng cho người dùng hiện tại sẽ được thực thi. Nếu không có từ khóa này, mã sẽ được thực thi trong ngữ cảnh hệ thống.

Ví dụ:

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

Không chia sẻ

Nếu một lớp được định nghĩa với từ khóa này, thì các quy tắc chia sẻ áp dụng cho người dùng hiện tại sẽ không được thực thi.

Ví dụ:

public without sharing class MyApexClass{
// sharing rules are not enforced when code in this class executes
}

tĩnh

Biến hoặc phương thức được định nghĩa bằng từ khóa `static` chỉ được khởi tạo một lần và liên kết với lớp. Các biến và phương thức `static` có thể được gọi trực tiếp bằng tên lớp mà không cần tạo một thể hiện của lớp đó.

Cuối cùng

Hằng số hoặc phương thức được định nghĩa bằng từ khóa final không thể bị ghi đè. Ví dụ:

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

Nếu bạn cố gắng ghi đè giá trị của biến INT_CONST này, bạn sẽ gặp lỗi ngoại lệ – System.FinalException: Biến final đã được khởi tạo.

Trả hàng

Từ khóa này trả về một giá trị từ một phương thức. Ví dụ:

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

Null

Nó định nghĩa một hằng số rỗng và có thể được gán cho một biến. Ví dụ:

Boolean b = null;

ảo

Nếu một lớp được định nghĩa bằng từ khóa virtual, nó có thể được kế thừa và ghi đè.

Abstract

Nếu một lớp được định nghĩa với abstracTừ khóa t phải chứa ít nhất một phương thức có từ khóa abs.tracvà phương pháp đó chỉ nên có chữ ký.

Ví dụ:

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

Chuỗi đỉnh

Chuỗi ký tự là một tập hợp các ký tự không giới hạn số lượng ký tự. Ví dụ:

String name = 'Test';

Lớp String trong Salesforce cung cấp một số phương thức tích hợp sẵn. Sau đây là một vài phương thức thường được sử dụng:

viết tắt(maxWidth)

Phương thức này cắt ngắn chuỗi đến độ dài được chỉ định và trả về chuỗi đã cắt nếu độ dài của chuỗi được cung cấp dài hơn độ dài được chỉ định; ngược lại, nó trả về chuỗi gốc. Nếu giá trị của biến maxWidth nhỏ hơn 4, phương thức này sẽ ném ra một ngoại lệ khi chạy – System.StringException: Minimum abbreviation width is 4.

Ví dụ:

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

viết hoa ()

Phương thức này chuyển đổi chữ cái đầu tiên của chuỗi thành kiểu chữ tiêu đề và trả về nó.

Ví dụ:

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

chứa (chuỗi con)

Phương thức này trả về true nếu chuỗi gọi phương thức chứa chuỗi con được chỉ định.

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

bằng(stringOrId)

Phương thức này trả về true nếu tham số được truyền vào không phải là null và biểu diễn cùng một chuỗi ký tự nhị phân với chuỗi gọi phương thức.

Khi so sánh các giá trị ID, độ dài của các ID có thể không bằng nhau. Ví dụ, nếu một chuỗi biểu thị ID 15 ký tự được so sánh với một đối tượng biểu thị ID 18 ký tự, phương thức này vẫn trả về true. Ví dụ:

String stringValue15 = '001D000000Ju1zH';
Id idValue18 = '001D000000Ju1zHIAR';
Boolean result = stringValue15.equals(idValue18);
System.debug('result: ' + result); //true

Trong ví dụ trên, phương thức equals so sánh một ID đối tượng gồm 15 ký tự với một ID đối tượng gồm 18 ký tự, và nếu cả hai ID đều đại diện cho cùng một chuỗi nhị phân, nó sẽ trả về true.

Sử dụng phương pháp này để thực hiện so sánh phân biệt chữ hoa chữ thường.

escapeSingleQuotes(stringToEscape)

Phương pháp này thêm ký tự thoát (\) trước bất kỳ dấu ngoặc đơn nào trong chuỗi và trả về kết quả. Phương pháp này ngăn chặn tấn công SOQL injection khi tạo truy vấn SOQL động. Nó đảm bảo rằng tất cả các dấu ngoặc đơn được coi là chuỗi bao quanh thay vì lệnh cơ sở dữ liệu.

Ví dụ:

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

xóa (chuỗi con)

Phương pháp này loại bỏ tất cả các lần xuất hiện của chuỗi con được đề cập khỏi chuỗi gọi phương thức và trả về chuỗi kết quả.

Ví dụ:

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

chuỗi con (startIndex)

Phương thức này trả về một chuỗi con bắt đầu từ ký tự tại startIndex và kéo dài đến cuối chuỗi.

Ví dụ:

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

đảo ngược()

Phương thức này đảo ngược tất cả các ký tự của một chuỗi và trả về chuỗi đó. Ví dụ:

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

trim ()

Phương pháp này loại bỏ tất cả các khoảng trắng ở đầu và cuối chuỗi rồi trả về chuỗi đó.

valueOf(toConvert)

Phương thức này trả về chuỗi biểu diễn của đối tượng được truyền vào.

Chuỗi ký tự, lớp và từ khóa kết hợp với nhau khi bạn bắt đầu đóng gói logic thành các đơn vị có thể tái sử dụng, và đó chính xác là mục đích của các lớp trong Apex.

Lớp đỉnh cao

Lớp Apex là một bản thiết kế hoặc khuôn mẫu mà từ đó các đối tượng được tạo ra. Một đối tượng là một thể hiện của lớp.

Có ba cách để tạo các lớp Apex trong Salesforce:

  • Ban điêu khiển cải tiên hơn
  • Visual Studio Code với Gói mở rộng Salesforce
  • Trang chi tiết lớp Apex trong phần Thiết lập

Trong Apex, bạn có thể định nghĩa một lớp bên ngoài, còn được gọi là lớp cấp cao nhất, và bạn cũng có thể định nghĩa các lớp bên trong một lớp bên ngoài, được gọi là các lớp bên trong.

Việc sử dụng từ khóa chỉ định quyền truy cập như global hoặc public trong khai báo lớp bên ngoài là bắt buộc.

Không cần thiết phải sử dụng công cụ sửa đổi quyền truy cập trong khai báo các lớp bên trong.

Một lớp Apex được định nghĩa bằng cách sử dụng từ khóa `class` theo sau là tên lớp.

Từ khóa `extends` được sử dụng để mở rộng một lớp hiện có trong một lớp Apex, còn từ khóa `implements` được sử dụng để triển khai một giao diện trong một lớp Apex.

Salesforce Apex không hỗ trợ đa kế thừa; một lớp Apex chỉ có thể kế thừa từ một lớp Apex hiện có nhưng có thể triển khai nhiều giao diện.

Một lớp Apex có thể chứa một hàm tạo do người dùng định nghĩa, và nếu không có hàm tạo do người dùng định nghĩa, một hàm tạo mặc định sẽ được sử dụng. Mã trong hàm tạo sẽ được thực thi khi một thể hiện của lớp được tạo ra.

Cú pháp của một lớp Apex:

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

Từ khóa `new` được sử dụng để tạo một thể hiện của lớp Apex. Dưới đây là cú pháp để tạo một thể hiện của lớp Apex:

myApexClass obj = new myApexClass();

Apex Getter và Setter

Thuộc tính trong Apex tương tự như biến trong Apex. Một phương thức getter và setter là cần thiết cho một thuộc tính trong Apex. Chúng có thể được sử dụng để thực thi mã trước khi giá trị của thuộc tính được truy cập hoặc thay đổi. Mã trong phương thức getter được thực thi khi giá trị của thuộc tính được đọc. Mã trong phương thức setter được thực thi khi giá trị của thuộc tính được thay đổi. Bất kỳ thuộc tính nào chỉ có phương thức getter được coi là chỉ đọc, bất kỳ thuộc tính nào chỉ có phương thức setter được coi là chỉ ghi, và bất kỳ thuộc tính nào có cả phương thức getter và setter được coi là đọc-ghi. Cú pháp của một thuộc tính trong Apex:

public class myApexClass {
// Property declaration
	access_modifier return_type property_name {
	get {
			//code
		}
		set{
			//code
		}
	}
}

Ở đây, access_modifier là bộ điều chỉnh quyền truy cập của thuộc tính, return_type là kiểu dữ liệu của thuộc tính, và property_name là tên của thuộc tính.

Dưới đây là một ví dụ về thuộc tính Apex có cả phương thức truy cập get và set:

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

Ở đây, tên thuộc tính là name, nó là một thuộc tính công khai và trả về kiểu dữ liệu String.

Không bắt buộc phải có mã trong các khối get và set. Các khối này có thể để trống để định nghĩa một thuộc tính tự động. Ví dụ:

public double MyReadWriteProp{ get; set; }

Các phương thức truy cập get và set cũng có thể được định nghĩa với các bổ ngữ truy cập riêng. Nếu một phương thức truy cập được định nghĩa với một bổ ngữ, nó sẽ ghi đè lên bổ ngữ truy cập của thuộc tính. Ví dụ:

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

Các lớp định nghĩa logic có thể tái sử dụng mà bạn gọi một cách rõ ràng. Các trình kích hoạt, sẽ được đề cập tiếp theo, sẽ tự động chạy bất cứ khi nào bản ghi thay đổi.

Kích hoạt đỉnh

Trigger Apex cho phép bạn thực thi mã Apex tùy chỉnh trước và sau khi thao tác DML được thực hiện.

Apex hỗ trợ hai loại trình kích hoạt sau:

Trước khi kích hoạt: Các trình kích hoạt này được sử dụng để xác thực và cập nhật giá trị của một trường trước khi bản ghi được lưu vào cơ sở dữ liệu.

Sau khi kích hoạt: Các trình kích hoạt này được sử dụng để truy cập các giá trị trường (chẳng hạn như ID bản ghi và trường LastModifiedDate) được hệ thống thiết lập sau khi bản ghi được lưu vào cơ sở dữ liệu. Các giá trị trường này có thể được sử dụng để sửa đổi các bản ghi khác. Các bản ghi được kích hoạt sau trình kích hoạt chỉ có thể đọc.

Viết trigger xử lý hàng loạt là một phương pháp tối ưu. Trigger xử lý hàng loạt có thể xử lý một bản ghi hoặc nhiều bản ghi cùng một lúc.

Cú pháp của một trigger Apex:

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

Ở đây, TriggerName là tên của trình kích hoạt, ObjectName là tên của đối tượng mà trình kích hoạt được ghi vào, và trigger_events là một danh sách các sự kiện được phân tách bằng dấu phẩy.

Sau đây là các sự kiện được hỗ trợ bởi trigger Apex: trước khi chèn, trước khi cập nhật, trước khi xóa, sau khi chèn, sau khi cập nhật, sau khi xóa, sau khi khôi phục.

Từ khóa tĩnh không thể được sử dụng trong trigger Apex. Tất cả các từ khóa áp dụng cho các lớp bên trong đều có thể được sử dụng trong trigger Apex.

Mỗi trigger đều định nghĩa các biến ngầm định trả về ngữ cảnh thời gian chạy. Các biến này được định nghĩa trong lớp System.Trigger và được gọi là biến ngữ cảnh. Hai ảnh chụp màn hình bên dưới liệt kê các biến ngữ cảnh được hỗ trợ bởi các trigger Apex:

Biến ngữ cảnh kích hoạt Apex

Biến ngữ cảnh kích hoạt Apex (Tiếp theo)

Sau đây là những điểm cần xem xét đối với các biến ngữ cảnh trong trình kích hoạt Apex:

  • Không sử dụng trigger.new và trigger.old trong các thao tác DML.
  • Không thể xóa Trigger.new.
  • Biến Trigger.new chỉ có thể đọc được trong các trigger sau.
  • Trigger.new chỉ có thể được sử dụng để thay đổi giá trị của các trường trên cùng một đối tượng trong các trigger trước đó.

Hai ảnh chụp màn hình bên dưới liệt kê những điểm cần cân nhắc về các hành động cụ thể trong các sự kiện kích hoạt khác nhau:

Các yếu tố cần xem xét khi kích hoạt sự kiện Apex

Các yếu tố cần xem xét khi kích hoạt sự kiện Apex (Tiếp theo)

Trigger xử lý logic thời gian thực, nhưng một số tác vụ quá lớn đối với một giao dịch đơn lẻ. Đó là lúc Apex xử lý theo lô phát huy tác dụng.

Lớp hàng loạt trong Apex

Trong Salesforce, lớp xử lý hàng loạt (batch class) được sử dụng để xử lý một lượng lớn bản ghi mà nếu xử lý thông thường sẽ vượt quá giới hạn của Apex governor. Lớp xử lý hàng loạt thực thi mã một cách bất đồng bộ.

Sau đây là những ưu điểm của lớp học theo lô:

  • Lớp xử lý theo lô (batch class) xử lý dữ liệu theo từng khối, và nếu một khối nào đó không được xử lý thành công, các khối đã được xử lý thành công sẽ không bị hoàn tác.
  • Mỗi khối dữ liệu trong một lớp xử lý theo lô được xử lý với một tập hợp các giới hạn điều khiển mới, đảm bảo rằng mã được thực thi trong giới hạn thực thi của trình điều khiển.

Giao diện Database.Batchable phải được một lớp Apex triển khai để có thể được sử dụng như một lớp xử lý hàng loạt. Nó cung cấp ba phương thức mà lớp xử lý hàng loạt phải triển khai:

1. bắt đầu()

Phương thức này tạo ra phạm vi các bản ghi hoặc đối tượng sẽ được xử lý bởi phương thức giao diện execute. Nó chỉ được gọi một lần trong suốt quá trình thực thi hàng loạt. Phương thức này trả về một đối tượng Database.QueryLocator hoặc một Iterable. Số lượng bản ghi có thể được truy xuất bằng truy vấn SOQL sử dụng đối tượng Database.QueryLocator là 50 triệu, nhưng khi sử dụng Iterable, tổng số bản ghi có thể được truy xuất bằng truy vấn SOQL chỉ là 50,000. Một Iterable được sử dụng để tạo ra một phạm vi phức tạp cho lớp xử lý hàng loạt.

Cú pháp của phương thức bắt đầu:

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

2. thực thi()

Phương pháp này được sử dụng để xử lý từng khối dữ liệu. Phương thức execute được gọi cho mỗi khối bản ghi. Kích thước lô mặc định để thực thi là 200 bản ghi. Phương thức execute nhận hai đối số:

Một tham chiếu đến đối tượng Database.BatchableContext,

Một danh sách các sObject, chẳng hạn như List hoặc một danh sách các kiểu tham số. Cú pháp của phương thức execute:

global void execute(Database.BatchableContext bc, List<P> records){}

3. finish()

Phương thức `finish` được gọi một lần trong quá trình thực thi lớp xử lý hàng loạt. Các thao tác xử lý sau có thể được thực hiện trong phương thức `finish`. Ví dụ: gửi email xác nhận. Phương thức này được gọi khi tất cả các lô xử lý đã được xử lý xong. Cú pháp của phương thức `finish`:

global void finish(Database.BatchableContext bc){}

Đối tượng Database.BatchableContext

Mỗi phương thức của giao diện Database.Batchable đều có một tham chiếu đến đối tượng Database.BatchableContext.

Vật thể này được sử dụng để track tiến độ của công việc xử lý theo lô.

Sau đây là các phương thức thể hiện được cung cấp bởi BatchableContext:

  • getChildJobId(): Phương thức này trả về ID của công việc xử lý theo lô hiện đang được thực thi.
  • getJobId(): Phương thức này trả về ID của batch job.

Dưới đây là cú pháp của một lớp xử lý hàng loạt:

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

Phương thức Database.executeBatch

Phương thức Database.executeBatch được sử dụng để thực thi một lớp xử lý hàng loạt.

Phương thức này nhận hai tham số: một thể hiện của lớp xử lý theo lô và một tham số phạm vi tùy chọn để chỉ định kích thước lô. Nếu không được chỉ định, kích thước mặc định là 200 sẽ được sử dụng.

Cú pháp của Database.executeBatch:

Database.executeBatch(myBatchObject, scope)

Thực thi một lớp xử lý hàng loạt có tên MyBatchClass:

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

Cơ sở dữ liệu. Có trạng thái

Theo mặc định, lớp xử lý theo lô (batch class) không có trạng thái. Mỗi khi phương thức execute được gọi, một bản sao mới của đối tượng sẽ được nhận và tất cả các biến của lớp đều được khởi tạo.

Database.Stateful được triển khai để làm cho một lớp xử lý hàng loạt có trạng thái.

Nếu lớp xử lý hàng loạt của bạn triển khai Cơ sở dữ liệuGiao diện có trạng thái (stateful interface), tất cả các biến thể hiện (instance variables) giữ nguyên giá trị của chúng, nhưng các biến tĩnh (static variables) sẽ được đặt lại về 0 giữa các giao dịch.

Apex bất đồng bộ vượt ra ngoài phạm vi xử lý hàng loạt

Batch Apex chỉ là một trong số nhiều cách để chạy mã bất đồng bộ. Salesforce cung cấp bốn tùy chọn bất đồng bộ, và việc chọn tùy chọn phù hợp phụ thuộc vào lượng dữ liệu bạn xử lý và liệu các tác vụ cần được xâu chuỗi hoặc lên lịch hay không.

  • Các phương pháp trong tương lai: Khi được chú thích bằng @future, chúng phù hợp nhất cho các thao tác đơn giản, "thực hiện một lần và quên" như gọi đến các dịch vụ web bên ngoài.
  • Apex có thể xếp hàng: Lớp này triển khai giao diện Queueable, chấp nhận các kiểu đối tượng phức tạp, trả về ID công việc và hỗ trợ liên kết nhiều công việc với nhau.
  • Batch Apex: Xử lý khối lượng dữ liệu rất lớn theo từng phần, như đã mô tả ở trên.
  • Apex đã lên lịch: Thực thi giao diện Schedulable để một lớp chạy vào một thời điểm cụ thể, chẳng hạn như công việc dọn dẹp hàng đêm.
Kiểu tốt nhất cho Khả năng chính
Phương pháp tương lai Chú thích đơn giản Bắn một phát rồi quên đi.
Apex có thể xếp hàng Xử lý tuần tự Chuỗi công việc và giám sát
Apex hàng loạt Hàng triệu bản ghi Xử lý theo khối
Apex theo lịch trình Công việc định kỳ Định thời gian dựa trên Cron

Bất kể bạn chọn mô hình thực thi nào, mọi giao dịch vẫn được đo lường dựa trên các giới hạn quản trị toàn nền tảng được liệt kê bên dưới.

Giới hạn thống đốc Apex

Các giới hạn quản trị Apex là các giới hạn được công cụ thời gian chạy Apex thực thi để đảm bảo rằng bất kỳ mã và quy trình Apex nào vượt quá giới hạn đều không chiếm dụng các tài nguyên được chia sẻ và không làm gián đoạn quá trình xử lý của người dùng khác trong môi trường đa người thuê. Các giới hạn này được xác minh đối với mỗi giao dịch Apex. Sau đây là các giới hạn quản trị được Salesforce định nghĩa trên mỗi giao dịch Apex:

Mô tả Chi tiết Giới Hạn
Các truy vấn SOQL có thể được thực hiện trong một giao dịch đồng bộ 100
Các truy vấn SOQL có thể được thực hiện trong một giao dịch bất đồng bộ. 200
Các bản ghi có thể được truy xuất bằng truy vấn SOQL 50,000
Các bản ghi có thể được truy xuất bởi Database.getQueryLocator 10,000
Các truy vấn SOSL có thể được thực hiện trong một giao dịch Apex. 20
Các bản ghi có thể được truy xuất bằng truy vấn SOSL 2,000
Các câu lệnh DML có thể được thực hiện trong một giao dịch Apex 150
Các bản ghi có thể được xử lý nhờ câu lệnh DML, Approval.process hoặc cơ sở dữ liệu.emptyRecycleBin 10,000
Các lệnh gọi hàm có thể được thực hiện trong giao dịch Apex. 100
Giới hạn thời gian chờ tích lũy trên tất cả các lệnh gọi đang được thực hiện trong một giao dịch Apex. 120 giây
Giới hạn số lượng công việc Apex có thể được thêm vào hàng đợi bằng System.enqueueJob 50
Giới hạn thời gian thực hiện cho mỗi giao dịch Apex 10 phút
Giới hạn số ký tự có thể được sử dụng trong một lớp Apex và trình kích hoạt. 1 triệu
Giới hạn thời gian CPU cho một giao dịch đồng bộ 10,000 mili giây
Giới hạn thời gian CPU cho một giao dịch bất đồng bộ 60,000 mili giây
Tổng kích thước heap 6 MB (đồng bộ) / 12 MB (không đồng bộ)

Cách viết lớp kiểm thử trong Apex

Salesforce yêu cầu ít nhất 75% mã Apex của bạn phải được kiểm thử đơn vị trước khi bạn có thể triển khai lên môi trường sản xuất, và mỗi trigger phải có một số mức độ kiểm thử nhất định. Do đó, viết các lớp kiểm thử là một kỹ năng cốt lõi của Apex, chứ không phải là một kỹ năng tùy chọn.

Lớp kiểm thử được chú thích bằng `@isTest`, và mỗi phương thức kiểm thử cũng được đánh dấu bằng `@isTest`. Các phương thức kiểm thử không ghi dữ liệu vào cơ sở dữ liệu và không truy cập hầu hết dữ liệu hiện có của tổ chức, vì vậy mỗi bài kiểm thử tạo ra các bản ghi riêng của nó. Các phương thức `Test.startTest()` và `Test.stopTest()` cung cấp cho mã cần kiểm thử một tập hợp các giới hạn quản trị mới, và các câu lệnh khẳng định xác minh rằng logic hoạt động như mong đợi.

Đây là một lớp kiểm thử đơn giản cho logic tạo tài khoản:

@isTest
private class AccountHandlerTest {
    @isTest
    static void testCreateAccount() {
        Account acc = new Account(Name = 'Test Account');
        Test.startTest();
        insert acc;
        Test.stopTest();
        Account result = [SELECT Id, Name FROM Account WHERE Id = :acc.Id];
        System.assertEquals('Test Account', result.Name);
    }
}

Hãy tuân thủ các hướng dẫn sau khi viết bài kiểm tra:

  • Sử dụng phương thức `@testSetup` để tạo dữ liệu kiểm thử dùng chung một lần cho tất cả các phương thức kiểm thử trong lớp.
  • Kiểm tra hành vi xử lý hàng loạt bằng cách chèn 200 bản ghi, chứ không chỉ một bản ghi.
  • Bao gồm các trường hợp tích cực, tiêu cực và hạn chế người dùng.
  • Luôn luôn bao gồm các câu lệnh System.assert có ý nghĩa; việc kiểm tra độ bao phủ mã mà không có các câu lệnh khẳng định thì không chứng minh được điều gì.

Các phương pháp thực hành tốt nhất của Apex

Người mới bắt đầu thường viết mã Apex hoạt động tốt với một bản ghi nhưng lại thất bại trong các thao tác xử lý hàng loạt thực tế. Các phương pháp dưới đây giúp mã của bạn tuân thủ giới hạn của hệ thống và dễ bảo trì hơn:

  • Thu nhỏ mọi thứ thành số lượng lớn: Hãy viết logic xử lý các tập hợp bản ghi, vì trình kích hoạt có thể nhận tối đa 200 bản ghi trong một lần xử lý.
  • Tránh sử dụng SOQL và DML trong vòng lặp: Truy vấn trước vòng lặp, thu thập các thay đổi vào một danh sách và thực hiện một câu lệnh DML sau vòng lặp.
  • Một trình kích hoạt cho mỗi đối tượng: Hãy giữ cho các trình kích hoạt không chứa logic và giao phó công việc cho các lớp xử lý, điều này giúp cho thứ tự thực thi trở nên dễ dự đoán hơn.
  • Sử dụng khi chia sẻ: Áp dụng bảo mật ở cấp độ bản ghi trừ khi có lý do được ghi lại để chạy trong ngữ cảnh hệ thống.
  • Tránh mã hóa cứng ID: Mã định danh bản ghi (Record ID) khác nhau giữa môi trường thử nghiệm và môi trường sản xuất, vì vậy hãy truy vấn chúng hoặc sử dụng Siêu dữ liệu tùy chỉnh (Custom Metadata) thay thế.
  • Giám sát các giới hạn trong mã: Các phương thức của lớp Limits, chẳng hạn như Limits.getQueries(), cho phép bạn kiểm tra mức tiêu thụ tài nguyên trong quá trình chạy.

💡 Mẹo: Hãy chạy mã của bạn với 200 bản ghi trong môi trường thử nghiệm trước khi triển khai. Hầu hết các lỗi giới hạn của trình quản lý chỉ xuất hiện khi xử lý khối lượng lớn, và việc phát hiện sớm chúng sẽ tiết kiệm chi phí hơn nhiều so với việc gỡ lỗi trong môi trường sản xuất.

Câu Hỏi Thường Gặp

Không. Apex mượn JavaCú pháp tương tự, nhưng không phân biệt chữ hoa chữ thường, chỉ chạy trên Nền tảng Salesforce Lightning, tích hợp trực tiếp SOQL vào ngôn ngữ và bị giới hạn bởi các quy tắc cho mỗi giao dịch. Java không có.

Đăng ký tài khoản Salesforce Developer Edition miễn phí, bao gồm Developer Console, và thực hiện các bài tập thực hành trên trang web. Đường mòn, nền tảng học tập chính thức từ Salesforce.

Visualforce là ngôn ngữ đánh dấu dùng để xây dựng các trang giao diện người dùng, trong khi Apex là ngôn ngữ phía máy chủ cung cấp logic xử lý cho chúng. Các trang Visualforce thường gọi các lớp điều khiển Apex để truy vấn và cập nhật dữ liệu.

Vâng. Agentforce dành cho nhà phát triển, trợ lý AI từ Salesforce dành cho Visual Studio CodeCông cụ này tạo và giải thích mã Apex từ các lời nhắc bằng ngôn ngữ tự nhiên. Luôn xem xét và kiểm tra mã do AI tạo ra so với các giới hạn của trình quản lý trước khi triển khai.

Các lớp Apex được đánh dấu bằng chú thích @InvocableMethod có thể được hiển thị dưới dạng các hành động tùy chỉnh, cho phép các bot Einstein và các tác nhân Agentforce gọi logic nghiệp vụ của bạn, đồng thời Apex cũng có thể gọi các mẫu lời nhắc Einstein và các mô hình AI thông qua API của nền tảng.

Tóm tắt bài viết này với: