Apex - Hướng dẫn nhanh

Apex là gì?

Apex là một ngôn ngữ độc quyền được phát triển bởi Salesforce.com. Theo định nghĩa chính thức, Apex là một ngôn ngữ lập trình hướng đối tượng, được đánh máy mạnh mẽ, cho phép các nhà phát triển thực thi các câu lệnh kiểm soát luồng và giao dịch trên máy chủ nền tảng Force.com cùng với các lệnh gọi tới API Force.com.

Nó có cú pháp giống Java và hoạt động giống như các thủ tục được lưu trữ trong cơ sở dữ liệu. Nó cho phép các nhà phát triển thêm logic nghiệp vụ vào hầu hết các sự kiện hệ thống, bao gồm các lần nhấp vào nút, cập nhật hồ sơ liên quan và Visualforcepages.Apexmã có thể được khởi tạo bởi các yêu cầu dịch vụ Web và từ các trình kích hoạt trên các đối tượng. Apex có trong phiên bản Performance Edition, Unlimited Edition, Enterprise Edition và Developer Edition.

Các tính năng của Apex như một ngôn ngữ

Bây giờ chúng ta hãy thảo luận về các tính năng của Apex như một ngôn ngữ -

Tích hợp

Apex đã tích hợp sẵn hỗ trợ cho các hoạt động DML như INSERT, UPDATE, DELETE và cả xử lý DML Exception. Nó có hỗ trợ xử lý truy vấn SOQL và SOSL nội tuyến trả về tập hợp các bản ghi sObject. Chúng ta sẽ nghiên cứu chi tiết về sObject, SOQL, SOSL trong các chương sau.

Java giống cú pháp và dễ sử dụng

Apex rất dễ sử dụng vì nó sử dụng cú pháp giống như Java. Ví dụ, khai báo biến, cú pháp vòng lặp và câu lệnh điều kiện.

Tích hợp mạnh mẽ với dữ liệu

Apex là tập trung vào dữ liệu và được thiết kế để thực thi nhiều truy vấn và câu lệnh DML cùng nhau. Nó đưa ra nhiều câu lệnh giao dịch trên Cơ sở dữ liệu.

Đã gõ mạnh

Apex là một ngôn ngữ được đánh máy mạnh. Nó sử dụng tham chiếu trực tiếp đến các đối tượng lược đồ như sObject và mọi tham chiếu không hợp lệ sẽ nhanh chóng bị lỗi nếu nó bị xóa hoặc nếu có kiểu dữ liệu sai.

Môi trường nhiều người

Apex chạy trong môi trường nhiều đối tượng. Do đó, công cụ thời gian chạy Apex được thiết kế để bảo vệ chặt chẽ chống lại mã chạy trốn, ngăn nó độc quyền tài nguyên được chia sẻ. Bất kỳ mã nào vi phạm giới hạn đều không thành công với các thông báo lỗi dễ hiểu.

Tự động nâng cấp

Apex được nâng cấp như một phần của bản phát hành Salesforce. Chúng tôi không phải nâng cấp nó theo cách thủ công.

Kiểm tra dễ dàng

Apex cung cấp hỗ trợ tích hợp để tạo và thực thi đơn vị kiểm tra, bao gồm kết quả kiểm tra cho biết lượng mã được bao phủ và phần nào trong mã của bạn có thể hiệu quả hơn.

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

Apex nên được sử dụng khi chúng tôi không thể triển khai chức năng nghiệp vụ phức tạp bằng cách sử dụng các chức năng sẵn có và sẵn có. Dưới đây là các trường hợp chúng ta cần sử dụng apex trên cấu hình Salesforce.

Ứng dụng Apex

Chúng ta có thể sử dụng Apex khi chúng ta muốn -

  • Tạo các dịch vụ Web với việc tích hợp các hệ thống khác.

  • Tạo dịch vụ email cho vụ nổ email hoặc thiết lập email.

  • Thực hiện xác thực phức tạp trên nhiều đối tượng cùng một lúc và cả triển khai xác thực tùy chỉnh.

  • Tạo các quy trình kinh doanh phức tạp không được hỗ trợ bởi chức năng hoặc luồng công việc hiện có.

  • Tạo logic giao dịch tùy chỉnh (logic xảy ra trên toàn bộ giao dịch, không chỉ với một bản ghi hoặc đối tượng duy nhất) giống như sử dụng các phương thức Cơ sở dữ liệu để cập nhật bản ghi.

  • Thực hiện một số logic khi một bản ghi được sửa đổi hoặc sửa đổi bản ghi của đối tượng liên quan khi có một số sự kiện khiến trình kích hoạt kích hoạt.

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

Như được hiển thị trong sơ đồ bên dưới (Tham khảo: Tài liệu dành cho nhà phát triển Salesforce), Apex chạy hoàn toàn trên Nền tảng Force.com theo yêu cầu

Luồng hành động

Có hai chuỗi hành động khi nhà phát triển lưu mã và khi người dùng cuối thực hiện một số hành động gọi mã Apex như hình dưới đây:

Hành động của nhà phát triển

Khi nhà phát triển viết và lưu mã Apex vào nền tảng, trước tiên máy chủ ứng dụng nền tảng sẽ biên dịch mã thành một tập hợp các hướng dẫn mà trình thông dịch thời gian chạy Apex có thể hiểu được, sau đó lưu các hướng dẫn đó dưới dạng siêu dữ liệu.

Hành động của người dùng cuối

Khi người dùng cuối kích hoạt thực thi Apex, bằng cách nhấp vào nút hoặc truy cập trang Visualforce, máy chủ ứng dụng nền tảng sẽ truy xuất các hướng dẫn đã biên dịch từ siêu dữ liệu và gửi chúng qua trình thông dịch thời gian chạy trước khi trả về kết quả. Người dùng cuối không nhận thấy sự khác biệt nào về thời gian thực hiện so với yêu cầu nền tảng ứng dụng tiêu chuẩn.

Vì Apex là ngôn ngữ độc quyền của Salesforce.com, nên nó không hỗ trợ một số tính năng mà ngôn ngữ lập trình thông thường có. Sau đây là một số tính năng mà Apex không hỗ trợ:

  • Nó không thể hiển thị các phần tử trong Giao diện người dùng.

  • Bạn không thể thay đổi chức năng tiêu chuẩn được cung cấp bởi SFDC và cũng không thể ngăn việc thực thi chức năng tiêu chuẩn.

  • Việc tạo nhiều luồng cũng không thể thực hiện được vì chúng ta có thể thực hiện bằng các ngôn ngữ khác.

Hiểu cú pháp Apex

Mã Apex thường chứa nhiều thứ mà chúng ta có thể quen thuộc với các ngôn ngữ lập trình khác.

Sự định nghĩa biến

Là ngôn ngữ được gõ mạnh, bạn phải khai báo mọi biến có kiểu dữ liệu trong Apex. Như đã thấy trong đoạn mã bên dưới (ảnh chụp màn hình bên dưới), lstAcc được khai báo với kiểu dữ liệu là Danh sách tài khoản.

Truy vấn SOQL

Điều này sẽ được sử dụng để tìm nạp dữ liệu từ cơ sở dữ liệu Salesforce. Truy vấn hiển thị trong ảnh chụp màn hình bên dưới đang tìm nạp dữ liệu từ đối tượng Tài khoản.

Tuyên bố vòng lặp

Câu lệnh lặp này được sử dụng để lặp qua một danh sách hoặc lặp qua một đoạn mã trong một số lần xác định. Trong đoạn mã được hiển thị trong ảnh chụp màn hình bên dưới, số lần lặp sẽ giống như số lượng bản ghi mà chúng tôi có.

Tuyên bố kiểm soát dòng chảy

Câu lệnh If được sử dụng để điều khiển luồng trong đoạn mã này. Dựa trên một số điều kiện nhất định, nó được quyết định xem nên thực thi hay dừng việc thực thi đoạn mã cụ thể. Ví dụ, trong đoạn mã được hiển thị bên dưới, nó đang kiểm tra xem danh sách trống hay nó chứa các bản ghi.

Tuyên bố DML

Thực hiện thao tác chèn, cập nhật, nâng cấp, xóa bản ghi trên các bản ghi trong cơ sở dữ liệu. Ví dụ: mã được cung cấp bên dưới giúp cập nhật Tài khoản với giá trị trường mới.

Sau đây là một ví dụ về cách một đoạn mã Apex sẽ như thế nào. Chúng ta sẽ nghiên cứu sâu hơn về tất cả các khái niệm lập trình Apex này trong hướng dẫn này.

Trong chương này, chúng ta sẽ hiểu môi trường phát triển Salesforce Apex của chúng ta. Giả sử rằng bạn đã có một phiên bản Salesforce được thiết lập để phát triển Apex.

Bạn có thể phát triển mã Apex trong phiên bản Sandbox hoặc Developer của Salesforce. Tổ chức Sandbox là một bản sao của tổ chức của bạn, trong đó bạn có thể viết mã và kiểm tra nó mà không phải chịu rủi ro sửa đổi dữ liệu hoặc làm ảnh hưởng đến chức năng bình thường. Theo thông lệ công nghiệp tiêu chuẩn, bạn phải phát triển mã trong Sandbox và sau đó triển khai nó vào môi trường Sản xuất.

Đối với hướng dẫn này, chúng tôi sẽ sử dụng phiên bản dành cho Nhà phát triển của Salesforce. Trong phiên bản dành cho Nhà phát triển, bạn sẽ không có tùy chọn tạo tổ chức Hộp cát. Các tính năng Hộp cát có sẵn trong các phiên bản khác của Salesforce.

Công cụ phát triển mã Apex

Trong tất cả các phiên bản, chúng tôi có thể sử dụng bất kỳ công cụ nào trong số ba công cụ sau để phát triển mã:

  • Bảng điều khiển dành cho nhà phát triển Force.com
  • Force.com IDE
  • Trình chỉnh sửa mã trong giao diện người dùng Salesforce

Note − Chúng tôi sẽ sử dụng Bảng điều khiển dành cho nhà phát triển trong suốt hướng dẫn của chúng tôi để thực thi mã vì nó đơn giản và thân thiện với người dùng để học.

Bảng điều khiển dành cho nhà phát triển Force.com

Bảng điều khiển dành cho nhà phát triển là một môi trường phát triển tích hợp với tập hợp các công cụ bạn có thể sử dụng để tạo, gỡ lỗi và kiểm tra các ứng dụng trong tổ chức Salesforce của mình.

Làm theo các bước sau để mở Bảng điều khiển dành cho nhà phát triển -

Step 1 − Đi tới Tên → Bảng điều khiển dành cho nhà phát triển

Step 2 − Nhấp vào "Bảng điều khiển dành cho nhà phát triển" và một cửa sổ sẽ xuất hiện như trong ảnh chụp màn hình sau.

Sau đây là một số thao tác có thể được thực hiện bằng Bảng điều khiển dành cho nhà phát triển.

  • Writing and compiling code −Bạn có thể viết mã bằng trình chỉnh sửa mã nguồn. Khi bạn lưu trình kích hoạt hoặc lớp, mã sẽ tự động được biên dịch. Mọi lỗi biên dịch sẽ được thông báo.

  • Debugging −Bạn có thể viết mã bằng trình chỉnh sửa mã nguồn. Khi bạn lưu trình kích hoạt hoặc lớp, mã sẽ tự động được biên dịch. Mọi lỗi biên dịch sẽ được thông báo.

  • Testing − Bạn có thể xem nhật ký gỡ lỗi và đặt các điểm kiểm tra hỗ trợ gỡ lỗi.

  • Checking performance −Bạn có thể thực hiện các bài kiểm tra của các lớp kiểm tra cụ thể hoặc tất cả các lớp trong tổ chức của mình và bạn có thể xem kết quả kiểm tra. Ngoài ra, bạn có thể kiểm tra độ phủ của mã.

  • SOQL queries − Bạn có thể kiểm tra nhật ký gỡ lỗi để xác định vị trí tắc nghẽn hiệu suất.

  • Color coding and autocomplete − Trình soạn thảo mã nguồn sử dụng một bảng màu để dễ đọc hơn các phần tử mã và cung cấp tính năng tự động hoàn thành cho các tên lớp và phương thức.

Thực thi mã trong Bảng điều khiển dành cho nhà phát triển

Tất cả các đoạn mã được đề cập trong hướng dẫn này cần được thực thi trong bảng điều khiển dành cho nhà phát triển. Làm theo các bước sau để thực hiện các bước trong Bảng điều khiển dành cho nhà phát triển.

Step 1 - Đăng nhập vào Salesforce.com bằng login.salesforce.com. Sao chép các đoạn mã được đề cập trong hướng dẫn. Hiện tại, chúng tôi sẽ sử dụng mã mẫu sau.

String myString = 'MyString';
System.debug('Value of String Variable'+myString);

Step 2 - Để mở Bảng điều khiển dành cho nhà phát triển, hãy nhấp vào Tên → Bảng điều khiển dành cho nhà phát triển sau đó nhấp vào Thực hiện ẩn danh như hình dưới đây.

Step 3 - Ở bước này, một cửa sổ hiện ra và bạn có thể dán mã vào đó.

Step 4 - Khi chúng ta nhấp vào Execute, các bản ghi gỡ lỗi sẽ mở ra. Khi nhật ký xuất hiện trong cửa sổ như hình dưới đây, hãy nhấp vào ghi nhật ký.

Sau đó gõ 'USER' vào cửa sổ như hình dưới đây và câu lệnh đầu ra sẽ xuất hiện trong cửa sổ gỡ lỗi. Câu lệnh 'USER' này được sử dụng để lọc đầu ra.

Vì vậy, về cơ bản, bạn sẽ làm theo tất cả các bước đã đề cập ở trên để thực thi bất kỳ đoạn mã nào trong hướng dẫn này.

Ví dụ về phát triển ứng dụng doanh nghiệp

Đối với hướng dẫn của chúng tôi, chúng tôi sẽ triển khai ứng dụng CRM cho một Công ty Chế biến và Thiết bị Hóa chất. Công ty này giao dịch với các nhà cung cấp và cung cấp dịch vụ. Chúng tôi sẽ tìm ra các đoạn mã nhỏ liên quan đến ví dụ này trong suốt hướng dẫn của chúng tôi để hiểu chi tiết từng khái niệm.

Để thực thi mã trong hướng dẫn này, bạn sẽ cần phải tạo hai đối tượng: Đối tượng Khách hàng và Đối tượng Hóa đơn. Nếu bạn đã biết cách tạo các đối tượng này trong Salesforce, bạn có thể bỏ qua các bước dưới đây. Nếu không, bạn có thể làm theo hướng dẫn từng bước dưới đây.

Tạo đối tượng khách hàng

Chúng tôi sẽ thiết lập đối tượng Khách hàng trước.

Step 1- Vào Setup rồi tìm kiếm 'Object' như hình bên dưới. Sau đó nhấp vào liên kết Đối tượng như hình bên dưới.

Step 2 - Khi trang đối tượng được mở, sau đó nhấp vào 'Create New Object'như hình dưới đây.

Step 3- Sau khi click vào nút, trang tạo đối tượng mới sẽ xuất hiện, sau đó nhập tất cả các chi tiết đối tượng như đã nhập bên dưới. Tên đối tượng phải là Khách hàng. Bạn chỉ cần nhập thông tin vào trường như thể hiện trong ảnh chụp màn hình bên dưới và giữ nguyên những thứ mặc định khác.

Nhập thông tin và sau đó nhấp vào nút 'Lưu' -

Làm theo các bước trên là chúng ta đã tạo thành công đối tượng Khách hàng.

Tạo Trường tùy chỉnh cho đối tượng Khách hàng

Bây giờ chúng ta đã thiết lập xong đối tượng Khách hàng, chúng ta sẽ tạo một trường 'Hoạt động' và sau đó bạn có thể tạo các trường khác bằng cách làm theo các bước tương tự. Tên và tên API của trường sẽ được đưa ra trong ảnh chụp màn hình.

Step 1- Chúng tôi sẽ tạo một trường có tên là 'Hoạt động' của kiểu dữ liệu là Hộp kiểm. Đi tới Thiết lập và nhấp vào nó.

Step 2 - Tìm kiếm 'Đối tượng' như hình dưới đây và nhấp vào nó.

Step 3 - Bấm vào đối tượng 'Khách hàng'.

Step 4 - Khi bạn đã nhấp vào liên kết Đối tượng khách hàng và trang chi tiết đối tượng xuất hiện, hãy nhấp vào nút Mới.

Step 5 - Bây giờ, chọn kiểu dữ liệu là Hộp kiểm và nhấp vào Tiếp theo.

Step 6 - Nhập tên trường và nhãn như hình bên dưới.

Step 7 - Nhấp vào Hiển thị và sau đó nhấp vào Tiếp theo.

Step 8 - Bây giờ nhấp vào 'Lưu'.

Bằng cách làm theo các bước trên, trường tùy chỉnh 'Hoạt động' của chúng tôi được tạo. Bạn phải làm theo tất cả các bước tạo trường tùy chỉnh ở trên cho các trường còn lại. Đây là chế độ xem cuối cùng của đối tượng khách hàng sau khi tất cả các trường được tạo -

Tạo đối tượng hóa đơn

Step 1 - Vào Setup và tìm kiếm 'Object' rồi click vào đường dẫn Objects như hình bên dưới.

Step 2 - Khi trang đối tượng được mở, sau đó nhấp vào nút 'Tạo đối tượng mới' như hình dưới đây.

Step 3- Sau khi nhấp vào nút, trang tạo đối tượng mới sẽ xuất hiện như trong ảnh chụp màn hình bên dưới. Bạn cần nhập thông tin chi tiết tại đây. Tên đối tượng phải là Hóa đơn. Điều này tương tự như cách chúng tôi tạo đối tượng Khách hàng trước đó trong hướng dẫn này.

Step 4 - Nhập thông tin như hình bên dưới rồi bấm vào nút 'Lưu'.

Bằng cách làm theo các bước sau, đối tượng Hóa đơn của bạn sẽ được tạo.

Tạo Trường tùy chỉnh cho đối tượng Hóa đơn

Chúng tôi sẽ tạo trường Mô tả trên đối tượng Hóa đơn như hình dưới đây -

Step 1 - Vào Setup và nhấp vào nó.

Step 2 - Tìm kiếm 'Đối tượng' như hình dưới đây và nhấp vào nó.

Step 3 - Bấm vào đối tượng 'Hóa đơn'.

Và sau đó nhấp vào 'Mới'.

Step 4 - Chọn kiểu dữ liệu là Vùng văn bản rồi nhấp vào nút Tiếp theo.

Step 5 - Nhập thông tin như bên dưới.

Step 6 - Nhấp vào Hiển thị và sau đó Tiếp theo.

Step 7 - Nhấp vào Lưu.

Tương tự, bạn có thể tạo các trường khác trên đối tượng Hóa đơn.

Bằng cách này, chúng tôi đã tạo các đối tượng cần thiết cho hướng dẫn này. Chúng ta sẽ học các ví dụ khác nhau trong các chương tiếp theo dựa trên các đối tượng này.

Hiểu các loại dữ liệu

Ngôn ngữ Apex được gõ mạnh nên mọi biến trong Apex sẽ được khai báo với kiểu dữ liệu cụ thể. Tất cả các biến apex được khởi tạo ban đầu thành null. Nhà phát triển luôn khuyên bạn nên đảm bảo rằng các giá trị thích hợp được gán cho các biến. Nếu không, các biến như vậy khi được sử dụng, sẽ ném ra các ngoại lệ con trỏ null hoặc bất kỳ ngoại lệ nào chưa được xử lý.

Apex hỗ trợ các kiểu dữ liệu sau:

  • Nguyên thủy (Số nguyên, Đôi, Dài, Ngày, Giờ, Chuỗi, ID hoặc Boolean)

  • Bộ sưu tập (Danh sách, Bộ và Bản đồ) (Được đề cập trong Chương 6)

  • sObject

  • Enums

  • Lớp, Đối tượng và Giao diện (Được đề cập trong Chương 11, 12 và 13)

Trong chương này, chúng ta sẽ xem xét tất cả Các kiểu dữ liệu nguyên thủy, sObjects và Enums. Chúng ta sẽ xem xét Bộ sưu tập, Lớp, Đối tượng và Giao diện trong các chương sắp tới vì chúng là những chủ đề chính cần học từng cá nhân.

Các kiểu dữ liệu ban đầu

Trong phần này, chúng ta sẽ thảo luận về Các kiểu dữ liệu ban đầu được hỗ trợ bởi Apex.

Số nguyên

Một số 32 bit không bao gồm bất kỳ dấu thập phân nào. Phạm vi giá trị cho điều này bắt đầu từ -2,147,483,648 và giá trị lớn nhất lên đến 2,147,483,647.

Example

Chúng tôi muốn khai báo một biến sẽ lưu trữ số lượng thùng cần được vận chuyển đến người mua của nhà máy chế biến hóa chất.

Integer barrelNumbers = 1000;
system.debug(' value of barrelNumbers variable: '+barrelNumbers);

Các System.debug() hàm in ra giá trị của biến để chúng ta có thể sử dụng nó để gỡ lỗi hoặc để biết giá trị của biến hiện tại.

Dán đoạn mã trên vào Bảng điều khiển dành cho nhà phát triển và nhấp vào Thực thi. Sau khi các nhật ký được tạo, nó sẽ hiển thị giá trị của biến "Số thùng" là 1000.

Boolean

Biến này có thể là true, false hoặc null. Nhiều lần, loại biến này có thể được sử dụng làm cờ trong lập trình để xác định xem điều kiện cụ thể được đặt hay không.

Example

Nếu lô hàng Boolean được đặt là true, thì nó có thể được khai báo là:

Boolean shipmentDispatched;
shipmentDispatched = true;
System.debug('Value of shipmentDispatched '+shipmentDispatched);

Ngày

Loại biến này chỉ ra một ngày. Điều này chỉ có thể lưu trữ ngày chứ không phải thời gian. Để lưu ngày cùng với thời gian, chúng ta sẽ cần lưu trữ nó trong biến DateTime.

Example

Hãy xem xét ví dụ sau để hiểu cách hoạt động của biến Ngày.

//ShipmentDate can be stored when shipment is dispatched.
Date ShipmentDate = date.today();
System.debug('ShipmentDate '+ShipmentDate);

Dài

Đây là số 64 bit không có dấu thập phân. Điều này được sử dụng khi chúng ta cần một phạm vi giá trị rộng hơn giá trị được cung cấp bởi Integer.

Example

Nếu doanh thu của công ty được lưu trữ, thì chúng tôi sẽ sử dụng kiểu dữ liệu là Long.

Long companyRevenue = 21474838973344648L;
system.debug('companyRevenue'+companyRevenue);

Vật

Chúng tôi có thể coi đây là bất kỳ kiểu dữ liệu nào được hỗ trợ trong Apex. Ví dụ, biến Class có thể là đối tượng của lớp đó, và kiểu chung sObject cũng là một đối tượng và kiểu đối tượng cụ thể tương tự như Account cũng là Object.

Example

Hãy xem xét ví dụ sau để hiểu cách hoạt động của biến bject.

Account objAccount = new Account (Name = 'Test Chemical');
system.debug('Account value'+objAccount);

Note - Bạn cũng có thể tạo một đối tượng của lớp được xác định trước, như được đưa ra bên dưới -

//Class Name: MyApexClass
MyApexClass classObj = new MyApexClass();

Đây là đối tượng lớp sẽ được sử dụng làm biến lớp.

Chuỗi

Chuỗi là bất kỳ bộ ký tự nào trong dấu ngoặc kép. Nó không có bất kỳ giới hạn nào về số lượng ký tự. Ở đây, kích thước heap sẽ được sử dụng để xác định số lượng ký tự. Điều này hạn chế sự độc quyền tài nguyên của chương trình Apex và cũng đảm bảo rằng nó không quá lớn.

Example

String companyName = 'Abc International';
System.debug('Value companyName variable'+companyName);

Thời gian

Biến này được sử dụng để lưu trữ thời gian cụ thể. Biến này phải luôn được khai báo bằng phương thức tĩnh hệ thống.

Bãi

Blob là một tập hợp dữ liệu nhị phân được lưu trữ dưới dạng đối tượng. Điều này sẽ được sử dụng khi chúng tôi muốn lưu trữ tệp đính kèm trong lực lượng bán hàng thành một biến. Kiểu dữ liệu này chuyển đổi các tệp đính kèm thành một đối tượng duy nhất. Nếu blob được chuyển đổi thành một chuỗi, thì chúng ta có thể sử dụng các phương thức toString và valueOf cho tương tự.

sObject

Đây là một kiểu 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. Có hai loại sObjects - Standard và Custom.

Ví dụ: Tài khoản là một sObject tiêu chuẩn và bất kỳ đối tượng nào khác do người dùng xác định (như đối tượng Khách hàng mà chúng tôi đã tạo) là một sObject tùy chỉnh.

Example

//Declaring an sObject variable of type Account
Account objAccount = new Account();

//Assignment of values to fields of sObjects
objAccount.Name = 'ABC Customer';
objAccount.Description = 'Test Account';
System.debug('objAccount variable value'+objAccount);

//Declaring an sObject for custom object APEX_Invoice_c
APEX_Customer_c objCustomer = new APEX_Customer_c();

//Assigning value to fields
objCustomer.APEX_Customer_Decscription_c = 'Test Customer';
System.debug('value objCustomer'+objCustomer);

Enum

Enum là một kiểu dữ liệu trừu tượng lưu trữ một giá trị của một tập hợp hữu hạn các số nhận dạng được chỉ định. Bạn có thể sử dụng từ khóa Enum để định nghĩa một Enum. Enum có thể được sử dụng như bất kỳ loại dữ liệu nào khác trong Salesforce.

Example

Bạn có thể khai báo các tên có thể có của Hợp chất hóa học bằng cách thực thi đoạn mã sau:

//Declaring enum for Chemical Compounds
public enum Compounds {HCL, H2SO4, NACL, HG}
Compounds objC = Compounds.HCL;
System.debug('objC value: '+objC);

Java và Apex tương tự nhau về nhiều mặt. Khai báo biến trong Java và Apex cũng hoàn toàn giống nhau. Chúng ta sẽ thảo luận một vài ví dụ để hiểu cách khai báo các biến cục bộ.

String productName = 'HCL';
Integer i = 0;
Set<string> setOfProducts = new Set<string>();
Map<id, string> mapOfProductIdToName = new Map<id, string>();

Lưu ý rằng tất cả các biến được gán với giá trị null.

Declaring Variables

Bạn có thể khai báo các biến trong Apex như String và Integer như sau:

String strName = 'My String';  //String variable declaration
Integer myInteger = 1;         //Integer variable declaration
Boolean mtBoolean = true;      //Boolean variable declaration

Apex variables are Case-Insensitive

Điều này có nghĩa là đoạn mã được đưa ra bên dưới sẽ tạo ra một lỗi vì biến 'm' đã được khai báo hai lần và cả hai sẽ được coi là như nhau.

Integer m = 100;
for (Integer i = 0; i<10; i++) {
   integer m = 1; //This statement will throw an error as m is being declared
   again
   System.debug('This code will throw error');
}

Scope of Variables

Một biến Apex có hiệu lực từ thời điểm nó được khai báo trong mã. Vì vậy nó không được phép xác định lại cùng một biến một lần nữa và trong khối mã. Ngoài ra, nếu bạn khai báo bất kỳ biến nào trong một phương thức, thì phạm vi biến đó sẽ chỉ được giới hạn trong phương thức cụ thể đó. Tuy nhiên, các biến lớp có thể được truy cập trong toàn bộ lớp.

Example

//Declare variable Products
List<string> Products = new List<strings>();
Products.add('HCL');

//You cannot declare this variable in this code clock or sub code block again
//If you do so then it will throw the error as the previous variable in scope
//Below statement will throw error if declared in same code block
List<string> Products = new List<strings>();

Chuỗi trong Apex, cũng như bất kỳ ngôn ngữ lập trình nào khác, là bất kỳ bộ ký tự nào không có giới hạn ký tự.

Example

String companyName = 'Abc International';
System.debug('Value companyName variable'+companyName);

Phương thức chuỗi

Lớp chuỗi trong Salesforce có nhiều phương thức. Chúng ta sẽ xem xét một số phương thức chuỗi quan trọng nhất và được sử dụng thường xuyên trong chương này.

chứa đựng

Phương thức này sẽ trả về true nếu chuỗi đã cho có chứa chuỗi con được đề cập.

Syntax

public Boolean contains(String substring)

Example

String myProductName1 = 'HCL';
String myProductName2 = 'NAHCL';
Boolean result = myProductName2.contains(myProductName1);
System.debug('O/p will be true as it contains the String and Output is:'+result);

bằng

Phương thức này sẽ trả về true nếu chuỗi đã cho và chuỗi được truyền trong phương thức có cùng chuỗi ký tự nhị phân và chúng không rỗng. Bạn cũng có thể so sánh id bản ghi SFDC bằng cách sử dụng phương pháp này. Phương pháp này phân biệt chữ hoa chữ thường.

Syntax

public Boolean equals(Object string)

Example

String myString1 = 'MyString';
String myString2 = 'MyString';
Boolean result = myString2.equals(myString1);
System.debug('Value of Result will be true as they are same and Result is:'+result);

equalsIgnoreCase

Phương thức này sẽ trả về true nếu stringtoCompare có cùng chuỗi ký tự với chuỗi đã cho. Tuy nhiên, phương pháp này không phân biệt chữ hoa chữ thường.

Syntax

public Boolean equalsIgnoreCase(String stringtoCompare)

Example

Đoạn mã sau sẽ trả về true vì các ký tự chuỗi và chuỗi giống nhau, bỏ qua phân biệt chữ hoa chữ thường.

String myString1 = 'MySTRING';
String myString2 = 'MyString';
Boolean result = myString2.equalsIgnoreCase(myString1);
System.debug('Value of Result will be true as they are same and Result is:'+result);

tẩy

Phương thức này loại bỏ chuỗi được cung cấp trong stringToRemove khỏi chuỗi đã cho. Điều này rất hữu ích khi bạn muốn xóa một số ký tự cụ thể khỏi chuỗi và không biết chỉ mục chính xác của các ký tự cần xóa. Phương pháp này phân biệt chữ hoa chữ thường và sẽ không hoạt động nếu cùng một dãy ký tự xảy ra nhưng chữ hoa chữ thường khác nhau.

Syntax

public String remove(String stringToRemove)

Example

String myString1 = 'This Is MyString Example';
String stringToRemove = 'MyString';
String result = myString1.remove(stringToRemove);
System.debug('Value of Result will be 'This Is Example' as we have removed the MyString 
   and Result is :'+result);

removeEndIgnoreCase

Phương thức này loại bỏ chuỗi được cung cấp trong stringToRemove khỏi chuỗi đã cho nhưng chỉ khi nó xảy ra ở cuối. Phương pháp này không phân biệt chữ hoa chữ thường.

Syntax

public String removeEndIgnoreCase(String stringToRemove)

Example

String myString1 = 'This Is MyString EXAMPLE';
String stringToRemove = 'Example';
String result = myString1.removeEndIgnoreCase(stringToRemove);
System.debug('Value of Result will be 'This Is MyString' as we have removed the 'Example'
   and Result is :'+result);

bắt đầu với

Phương thức này sẽ trả về true nếu chuỗi đã cho bắt đầu bằng tiền tố được cung cấp trong phương thức.

Syntax

public Boolean startsWith(String prefix)

Example

String myString1 = 'This Is MyString EXAMPLE';
String prefix = 'This';
Boolean result = myString1.startsWith(prefix);
System.debug(' This will return true as our String starts with string 'This' and the 
   Result is :'+result);

Mảng trong Apex về cơ bản giống như Danh sách trong Apex. Không có sự phân biệt hợp lý giữa Mảng và Danh sách vì cấu trúc và phương thức dữ liệu bên trong của chúng cũng giống nhau nhưng cú pháp mảng hơi truyền thống như Java.

Dưới đây là đại diện của Mảng Sản phẩm -

Index 0 - HCL

Index 1 - H2SO4

Index 2 - NACL

Index 3 - H2O

Index 4 - N2

Index 5 - U296

Cú pháp

<String> [] arrayOfProducts = new List<String>();

Thí dụ

Giả sử, chúng ta phải lưu trữ tên Sản phẩm của mình - chúng ta có thể sử dụng Mảng trong đó, chúng ta sẽ lưu trữ Tên sản phẩm như hình dưới đây. Bạn có thể truy cập Sản phẩm cụ thể bằng cách chỉ định chỉ mục.

//Defining array
String [] arrayOfProducts = new List<String>();

//Adding elements in Array
arrayOfProducts.add('HCL');
arrayOfProducts.add('H2SO4');
arrayOfProducts.add('NACL');
arrayOfProducts.add('H2O');
arrayOfProducts.add('N2');
arrayOfProducts.add('U296');

for (Integer i = 0; i<arrayOfProducts.size(); i++) {
   //This loop will print all the elements in array
   system.debug('Values In Array: '+arrayOfProducts[i]);
}

Truy cập phần tử mảng bằng cách sử dụng chỉ mục

Bạn có thể truy cập bất kỳ phần tử nào trong mảng bằng cách sử dụng chỉ mục như hình dưới đây -

//Accessing the element in array
//We would access the element at Index 3
System.debug('Value at Index 3 is :'+arrayOfProducts[3]);

Như trong bất kỳ ngôn ngữ lập trình nào khác, Hằng số là các biến không thay đổi giá trị của chúng sau khi được khai báo hoặc gán giá trị.

Trong Apex, Hằng số được sử dụng khi chúng ta muốn xác định các biến phải có giá trị không đổi trong suốt quá trình thực thi chương trình. Hằng số Apex được khai báo với từ khóa 'final'.

Thí dụ

Hãy xem xét một CustomerOperationClass lớp và một biến hằng số regularCustomerDiscount bên trong nó -

public class CustomerOperationClass {
   static final Double regularCustomerDiscount = 0.1;
   static Double finalPrice = 0;
   
   public static Double provideDiscount (Integer price) {
      //calculate the discount
      finalPrice = price - price * regularCustomerDiscount;
      return finalPrice;
   }
}

Để xem Đầu ra của lớp trên, bạn phải thực thi mã sau trong Cửa sổ ẩn danh của Bảng điều khiển dành cho nhà phát triển:

Double finalPrice = CustomerOperationClass.provideDiscount(100);
System.debug('finalPrice '+finalPrice);

Cấu trúc ra quyết định yêu cầu người lập trình chỉ định một hoặc nhiều điều kiện để được đánh giá hoặc kiểm tra bởi chương trình, cùng với một câu lệnh hoặc các câu lệnh sẽ được thực thi nếu điều kiện đó được xác định là đúng và tùy chọn, các câu lệnh khác được thực thi nếu điều kiện được xác định là sai.

Trong chương này, chúng ta sẽ nghiên cứu cấu trúc cơ bản và nâng cao của câu lệnh điều kiện và ra quyết định trong Apex. Việc ra quyết định là cần thiết để kiểm soát luồng thực thi khi một số điều kiện được đáp ứng hay không. Sau đây là dạng chung của cấu trúc ra quyết định điển hình được tìm thấy trong hầu hết các ngôn ngữ lập trình

Sr.No. Tuyên bố & Mô tả
1 câu lệnh if

Một câu lệnh if bao gồm một biểu thức Boolean theo sau là một hoặc nhiều câu lệnh.

2 câu lệnh if ... else

Một câu lệnh if có thể được theo sau bởi một tùy chọn else câu lệnh này thực thi khi biểu thức Boolean sai.

3 câu lệnh if ... elseif ... else

Một câu lệnh if có thể được theo sau bởi một tùy chọn else if...else câu lệnh, rất hữu ích để kiểm tra các điều kiện khác nhau bằng cách sử dụng câu lệnh if ... else if duy nhất.

4 câu lệnh if lồng nhau

Bạn có thể sử dụng một if or else if tuyên bố bên trong khác if or else if các câu lệnh).

Vòng lặp được sử dụng khi một đoạn mã cụ thể phải được lặp lại với số lần lặp mong muốn. Apex hỗ trợ vòng lặp for truyền thống tiêu chuẩn cũng như các loại vòng lặp nâng cao khác. Trong chương này, chúng ta sẽ thảo luận chi tiết về các Vòng lặp trong Apex.

Một câu lệnh lặp cho phép chúng ta thực hiện một câu lệnh hoặc một nhóm câu lệnh nhiều lần và sau đây là tổng quát của câu lệnh lặp trong hầu hết các ngôn ngữ lập trình:

Các bảng sau liệt kê các Vòng lặp khác nhau xử lý các yêu cầu lặp trong ngôn ngữ Lập trình Apex. Nhấp vào các liên kết sau để kiểm tra chi tiết của chúng.

Sr.No. Loại vòng lặp & Mô tả
1 vòng lặp for

Vòng lặp này thực hiện một tập hợp các câu lệnh cho mỗi mục trong một tập các bản ghi.

2 SOQL cho vòng lặp

Thực thi một chuỗi câu lệnh trực tiếp trên tập hợp trả về o truy vấn SOQL.

3 Vòng lặp for giống Java

Thực thi một chuỗi các câu lệnh theo cú pháp giống Java truyền thống.

4 trong khi lặp lại

Lặp lại một câu lệnh hoặc một nhóm câu lệnh trong khi một điều kiện đã cho là đúng. Nó kiểm tra điều kiện trước khi thực thi phần thân của vòng lặp.

5 vòng lặp do ... while

Giống như một câu lệnh while, ngoại trừ việc nó kiểm tra điều kiện ở cuối thân vòng lặp.

Bộ sưu tập là một loại biến có thể lưu trữ nhiều bản ghi. Ví dụ: Danh sách có thể lưu trữ nhiều bản ghi của đối tượng Tài khoản. Bây giờ chúng ta hãy có một cái nhìn tổng quan chi tiết về tất cả các loại bộ sưu tập.

Danh sách

Danh sách có thể chứa bất kỳ số lượng bản ghi nguyên thủy, bộ sưu tập, sObjects, người dùng xác định và xây dựng trong kiểu Apex. Đây là một trong những loại tập hợp quan trọng nhất và nó cũng có một số phương pháp hệ thống đã được điều chỉnh riêng để sử dụng với Danh sách. Chỉ mục danh sách luôn bắt đầu bằng 0. Điều này đồng nghĩa với mảng trong Java. Một danh sách nên được khai báo với từ khóa 'Danh sách'.

Example

Dưới đây là danh sách chứa Danh sách của một kiểu dữ liệu nguyên thủy (chuỗi), đó là danh sách các thành phố.

List<string> ListOfCities = new List<string>();
System.debug('Value Of ListOfCities'+ListOfCities);

Khai báo các giá trị ban đầu của danh sách là tùy chọn. Tuy nhiên, chúng tôi sẽ khai báo các giá trị ban đầu ở đây. Sau đây là một ví dụ cho thấy tương tự.

List<string> ListOfStates = new List<string> {'NY', 'LA', 'LV'};
System.debug('Value ListOfStates'+ListOfStates);

Danh sách tài khoản (sObject)

List<account> AccountToDelete = new List<account> (); //This will be null
System.debug('Value AccountToDelete'+AccountToDelete);

Chúng ta cũng có thể khai báo Danh sách lồng nhau. Nó có thể lên đến năm cấp độ. Đây được gọi là danh sách Đa chiều.

Đây là danh sách tập hợp các số nguyên.

List<List<Set<Integer>>> myNestedList = new List<List<Set<Integer>>>();
System.debug('value myNestedList'+myNestedList);

Danh sách có thể chứa bất kỳ số lượng bản ghi nào, nhưng có một giới hạn về kích thước đống để ngăn chặn vấn đề hiệu suất và độc quyền tài nguyên.

Phương pháp cho danh sách

Có các phương pháp có sẵn cho Danh sách mà chúng ta có thể sử dụng trong khi lập trình để đạt được một số chức năng như tính toán kích thước của Danh sách, thêm phần tử, v.v.

Sau đây là một số phương pháp được sử dụng thường xuyên nhất -

  • size()
  • add()
  • get()
  • clear()
  • set()

Ví dụ sau minh họa việc sử dụng tất cả các phương pháp này

// Initialize the List
List<string> ListOfStatesMethod = new List<string>();

// This statement would give null as output in Debug logs
System.debug('Value of List'+ ListOfStatesMethod);

// Add element to the list using add method
ListOfStatesMethod.add('New York');
ListOfStatesMethod.add('Ohio');

// This statement would give New York and Ohio as output in Debug logs
System.debug('Value of List with new States'+ ListOfStatesMethod);

// Get the element at the index 0
String StateAtFirstPosition = ListOfStatesMethod.get(0);

// This statement would give New York as output in Debug log
System.debug('Value of List at First Position'+ StateAtFirstPosition);

// set the element at 1 position
ListOfStatesMethod.set(0, 'LA');

// This statement would give output in Debug log
System.debug('Value of List with element set at First Position' + ListOfStatesMethod[0]);

// Remove all the elements in List
ListOfStatesMethod.clear();

// This statement would give output in Debug log
System.debug('Value of List'+ ListOfStatesMethod);

Bạn cũng có thể sử dụng ký hiệu mảng để khai báo Danh sách, như được đưa ra bên dưới, nhưng đây không phải là thông lệ chung trong lập trình Apex -

String [] ListOfStates = new List<string>();

Bộ

Tập hợp là một kiểu tập hợp chứa nhiều bản ghi duy nhất không có thứ tự. Một Tập hợp không thể có các bản ghi trùng lặp. Giống như Danh sách, các Bộ có thể được lồng vào nhau.

Example

Chúng tôi sẽ xác định bộ sản phẩm mà công ty đang bán.

Set<string> ProductSet = new Set<string>{'Phenol', 'Benzene', 'H2SO4'};
System.debug('Value of ProductSet'+ProductSet);

Phương pháp cho Bộ

Set không hỗ trợ các phương thức mà chúng tôi có thể sử dụng trong khi lập trình như được hiển thị bên dưới (chúng tôi đang mở rộng ví dụ trên) -

// Adds an element to the set
// Define set if not defined previously
Set<string> ProductSet = new Set<string>{'Phenol', 'Benzene', 'H2SO4'};
ProductSet.add('HCL');
System.debug('Set with New Value '+ProductSet);

// Removes an element from set
ProductSet.remove('HCL');
System.debug('Set with removed value '+ProductSet);

// Check whether set contains the particular element or not and returns true or false
ProductSet.contains('HCL');
System.debug('Value of Set with all values '+ProductSet);

Bản đồ

Nó là một cặp giá trị khóa chứa khóa duy nhất cho mỗi giá trị. Cả khóa và giá trị đều có thể thuộc bất kỳ kiểu dữ liệu nào.

Example

Ví dụ sau thể hiện bản đồ của Tên sản phẩm với mã Sản phẩm.

// Initialize the Map
Map<string, string> ProductCodeToProductName = new Map<string, string>
{'1000'=>'HCL', '1001'=>'H2SO4'};

// This statement would give as output as key value pair in Debug log
System.debug('value of ProductCodeToProductName'+ProductCodeToProductName);

Phương pháp cho Bản đồ

Sau đây là một số ví dụ minh họa các phương pháp có thể được sử dụng với Bản đồ -

// Define a new map
Map<string, string> ProductCodeToProductName = new Map<string, string>();

// Insert a new key-value pair in the map where '1002' is key and 'Acetone' is value
ProductCodeToProductName.put('1002', 'Acetone');

// Insert a new key-value pair in the map where '1003' is key and 'Ketone' is value
ProductCodeToProductName.put('1003', 'Ketone');

// Assert that the map contains a specified key and respective value
System.assert(ProductCodeToProductName.containsKey('1002'));
System.debug('If output is true then Map contains the key and output is:'
   + ProductCodeToProductName.containsKey('1002'));

// Retrieves a value, given a particular key
String value = ProductCodeToProductName.get('1002');
System.debug('Value at the Specified key using get function: '+value);

// Return a set that contains all of the keys in the map
Set SetOfKeys = ProductCodeToProductName.keySet();
System.debug('Value of Set with Keys '+SetOfKeys);

Các giá trị bản đồ có thể không có thứ tự và do đó chúng ta không nên dựa vào thứ tự lưu trữ các giá trị và cố gắng truy cập bản đồ luôn bằng các phím. Giá trị bản đồ có thể là rỗng. Các khóa ánh xạ khi khai báo Chuỗi có phân biệt chữ hoa chữ thường; ví dụ: ABC và abc sẽ được coi là các khóa khác nhau và được coi là duy nhất.

Class là gì?

Lớp là một khuôn mẫu hoặc bản thiết kế mà từ đó các đối tượng được tạo ra. Một đối tượng là một thể hiện của một lớp. Đây là định nghĩa tiêu chuẩn của Class. Các lớp Apex tương tự như các Lớp Java.

Ví dụ, InvoiceProcessorlớp mô tả lớp có tất cả các phương thức và hành động có thể được thực hiện trên Hóa đơn. Nếu bạn tạo một phiên bản của lớp này, thì nó sẽ đại diện cho một hóa đơn hiện đang có trong ngữ cảnh.

Tạo lớp học

Bạn có thể tạo lớp trong Apex từ Bảng điều khiển dành cho nhà phát triển, Force.com Eclipse IDE và từ trang chi tiết Lớp Apex.

Từ Bảng điều khiển dành cho nhà phát triển

Làm theo các bước sau để tạo lớp Apex từ Bảng điều khiển dành cho nhà phát triển -

Step 1 - Vào Tên và nhấp vào Bảng điều khiển dành cho nhà phát triển.

Step 2 - Nhấp vào Tệp ⇒ Mới và sau đó nhấp vào lớp Apex.

Từ Force.com IDE

Làm theo các bước sau để tạo một lớp từ Force.com IDE -

Step 1 - Mở Force.com Eclipse IDE

Step 2 - Tạo một dự án mới bằng cách nhấp vào Tệp ⇒ Mới ⇒ Lớp Apex.

Step 3 - Cung cấp Tên cho Lớp và nhấp vào OK.

Khi điều này được thực hiện, lớp mới sẽ được tạo.

Từ trang chi tiết lớp Apex

Làm theo các bước sau để tạo một lớp từ Trang Chi tiết Lớp Apex -

Step 1 - Nhấp vào Tên ⇒ Thiết lập.

Step 2- Tìm kiếm 'Apex Class' và nhấp vào liên kết. Nó sẽ mở trang chi tiết Apex Class.

Step 3 - Nhấp vào 'Mới', sau đó cung cấp Tên cho lớp rồi nhấp vào Lưu.

Cấu trúc lớp Apex

Dưới đây là cấu trúc mẫu cho định nghĩa lớp Apex.

Syntax

private | public | global
[virtual | abstract | with sharing | without sharing]
class ClassName [implements InterfaceNameList] [extends ClassName] {
   // Classs Body
}

Định nghĩa này sử dụng kết hợp các công cụ sửa đổi quyền truy cập, chế độ chia sẻ, tên lớp và nội dung lớp. Chúng tôi sẽ xem xét thêm tất cả các tùy chọn này.

Example

Sau đây là cấu trúc mẫu cho định nghĩa lớp Apex:

public class MySampleApexClass {       //Class definition and body
   public static Integer myValue = 0;  //Class Member variable
   public static String myString = ''; //Class Member variable
   
   public static Integer getCalculatedValue () {
   // Method definition and body
   // do some calculation
      myValue = myValue+10;
      return myValue;
   }
}

Truy cập công cụ sửa đổi

Riêng tư

Nếu bạn khai báo công cụ sửa đổi truy cập là 'Riêng tư', thì lớp này sẽ chỉ được biết cục bộ và bạn không thể truy cập lớp này bên ngoài phần cụ thể đó. Theo mặc định, các lớp có bổ ngữ này.

Công cộng

Nếu bạn khai báo lớp là 'Công khai' thì điều này ngụ ý rằng lớp này có thể truy cập vào tổ chức của bạn và không gian tên đã xác định của bạn. Thông thường, hầu hết các lớp Apex được định nghĩa bằng từ khóa này.

Toàn cầu

Nếu bạn khai báo lớp là 'toàn cầu' thì tất cả các mã apex đều có thể truy cập được, bất kể tổ chức của bạn là gì. Nếu bạn có phương thức được xác định với từ khóa dịch vụ web, thì bạn phải khai báo lớp chứa với từ khóa toàn cầu.

Chế độ chia sẻ

Bây giờ chúng ta hãy thảo luận về các phương thức chia sẻ khác nhau.

Với sự chia sẻ

Đây là một tính năng đặc biệt của Apex Classes trong Salesforce. Khi một lớp được chỉ định bằng từ khóa 'With Sharing' thì nó có các hàm ý sau: Khi lớp sẽ được thực thi, nó sẽ tôn trọng cài đặt truy cập của Người dùng và quyền hồ sơ. Giả sử, hành động của Người dùng đã kích hoạt cập nhật bản ghi cho 30 bản ghi, nhưng người dùng chỉ có quyền truy cập vào 20 bản ghi và 10 bản ghi không thể truy cập được. Sau đó, nếu lớp đang thực hiện hành động cập nhật bản ghi, chỉ 20 bản ghi sẽ được cập nhật mà người dùng có quyền truy cập và phần còn lại của 10 bản ghi sẽ không được cập nhật. Đây còn được gọi là chế độ Người dùng.

Không chia sẻ

Ngay cả khi Người dùng không có quyền truy cập vào 10 bản ghi trong số 30 bản ghi, tất cả 30 bản ghi sẽ được cập nhật khi Lớp đang chạy ở chế độ Hệ thống, tức là nó đã được xác định với từ khóa Không chia sẻ. Đây được gọi là Chế độ Hệ thống.

Ảo

Nếu bạn sử dụng từ khóa 'virtual', thì nó chỉ ra rằng lớp này có thể được mở rộng và cho phép ghi đè. Nếu các phương thức cần được ghi đè, thì các lớp phải được khai báo bằng từ khóa ảo.

trừu tượng

Nếu bạn khai báo lớp là 'trừu tượng', thì nó sẽ chỉ chứa chữ ký của phương thức chứ không phải thực thi thực tế.

Biến lớp

Syntax

[public | private | protected | global] [final] [static] data_type
variable_name [= value]

Trong cú pháp trên -

  • Kiểu dữ liệu biến và tên biến là bắt buộc
  • Công cụ sửa đổi và giá trị truy cập là tùy chọn.

Example

public static final Integer myvalue;

Phương pháp lớp học

Có hai công cụ sửa đổi cho Phương thức lớp trong Apex - Công khai hoặc Được bảo vệ. Kiểu trả về là bắt buộc đối với phương thức và nếu phương thức không trả về bất cứ thứ gì thì bạn phải đề cập đến void làm kiểu trả về. Ngoài ra, Body cũng được yêu cầu cho phương pháp.

Syntax

[public | private | protected | global]
[override]
[static]

return_data_type method_name (input parameters) {
   // Method body goes here
}

Giải thích cú pháp

Các tham số được đề cập trong dấu ngoặc vuông là tùy chọn. Tuy nhiên, các thành phần sau là cần thiết:

  • return_data_type
  • method_name

Access Modifier cho các phương thức lớp

Sử dụng công cụ sửa đổi quyền truy cập, bạn có thể chỉ định mức truy cập cho các phương thức lớp. Ví dụ, phương thức Public sẽ có thể truy cập từ bất kỳ đâu trong lớp và bên ngoài Lớp. Phương thức riêng sẽ chỉ có thể truy cập trong lớp. Toàn cầu sẽ có thể truy cập được bởi tất cả các lớp Apex và có thể được hiển thị dưới dạng phương thức dịch vụ web mà các lớp apex khác có thể truy cập.

Example

//Method definition and body
public static Integer getCalculatedValue () {
   
   //do some calculation
   myValue = myValue+10;
   return myValue;
}

Phương thức này có kiểu trả về là Số nguyên và không có tham số.

Một phương thức có thể có các tham số như được hiển thị trong ví dụ sau:

// Method definition and body, this method takes parameter price which will then be used 
// in method.

public static Integer getCalculatedValueViaPrice (Decimal price) {
   // do some calculation
   myValue = myValue+price;
   return myValue;
}

Trình tạo lớp

Hàm tạo là một mã được gọi khi một đối tượng được tạo từ bản thiết kế lớp. Nó có cùng tên với tên lớp.

Chúng ta không cần xác định hàm tạo cho mọi lớp, vì theo mặc định một hàm tạo không đối số được gọi. Các hàm tạo hữu ích cho việc khởi tạo các biến hoặc khi một quá trình được thực hiện tại thời điểm khởi tạo lớp. Ví dụ: bạn sẽ muốn gán giá trị cho một số biến Integer là 0 khi lớp được gọi.

Example

// Class definition and body
public class MySampleApexClass2 {
   public static Double myValue;   // Class Member variable
   public static String myString;  // Class Member variable

   public MySampleApexClass2 () {
      myValue = 100; //initialized variable when class is called
   }

   public static Double getCalculatedValue () { // Method definition and body
      // do some calculation
      myValue = myValue+10;
      return myValue;
   }

   public static Double getCalculatedValueViaPrice (Decimal price) {
      // Method definition and body
      // do some calculation
      myValue = myValue+price; // Final Price would be 100+100=200.00
      return myValue;
   }
}

Bạn cũng có thể gọi phương thức của lớp thông qua hàm tạo. Điều này có thể hữu ích khi lập trình Apex cho bộ điều khiển lực trực quan. Khi đối tượng lớp được tạo, thì hàm tạo được gọi như hình dưới đây:

// Class and constructor has been instantiated
MySampleApexClass2 objClass = new MySampleApexClass2();
Double FinalPrice = MySampleApexClass2.getCalculatedValueViaPrice(100);
System.debug('FinalPrice: '+FinalPrice);

Quá tải cấu tạo

Các hàm tạo có thể được nạp chồng, tức là một lớp có thể có nhiều hơn một hàm tạo được xác định với các tham số khác nhau.

Example

public class MySampleApexClass3 {  // Class definition and body
   public static Double myValue;   // Class Member variable
   public static String myString;  // Class Member variable

   public MySampleApexClass3 () {
      myValue = 100; // initialized variable when class is called
      System.debug('myValue variable with no Overaloading'+myValue);
   }

   public MySampleApexClass3 (Integer newPrice) { // Overloaded constructor
      myValue = newPrice; // initialized variable when class is called
      System.debug('myValue variable with Overaloading'+myValue);
   }

      public static Double getCalculatedValue () { // Method definition and body
      // do some calculation
      myValue = myValue+10;
      return myValue;
   }

   public static Double getCalculatedValueViaPrice (Decimal price) {
      // Method definition and body
      // do some calculation
      myValue = myValue+price;
      return myValue;
   }
}

Bạn có thể thực thi lớp này như chúng ta đã thực thi trong ví dụ trước.

// Developer Console Code
MySampleApexClass3 objClass = new MySampleApexClass3();
Double FinalPrice = MySampleApexClass3.getCalculatedValueViaPrice(100);
System.debug('FinalPrice: '+FinalPrice);

Một thể hiện của lớp được gọi là Đối tượng. Về khía cạnh Salesforce, đối tượng có thể thuộc lớp hoặc bạn cũng có thể tạo một đối tượng của sObject.

Tạo đối tượng từ lớp

Bạn có thể tạo một đối tượng của lớp như bạn có thể đã làm trong Java hoặc ngôn ngữ lập trình hướng đối tượng khác.

Sau đây là một Class ví dụ được gọi là MyClass -

// Sample Class Example
public class MyClass {
   Integer myInteger = 10;
   
   public void myMethod (Integer multiplier) {
      Integer multiplicationResult;
      multiplicationResult = multiplier*myInteger;
      System.debug('Multiplication is '+multiplicationResult);
   }
}

Đây là một lớp thể hiện, tức là, để gọi hoặc truy cập các biến hoặc phương thức của lớp này, bạn phải tạo một thể hiện của lớp này và sau đó bạn có thể thực hiện tất cả các thao tác.

// Object Creation
// Creating an object of class
MyClass objClass = new MyClass();

// Calling Class method using Class instance
objClass.myMethod(100);

sObject tạo

sObjects là các đối tượng của Salesforce mà bạn lưu trữ dữ liệu. Ví dụ: Tài khoản, Liên hệ, v.v., là các đối tượng tùy chỉnh. Bạn có thể tạo các thể hiện đối tượng của các sObjects này.

Sau đây là một ví dụ về khởi tạo sObject và cho thấy cách bạn có thể truy cập trường của đối tượng cụ thể đó bằng cách sử dụng ký hiệu dấu chấm và gán giá trị cho các trường.

// Execute the below code in Developer console by simply pasting it
// Standard Object Initialization for Account sObject
Account objAccount = new Account(); // Object initialization
objAccount.Name = 'Testr Account'; // Assigning the value to field Name of Account
objAccount.Description = 'Test Account';
insert objAccount; // Creating record using DML
System.debug('Records Has been created '+objAccount);

// Custom sObject initialization and assignment of values to field
APEX_Customer_c objCustomer = new APEX_Customer_c ();
objCustomer.Name = 'ABC Customer';
objCustomer.APEX_Customer_Decscription_c = 'Test Description';
insert objCustomer;
System.debug('Records Has been created '+objCustomer);

Khởi tạo tĩnh

Các phương thức và biến tĩnh chỉ được khởi tạo một lần khi một lớp được tải. Các biến tĩnh không được truyền như một phần của trạng thái xem cho trang Visualforce.

Sau đây là một ví dụ về phương thức Static cũng như biến Static.

// Sample Class Example with Static Method
public class MyStaticClass {
   Static Integer myInteger = 10;
   
   public static void myMethod (Integer multiplier) {
      Integer multiplicationResult;
      multiplicationResult = multiplier * myInteger;
      System.debug('Multiplication is '+multiplicationResult);
   }
}

// Calling the Class Method using Class Name and not using the instance object
MyStaticClass.myMethod(100);

Static Variable Use

Các biến static sẽ được khởi tạo chỉ một lần khi lớp được tải và hiện tượng này có thể được sử dụng để tránh đệ quy kích hoạt. Giá trị biến tĩnh sẽ giống nhau trong cùng một ngữ cảnh thực thi và bất kỳ lớp, trình kích hoạt hoặc mã nào đang thực thi đều có thể tham chiếu đến nó và ngăn chặn đệ quy.

Một giao diện giống như một lớp Apex trong đó không có phương thức nào được triển khai. Nó chỉ chứa các ký hiệu của phương thức, nhưng phần thân của mỗi phương thức là trống. Để sử dụng một giao diện, một lớp khác phải triển khai nó bằng cách cung cấp một phần thân cho tất cả các phương thức có trong giao diện.

Các giao diện được sử dụng chủ yếu để cung cấp lớp trừu tượng cho mã của bạn. Chúng tách việc triển khai khỏi khai báo phương thức.

Hãy lấy một ví dụ về Công ty Hóa chất của chúng tôi. Giả sử rằng chúng tôi cần cung cấp chiết khấu cho khách hàng Cao cấp và Thông thường và chiết khấu cho cả hai sẽ khác nhau.

Chúng tôi sẽ tạo một Giao diện được gọi là DiscountProcessor.

// Interface
public interface DiscountProcessor {
   Double percentageDiscountTobeApplied(); // method signature only
}

// Premium Customer Class
public class PremiumCustomer implements DiscountProcessor {
   
   //Method Call
   public Double percentageDiscountTobeApplied () {
      
      // For Premium customer, discount should be 30%
      return 0.30;
   }
}

// Normal Customer Class
public class NormalCustomer implements DiscountProcessor {
   
   // Method Call
   public Double percentageDiscountTobeApplied () {
      
      // For Premium customer, discount should be 10%
      return 0.10;
   }
}

Khi bạn triển khai Giao diện thì bắt buộc phải triển khai phương thức của Giao diện đó. Nếu bạn không triển khai các phương thức Giao diện, nó sẽ xuất hiện một lỗi. Bạn nên sử dụng Interfaces khi muốn bắt buộc nhà phát triển triển khai phương thức.

Giao diện Salesforce Tiêu chuẩn cho Batch Apex

SFDC có các giao diện tiêu chuẩn như Database.Batchable, Schedulable, v.v. Ví dụ: nếu bạn triển khai Giao diện Database.Batchable, thì bạn phải triển khai ba phương thức được xác định trong Giao diện - Bắt đầu, Thực thi và Kết thúc.

Dưới đây là một ví dụ cho Giao diện Cơ sở dữ liệu được cung cấp bởi Standard Salesforce, giao diện này sẽ gửi email cho người dùng với Trạng thái hàng loạt. Giao diện này có 3 phương thức là Start, Execute và Finish. Sử dụng giao diện này, chúng ta có thể triển khai chức năng Batchable và nó cũng cung cấp biến BatchableContext mà chúng ta có thể sử dụng để có thêm thông tin về Batch đang thực thi và thực hiện các chức năng khác.

global class CustomerProessingBatch implements Database.Batchable<sobject7>,
Schedulable {
   // Add here your email address
   global String [] email = new String[] {'[email protected]'};

   // Start Method
   global Database.Querylocator start (Database.BatchableContext BC) {
      
      // This is the Query which will determine the scope of Records and fetching the same
      return Database.getQueryLocator('Select id, Name, APEX_Customer_Status__c,
         APEX_Customer_Decscription__c From APEX_Customer__c WHERE createdDate = today
         && APEX_Active__c = true');
   }

   // Execute method
   global void execute (Database.BatchableContext BC, List<sobject> scope) {
      List<apex_customer__c> customerList = new List<apex_customer__c>();
      List<apex_customer__c> updtaedCustomerList = new List<apex_customer__c>();
      
      for (sObject objScope: scope) {
         // type casting from generic sOject to APEX_Customer__c
         APEX_Customer__c newObjScope = (APEX_Customer__c)objScope ;
         newObjScope.APEX_Customer_Decscription__c = 'Updated Via Batch Job';
         newObjScope.APEX_Customer_Status__c = 'Processed';
         
         // Add records to the List
         updtaedCustomerList.add(newObjScope);
      }

      // Check if List is empty or not
      if (updtaedCustomerList != null && updtaedCustomerList.size()>0) {
         
         // Update the Records
         Database.update(updtaedCustomerList); System.debug('List Size
            '+updtaedCustomerList.size());
      }
   }

   // Finish Method
   global void finish(Database.BatchableContext BC) {
      Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
      
      // get the job Id
      AsyncApexJob a = [Select a.TotalJobItems, a.Status, a.NumberOfErrors,
      a.JobType, a.JobItemsProcessed, a.ExtendedStatus, a.CreatedById,
      a.CompletedDate From AsyncApexJob a WHERE id = :BC.getJobId()];
      System.debug('$$$ Jobid is'+BC.getJobId());
      
      // below code will send an email to User about the status
      mail.setToAddresses(email);
     
      // Add here your email address
      mail.setReplyTo('[email protected]');
      mail.setSenderDisplayName('Apex Batch Processing Module');
      mail.setSubject('Batch Processing '+a.Status);
      mail.setPlainTextBody('The Batch Apex job processed
         '+a.TotalJobItems+'batches with '+a.NumberOfErrors+'failures'+'Job Item
         processed are'+a.JobItemsProcessed);
      Messaging.sendEmail(new Messaging.Singleemailmessage [] {mail});
   }

   // Scheduler Method to scedule the class
   global void execute(SchedulableContext sc) {
      CustomerProessingBatch conInstance = new CustomerProessingBatch();
      database.executebatch(conInstance,100);
   }
}

Để thực thi lớp này, bạn phải chạy đoạn mã dưới đây trong Bảng điều khiển dành cho nhà phát triển.

CustomerProessingBatch objBatch = new CustomerProessingBatch ();
Database.executeBatch(objBatch);

Trong chương này, chúng ta sẽ thảo luận về cách thực hiện các Chức năng Sửa đổi Cơ sở dữ liệu khác nhau trong Salesforce. Có hai lời nói mà chúng ta có thể thực hiện các chức năng.

Tuyên bố DML

DML là các hành động được thực hiện để thực hiện chèn, cập nhật, xóa, nâng cấp, khôi phục bản ghi, hợp nhất bản ghi hoặc chuyển đổi hoạt động dẫn.

DML là một trong những phần quan trọng nhất trong Apex vì hầu hết mọi trường hợp nghiệp vụ đều liên quan đến việc thay đổi và sửa đổi cơ sở dữ liệu.

Phương pháp cơ sở dữ liệu

Tất cả các hoạt động mà bạn có thể thực hiện bằng cách sử dụng các câu lệnh DML cũng có thể được thực hiện bằng các phương thức Cơ sở dữ liệu. Phương thức cơ sở dữ liệu là phương thức hệ thống mà bạn có thể sử dụng để thực hiện các hoạt động DML. Các phương thức cơ sở dữ liệu cung cấp tính linh hoạt hơn so với các Câu lệnh DML.

Trong chương này, chúng ta sẽ xem xét cách tiếp cận đầu tiên sử dụng Câu lệnh DML. Chúng ta sẽ xem xét các Phương thức Cơ sở dữ liệu trong chương tiếp theo.

Tuyên bố DML

Bây giờ chúng ta hãy xem xét trường hợp của công ty cung cấp hóa chất một lần nữa. Hồ sơ Hóa đơn của chúng tôi có các trường là Trạng thái, Số tiền đã trả, Số tiền còn lại, Ngày thanh toán tiếp theo và Số hóa đơn. Các hóa đơn đã được tạo ngày hôm nay và có trạng thái là 'Đang chờ xử lý', sẽ được cập nhật thành 'Đã thanh toán'.

Chèn hoạt động

Thao tác chèn được sử dụng để tạo bản ghi mới trong Cơ sở dữ liệu. Bạn có thể tạo bản ghi của bất kỳ đối tượng Chuẩn hoặc Tùy chỉnh nào bằng cách sử dụng câu lệnh Chèn DML.

Example

Chúng tôi có thể tạo bản ghi mới trong đối tượng APEX_Invoice__c vì các hóa đơn mới đang được tạo cho các đơn đặt hàng mới của khách hàng mỗi ngày. Trước tiên, chúng tôi sẽ tạo bản ghi Khách hàng và sau đó chúng tôi có thể tạo bản ghi Hóa đơn cho bản ghi Khách hàng mới đó.

// fetch the invoices created today, Note, you must have at least one invoice 
// created today

List<apex_invoice__c> invoiceList = [SELECT id, Name, APEX_Status__c,
   createdDate FROM APEX_Invoice__c WHERE createdDate = today];

// create List to hold the updated invoice records
List<apex_invoice__c> updatedInvoiceList = new List<apex_invoice__c>();
APEX_Customer__c objCust = new APEX_Customer__C();
objCust.Name = 'Test ABC';

//DML for Inserting the new Customer Records
insert objCust;
for (APEX_Invoice__c objInvoice: invoiceList) {
   if (objInvoice.APEX_Status__c == 'Pending') {
      objInvoice.APEX_Status__c = 'Paid';
      updatedInvoiceList.add(objInvoice);
   }
}

// DML Statement to update the invoice status
update updatedInvoiceList;

// Prints the value of updated invoices
System.debug('List has been updated and updated values are' + updatedInvoiceList);

// Inserting the New Records using insert DML statement
APEX_Invoice__c objNewInvoice = new APEX_Invoice__c();
objNewInvoice.APEX_Status__c = 'Pending';
objNewInvoice.APEX_Amount_Paid__c = 1000;
objNewInvoice.APEX_Customer__c = objCust.id;

// DML which is creating the new Invoice record which will be linked with newly
// created Customer record
insert objNewInvoice;
System.debug('New Invoice Id is '+objNewInvoice.id+' and the Invoice Number is'
   + objNewInvoice.Name);

Cập nhật hoạt động

Thao tác cập nhật là thực hiện cập nhật các bản ghi hiện có. Trong ví dụ này, chúng tôi sẽ cập nhật trường Trạng thái của bản ghi Hóa đơn hiện có thành 'Đã thanh toán'.

Example

// Update Statement Example for updating the invoice status. You have to create
and Invoice records before executing this code. This program is updating the
record which is at index 0th position of the List.

// First, fetch the invoice created today
List<apex_invoice__c> invoiceList = [SELECT id, Name, APEX_Status__c,
createdDate FROM APEX_Invoice__c];
List<apex_invoice__c> updatedInvoiceList = new List<apex_invoice__c>();

// Update the first record in the List
invoiceList[0].APEX_Status__c = 'Pending';
updatedInvoiceList.add(invoiceList[0]);

// DML Statement to update the invoice status
update updatedInvoiceList;

// Prints the value of updated invoices
System.debug('List has been updated and updated values of records are' 
   + updatedInvoiceList[0]);

Hoạt động nâng cấp

Hoạt động nâng cấp được sử dụng để thực hiện thao tác cập nhật và nếu bản ghi cần cập nhật không có trong cơ sở dữ liệu, thì hãy tạo bản ghi mới.

Example

Giả sử, các bản ghi khách hàng trong đối tượng Khách hàng cần được cập nhật. Chúng tôi sẽ cập nhật hồ sơ Khách hàng hiện có nếu nó đã có, nếu không, hãy tạo một hồ sơ mới. Điều này sẽ dựa trên giá trị của trường APEX_External_Id__c. Trường này sẽ là trường của chúng tôi để xác định xem các bản ghi đã có hay chưa.

Note - Trước khi thực thi mã này, vui lòng tạo bản ghi trong đối tượng Khách hàng với giá trị trường Id bên ngoài là '12341' và sau đó thực thi mã được cung cấp bên dưới -

// Example for upserting the Customer records
List<apex_customer__c> CustomerList = new List<apex_customer__c>();
for (Integer i = 0; i < 10; i++) {
   apex_customer__c objcust=new apex_customer__c(name = 'Test' +i,
   apex_external_id__c='1234' +i);
   customerlist.add(objcust);
} //Upserting the Customer Records

upsert CustomerList;

System.debug('Code iterated for 10 times and created 9 records as one record with 
   External Id 12341 is already present');

for (APEX_Customer_c objCustomer: CustomerList) {
   if (objCustomer.APEX_External_Id_c == '12341') {
      system.debug('The Record which is already present is '+objCustomer);
   }
}

Xóa hoạt động

Bạn có thể thực hiện thao tác xóa bằng Xóa DML.

Example

Trong trường hợp này, chúng tôi sẽ xóa các hóa đơn đã được tạo cho mục đích thử nghiệm, đó là những hóa đơn có tên là 'Thử nghiệm'.

Bạn cũng có thể thực thi đoạn mã này từ Bảng điều khiển dành cho nhà phát triển mà không cần tạo lớp.

// fetch the invoice created today
List<apex_invoice__c> invoiceList = [SELECT id, Name, APEX_Status__c,
createdDate FROM APEX_Invoice__c WHERE createdDate = today];
List<apex_invoice__c> updatedInvoiceList = new List<apex_invoice__c>();
APEX_Customer__c objCust = new APEX_Customer__C();
objCust.Name = 'Test';

// Inserting the Customer Records
insert objCust;
for (APEX_Invoice__c objInvoice: invoiceList) {
   if (objInvoice.APEX_Status__c == 'Pending') {
      objInvoice.APEX_Status__c = 'Paid';
      updatedInvoiceList.add(objInvoice);
   }
}

// DML Statement to update the invoice status
update updatedInvoiceList;

// Prints the value of updated invoices
System.debug('List has been updated and updated values are' + updatedInvoiceList);

// Inserting the New Records using insert DML statement
APEX_Invoice__c objNewInvoice = new APEX_Invoice__c();
objNewInvoice.APEX_Status__c = 'Pending';
objNewInvoice.APEX_Amount_Paid__c = 1000;
objNewInvoice.APEX_Customer__c = objCust.id;

// DML which is creating the new record
insert objNewInvoice;
System.debug('New Invoice Id is' + objNewInvoice.id);

// Deleting the Test invoices from Database
// fetch the invoices which are created for Testing, Select name which Customer Name
// is Test.
List<apex_invoice__c> invoiceListToDelete = [SELECT id FROM APEX_Invoice__c
   WHERE APEX_Customer__r.Name = 'Test'];

// DML Statement to delete the Invoices
delete invoiceListToDelete;
System.debug('Success, '+invoiceListToDelete.size()+' Records has been deleted');

Phục hồi hoạt động

Bạn có thể phục hồi bản ghi đã bị xóa và có trong Thùng rác. Tất cả các mối quan hệ mà bản ghi đã xóa có, cũng sẽ được khôi phục.

Example

Giả sử, các Bản ghi đã xóa trong ví dụ trước cần được khôi phục. Điều này có thể đạt được bằng cách sử dụng ví dụ sau. Mã trong ví dụ trước đã được sửa đổi cho ví dụ này.

// fetch the invoice created today
List<apex_invoice__c> invoiceList = [SELECT id, Name, APEX_Status__c,
createdDate FROM APEX_Invoice__c WHERE createdDate = today];
List<apex_invoice__c> updatedInvoiceList = new List<apex_invoice__c>();
APEX_Customer__c objCust = new APEX_Customer__C();
objCust.Name = 'Test';

// Inserting the Customer Records
insert objCust;
for (APEX_Invoice__c objInvoice: invoiceList) {
   if (objInvoice.APEX_Status__c == 'Pending') {
      objInvoice.APEX_Status__c = 'Paid';
      updatedInvoiceList.add(objInvoice);
   }
}

// DML Statement to update the invoice status
update updatedInvoiceList;

// Prints the value of updated invoices
System.debug('List has been updated and updated values are' + updatedInvoiceList);

// Inserting the New Records using insert DML statement
APEX_Invoice__c objNewInvoice = new APEX_Invoice__c();
objNewInvoice.APEX_Status__c = 'Pending';
objNewInvoice.APEX_Amount_Paid__c = 1000;
objNewInvoice.APEX_Customer__c = objCust.id;

// DML which is creating the new record
insert objNewInvoice;
System.debug('New Invoice Id is '+objNewInvoice.id);

// Deleting the Test invoices from Database
// fetch the invoices which are created for Testing, Select name which Customer Name
// is Test.
List<apex_invoice__c> invoiceListToDelete = [SELECT id FROM APEX_Invoice__c
   WHERE APEX_Customer__r.Name = 'Test'];

// DML Statement to delete the Invoices
delete invoiceListToDelete;
system.debug('Deleted Record Count is ' + invoiceListToDelete.size());
System.debug('Success, '+invoiceListToDelete.size() + 'Records has been deleted');

// Restore the deleted records using undelete statement
undelete invoiceListToDelete;
System.debug('Undeleted Record count is '+invoiceListToDelete.size()+'. This should 
   be same as Deleted Record count');

Phương thức lớp cơ sở dữ liệu là một cách khác để làm việc với các câu lệnh DML linh hoạt hơn các câu lệnh DML như chèn, cập nhật, v.v.

Sự khác biệt giữa phương thức cơ sở dữ liệu và câu lệnh DML

Tuyên bố DML Phương pháp cơ sở dữ liệu
Cập nhật một phần không được phép. Ví dụ: nếu bạn có 20 bản ghi trong danh sách, thì tất cả các bản ghi sẽ được cập nhật hoặc không có bản ghi nào. Cập nhật một phần được cho phép. Bạn có thể chỉ định Phương thức Tham số trong Cơ sở dữ liệu là true hoặc false, true để cho phép cập nhật một phần và false để không cho phép cập nhật tương tự.
Bạn không thể lấy danh sách các bản ghi thành công và thất bại. Bạn có thể lấy danh sách các bản ghi thành công và thất bại như chúng ta đã thấy trong ví dụ.
Example - chèn listName Example - Database.insert (listName, False), trong đó false cho biết rằng không được phép cập nhật một phần.

Chèn hoạt động

Việc chèn các bản ghi mới thông qua các phương thức cơ sở dữ liệu cũng khá đơn giản và linh hoạt. Chúng ta hãy xem xét kịch bản trước, trong đó, chúng ta đã chèn các bản ghi mới bằng cách sử dụng các câu lệnh DML. Chúng tôi sẽ chèn tương tự bằng cách sử dụng các phương pháp Cơ sở dữ liệu.

Thí dụ

// Insert Operation Using Database methods
// Insert Customer Records First using simple DML Statement. This Customer Record will be
// used when we will create Invoice Records
APEX_Customer__c objCust = new APEX_Customer__C();
objCust.Name = 'Test';
insert objCust; // Inserting the Customer Records

// Insert Operation Using Database methods
APEX_Invoice__c objNewInvoice = new APEX_Invoice__c();
List<apex_invoice__c> InvoiceListToInsert = new List<apex_invoice__c>();
objNewInvoice.APEX_Status__c = 'Pending';
objNewInvoice.APEX_Customer__c = objCust.id;
objNewInvoice.APEX_Amount_Paid__c = 1000;
InvoiceListToInsert.add(objNewInvoice);
Database.SaveResult[] srList = Database.insert(InvoiceListToInsert, false);

// Database method to insert the records in List
// Iterate through each returned result by the method

for (Database.SaveResult sr : srList) {
   if (sr.isSuccess()) {
      // This condition will be executed for successful records and will fetch the ids 
      // of successful records
      System.debug('Successfully inserted Invoice. Invoice ID: ' + sr.getId());
      // Get the invoice id of inserted Account
   } else {
      // This condition will be executed for failed records
      for(Database.Error objErr : sr.getErrors()) {
         System.debug('The following error has occurred.');
         
         // Printing error message in Debug log
         System.debug(objErr.getStatusCode() + ': ' + objErr.getMessage());
         System.debug('Invoice oject field which are affected by the error:' 
            + objErr.getFields());
      }
   }
}

Cập nhật hoạt động

Bây giờ chúng ta hãy xem xét ví dụ trường hợp kinh doanh của chúng ta bằng cách sử dụng các phương pháp cơ sở dữ liệu. Giả sử chúng ta cần cập nhật trường trạng thái của đối tượng Hóa đơn nhưng đồng thời, chúng ta cũng yêu cầu thông tin như trạng thái của bản ghi, id bản ghi không thành công, số lượng thành công, v.v. Điều này không thể thực hiện được bằng cách sử dụng Câu lệnh DML, do đó chúng ta phải sử dụng phương thức Cơ sở dữ liệu để có được tình trạng hoạt động của chúng tôi.

Thí dụ

Chúng tôi sẽ cập nhật trường 'Trạng thái' của Hóa đơn nếu nó ở trạng thái 'Đang chờ xử lý' và ngày tạo là hôm nay.

Mã đưa ra bên dưới sẽ giúp cập nhật các bản ghi Hóa đơn bằng phương pháp Database.update. Ngoài ra, hãy tạo bản ghi Hóa đơn trước khi thực thi mã này.

// Code to update the records using the Database methods
List<apex_invoice__c> invoiceList = [SELECT id, Name, APEX_Status__c,
   createdDate FROM APEX_Invoice__c WHERE createdDate = today];

// fetch the invoice created today
List<apex_invoice__c> updatedInvoiceList = new List<apex_invoice__c>();
for (APEX_Invoice__c objInvoice: invoiceList) {
   if (objInvoice.APEX_Status__c == 'Pending') {
      objInvoice.APEX_Status__c = 'Paid';
      updatedInvoiceList.add(objInvoice);    //Adding records to the list
   }
}

Database.SaveResult[] srList = Database.update(updatedInvoiceList, false);
// Database method to update the records in List

// Iterate through each returned result by the method
for (Database.SaveResult sr : srList) {
   if (sr.isSuccess()) {
      // This condition will be executed for successful records and will fetch
      // the ids of successful records
      System.debug('Successfully updated Invoice. Invoice ID is : ' + sr.getId());
   } else {
      // This condition will be executed for failed records
      for(Database.Error objErr : sr.getErrors()) {
         System.debug('The following error has occurred.');
         
         // Printing error message in Debug log
         System.debug(objErr.getStatusCode() + ': ' + objErr.getMessage());
         System.debug('Invoice oject field which are affected by the error:' 
            + objErr.getFields());
      }
   }
}

Chúng tôi sẽ chỉ xem xét các thao tác Chèn và Cập nhật trong hướng dẫn này. Các thao tác khác khá giống với các thao tác này và những gì chúng ta đã làm trong chương trước.

Mọi doanh nghiệp hoặc ứng dụng đều có chức năng tìm kiếm là một trong những yêu cầu cơ bản. Đối với điều này, Salesforce.com cung cấp hai cách tiếp cận chính sử dụng SOSL và SOQL. Chúng ta hãy thảo luận chi tiết về cách tiếp cận SOSL trong chương này.

SOSL

Tìm kiếm chuỗi văn bản trên đối tượng và trên toàn trường sẽ được thực hiện bằng cách sử dụng SOSL. Đây là Ngôn ngữ Tìm kiếm Đối tượng của Salesforce. Nó có khả năng tìm kiếm một chuỗi cụ thể trên nhiều đối tượng.

Các câu lệnh SOSL đánh giá một danh sách các sObject, trong đó, mỗi danh sách chứa các kết quả tìm kiếm cho một loại sObject cụ thể. Danh sách kết quả luôn được trả về theo thứ tự như chúng được chỉ định trong truy vấn SOSL.

Ví dụ về truy vấn SOSL

Hãy xem xét một trường hợp kinh doanh, trong đó, chúng ta cần phát triển một chương trình có thể tìm kiếm một chuỗi cụ thể. Giả sử, chúng ta cần tìm kiếm chuỗi 'ABC' trong trường Tên khách hàng của đối tượng Hóa đơn. Đoạn mã như sau:

Đầu tiên, bạn phải tạo một bản ghi duy nhất trong đối tượng Hóa đơn với tên Khách hàng là 'ABC' để chúng tôi có thể nhận được kết quả hợp lệ khi tìm kiếm.

// Program To Search the given string in all Object
// List to hold the returned results of sObject generic type
List<list<SObject>> invoiceSearchList = new List<List<SObject>>();

// SOSL query which will search for 'ABC' string in Customer Name field of Invoice Object
invoiceSearchList = [FIND 'ABC*' IN ALL FIELDS RETURNING APEX_Invoice_c
   (Id,APEX_Customer_r.Name)];

// Returned result will be printed
System.debug('Search Result '+invoiceSearchList);

// Now suppose, you would like to search string 'ABC' in two objects,
// that is Invoice and Account. Then for this query goes like this:

// Program To Search the given string in Invoice and Account object,
// you could specify more objects if you want, create an Account with Name as ABC.

// List to hold the returned results of sObject generic type
List<List<SObject>> invoiceAndSearchList = new List<List<SObject>>();

// SOSL query which will search for 'ABC' string in Invoice and in Account object's fields
invoiceAndSearchList = [FIND 'ABC*' IN ALL FIELDS RETURNING APEX_Invoice__c
   (Id,APEX_Customer__r.Name), Account];

// Returned result will be printed
System.debug('Search Result '+invoiceAndSearchList);

// This list will hold the returned results for Invoice Object
APEX_Invoice__c [] searchedInvoice = ((List<APEX_Invoice_c>)invoiceAndSearchList[0]);

// This list will hold the returned results for Account Object
Account [] searchedAccount = ((List<Account>)invoiceAndSearchList[1]);
System.debug('Value of searchedInvoice'+searchedInvoice+'Value of searchedAccount'
   + searchedAccount);

SOQL

Điều này gần giống như SOQL. Bạn có thể sử dụng điều này để tìm nạp các bản ghi đối tượng từ một đối tượng duy nhất tại một thời điểm. Bạn có thể viết các truy vấn lồng nhau và cũng có thể tìm nạp các bản ghi từ đối tượng mẹ hoặc con mà bạn đang truy vấn bây giờ.

Chúng ta sẽ tìm hiểu SOQL trong chương tiếp theo.

Đây là Ngôn ngữ Truy vấn Đối tượng Salesforce được thiết kế để hoạt động với Cơ sở dữ liệu SFDC. Nó có thể tìm kiếm một bản ghi trên một tiêu chí nhất định chỉ trong một sObject duy nhất.

Giống như SOSL, nó không thể tìm kiếm trên nhiều đối tượng nhưng nó hỗ trợ các truy vấn lồng nhau.

Ví dụ SOQL

Hãy xem xét ví dụ hiện tại của chúng tôi về Công ty Hóa chất. Giả sử, chúng ta cần một danh sách các bản ghi được tạo ngày hôm nay và có tên khách hàng không phải là 'thử nghiệm'. Trong trường hợp này, chúng tôi sẽ phải sử dụng truy vấn SOQL như được đưa ra bên dưới:

// fetching the Records via SOQL
List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
InvoiceList = [SELECT Id, Name, APEX_Customer__r.Name, APEX_Status__c FROM
   APEX_Invoice__c WHERE createdDate = today AND APEX_Customer__r.Name != 'Test'];
// SOQL query for given criteria

// Printing the fetched records
System.debug('We have total '+InvoiceList.size()+' Records in List');

for (APEX_Invoice__c objInvoice: InvoiceList) {
   System.debug('Record Value is '+objInvoice); 
   // Printing the Record fetched
}

Bạn có thể chạy truy vấn SOQL thông qua Trình soạn thảo truy vấn trong Bảng điều khiển dành cho nhà phát triển như được hiển thị bên dưới.

Chạy truy vấn được cung cấp bên dưới trong Bảng điều khiển dành cho nhà phát triển. Tìm kiếm các bản ghi Hóa đơn được tạo ngày hôm nay.

SELECT Id, Name, APEX_Customer__r.Name, APEX_Status__c FROM APEX_Invoice__c
   WHERE createdDate = today

Bạn phải chọn các trường mà bạn cần các giá trị, nếu không, nó có thể gây ra lỗi thời gian chạy.

Chuyển ngang các trường quan hệ

Đây là một trong những phần quan trọng nhất trong SFDC vì nhiều lần chúng ta cần xem qua mối quan hệ đối tượng con chính

Ngoài ra, có thể có trường hợp khi bạn cần chèn hai bản ghi đối tượng liên kết trong Cơ sở dữ liệu. Ví dụ, đối tượng Hóa đơn có mối quan hệ với đối tượng Khách hàng và do đó một Khách hàng có thể có nhiều hóa đơn.

Giả sử, bạn đang tạo hóa đơn và sau đó bạn cần liên kết hóa đơn này với Khách hàng. Bạn có thể sử dụng mã sau cho chức năng này -

// Now create the invoice record and relate it with the Customer object
// Before executing this, please create a Customer Records with Name 'Customer
// Creation Test'
APEX_Invoice__c objInvoice = new APEX_Invoice__c();

// Relating Invoice to customer via id field of Customer object
objInvoice.APEX_Customer__c = [SELECT id FROM APEX_Customer__c WHERE Name =
   'Customer Creation Test' LIMIT 1].id;
objInvoice.APEX_Status__c = 'Pending';
insert objInvoice;  //Creating Invoice
System.debug('Newly Created Invoice'+objInvoice);  //Newly created invoice

Thực thi đoạn mã này trong Bảng điều khiển dành cho nhà phát triển. Sau khi thực hiện, hãy sao chép Id hóa đơn từ Bảng điều khiển dành cho nhà phát triển và sau đó mở mã hóa đơn đó trong SFDC như được hiển thị bên dưới. Bạn có thể thấy rằng bản ghi Gốc đã được gán cho bản ghi Hóa đơn như hình dưới đây.

Tìm nạp bản ghi con

Bây giờ chúng ta hãy xem xét một ví dụ trong đó, tất cả các hóa đơn liên quan đến hồ sơ khách hàng cụ thể cần phải ở một nơi. Đối với điều này, bạn phải biết tên mối quan hệ con. Để xem tên quan hệ con, hãy chuyển đến trang chi tiết trường trên đối tượng con và kiểm tra giá trị "Mối quan hệ con". Trong ví dụ của chúng tôi, đó là các hóa đơn được thêm vào bởi __r ở cuối.

Thí dụ

Trong ví dụ này, chúng tôi sẽ cần thiết lập dữ liệu, tạo một khách hàng có tên là bản ghi 'Khách hàng ABC' và sau đó thêm 3 hóa đơn cho khách hàng đó.

Bây giờ, chúng tôi sẽ tìm nạp các hóa đơn của Khách hàng "Khách hàng ABC". Sau đây là truy vấn cho cùng -

// Fetching Child Records using SOQL
List<apex_customer__c> ListCustomers = [SELECT Name, Id, 
   (SELECT id, Name FROM Invoices__r) FROM APEX_Customer__c WHERE Name = 'ABC Customer'];

// Query for fetching the Child records along with Parent
System.debug('ListCustomers '+ListCustomers); // Parent Record

List<apex_invoice__c> ListOfInvoices = ListCustomers[0].Invoices__r;
// By this notation, you could fetch the child records and save it in List
System.debug('ListOfInvoices values of Child '+ListOfInvoices);
// Child records

Bạn có thể xem các giá trị Bản ghi trong Nhật ký gỡ lỗi.

Tìm nạp bản ghi gốc

Giả sử, bạn cần tìm nạp Tên khách hàng của hóa đơn vào ngày tạo là hôm nay, sau đó bạn có thể sử dụng truy vấn được cung cấp bên dưới cho tương tự -

Thí dụ

Tìm nạp giá trị của bản ghi gốc cùng với đối tượng con.

// Fetching Parent Record Field value using SOQL
List<apex_invoice__c> ListOfInvoicesWithCustomerName = new List<apex_invoice__c>();
ListOfInvoicesWithCustomerName = [SELECT Name, id, APEX_Customer__r.Name 
   FROM APEX_Invoice__c LIMIT 10];

// Fetching the Parent record's values
for (APEX_Invoice__c objInv: ListOfInvoicesWithCustomerName) {
   System.debug('Invoice Customer Name is '+objInv.APEX_Customer__r.Name);
   // Will print the values, all the Customer Records will be printed
}

Ở đây chúng tôi đã sử dụng ký hiệu APEX_Customer__r.Name, trong đó APEX_Customer__r là tên quan hệ mẹ, ở đây bạn phải thêm __r vào cuối trường Cha và sau đó bạn có thể tìm nạp giá trị trường mẹ.

Chức năng tổng hợp

SOQL có chức năng tổng hợp như chúng ta có trong SQL. Các hàm tổng hợp cho phép chúng ta cuộn lại và tóm tắt dữ liệu. Bây giờ chúng ta hãy hiểu chức năng một cách chi tiết.

Giả sử bạn muốn biết doanh thu trung bình mà chúng tôi nhận được từ Khách hàng 'Khách hàng ABC' là bao nhiêu, thì bạn có thể sử dụng hàm này để tính mức trung bình.

Thí dụ

// Getting Average of all the invoices for a Perticular Customer
AggregateResult[] groupedResults = [SELECT
   AVG(APEX_Amount_Paid__c)averageAmount FROM APEX_Invoice__c WHERE
   APEX_Customer__r.Name = 'ABC Customer'];
Object avgPaidAmount = groupedResults[0].get('averageAmount');
System.debug('Total Average Amount Received From Customer ABC is '+avgPaidAmount);

Kiểm tra đầu ra trong Nhật ký gỡ lỗi. Lưu ý rằng bất kỳ truy vấn nào bao gồm một hàm tổng hợp đều trả về kết quả của nó trong một mảngAggregateResultcác đối tượng. AggregateResult là một sObject chỉ đọc và chỉ được sử dụng cho các kết quả truy vấn. Nó rất hữu ích khi chúng ta cần tạo Báo cáo về dữ liệu lớn.

Cũng có các hàm tổng hợp khác mà bạn có thể được sử dụng để thực hiện tóm tắt dữ liệu.

MIN() - Điều này có thể được sử dụng để tìm giá trị nhỏ nhất

MAX() - Điều này có thể được sử dụng để tìm giá trị lớn nhất.

Các biến Apex ràng buộc

Bạn có thể sử dụng biến Apex trong truy vấn SOQL để tìm nạp kết quả mong muốn. Các biến Apex có thể được tham chiếu bởi ký hiệu Colon (:).

Thí dụ

// Apex Variable Reference
String CustomerName = 'ABC Customer';
List<apex_customer__c> ListCustomer = [SELECT Id, Name FROM APEX_Customer__c
   WHERE Name = :CustomerName];

// Query Using Apex variable
System.debug('ListCustomer Name'+ListCustomer); // Customer Name

Apex security đề cập đến quá trình áp dụng cài đặt bảo mật và thực thi các quy tắc chia sẻ về mã đang chạy. Các lớp Apex có cài đặt bảo mật có thể được kiểm soát thông qua hai từ khóa.

Quy tắc chia sẻ và bảo mật dữ liệu

Apex thường chạy trong ngữ cảnh hệ thống, tức là quyền của người dùng hiện tại. Bảo mật cấp trường và quy tắc chia sẻ không được tính đến trong quá trình thực thi mã. Chỉ mã khối ẩn danh thực thi với sự cho phép của người dùng đang thực thi mã.

Mã Apex của chúng tôi không được để lộ dữ liệu nhạy cảm cho Người dùng bị ẩn qua cài đặt bảo mật và chia sẻ. Do đó, bảo mật Apex và thực thi quy tắc chia sẻ là quan trọng nhất.

Với từ khóa chia sẻ

Nếu bạn sử dụng từ khóa này, thì mã Apex sẽ thực thi cài đặt Chia sẻ của người dùng hiện tại thành mã Apex. Điều này không thực thi quyền Hồ sơ, chỉ cài đặt chia sẻ mức dữ liệu.

Chúng ta hãy xem xét một ví dụ trong đó, Người dùng của chúng tôi có quyền truy cập vào 5 bản ghi, nhưng tổng số bản ghi là 10. Vì vậy, khi lớp Apex sẽ được khai báo với Từ khóa "Với Chia sẻ", nó sẽ chỉ trả về 5 bản ghi mà người dùng có quyền truy cập vào.

Example

Trước tiên, hãy đảm bảo rằng bạn đã tạo ít nhất 10 bản ghi trong đối tượng Khách hàng với "Tên" của 5 bản ghi là "Khách hàng ABC" và 5 bản ghi còn lại là "Khách hàng XYZ". Sau đó, tạo quy tắc chia sẻ sẽ chia sẻ 'Khách hàng ABC' với tất cả Người dùng. Chúng tôi cũng cần đảm bảo rằng chúng tôi đã đặt đối tượng OWD of Customer là Riêng tư.

Dán mã được cung cấp bên dưới vào khối Ẩn danh trong Bảng điều khiển dành cho nhà phát triển.

// Class With Sharing
public with sharing class MyClassWithSharing {
   // Query To fetch 10 records
   List<apex_customer__c> CustomerList = [SELECT id, Name FROM APEX_Customer__c LIMIT 10];
   
   public Integer executeQuery () {
      System.debug('List will have only 5 records and the actual records are' 
         + CustomerList.size()+' as user has access to'+CustomerList);
      Integer ListSize = CustomerList.size();
      return ListSize;
   }
}

// Save the above class and then execute as below
// Execute class using the object of class
MyClassWithSharing obj = new MyClassWithSharing();
Integer ListSize = obj.executeQuery();

Không có Từ khoá Chia sẻ

Như tên cho thấy, lớp được khai báo với từ khóa này thực thi ở chế độ Hệ thống, tức là, bất kể Người dùng truy cập vào bản ghi, truy vấn sẽ tìm nạp tất cả các bản ghi.

// Class Without Sharing
public without sharing class MyClassWithoutSharing {
   List<apex_customer__c> CustomerList = [SELECT id, Name FROM APEX_Customer__c LIMIT 10];
   
   // Query To fetch 10 records, this will return all the records
   public Integer executeQuery () {
      System.debug('List will have only 5 records and the actula records are'
         + CustomerList.size()+' as user has access to'+CustomerList);
      Integer ListSize = CustomerList.size();
      return ListSize;
   }
}
// Output will be 10 records.

Đặt bảo mật cho Apex Class

Bạn có thể bật hoặc tắt lớp Apex cho cấu hình cụ thể. Các bước tương tự được đưa ra dưới đây. Bạn có thể xác định hồ sơ nào nên có quyền truy cập vào lớp nào.

Đặt bảo mật lớp Apex từ trang danh sách lớp

Step 1 - Từ Thiết lập, nhấp vào Phát triển → Lớp Apex.

Step 2- Nhấp vào tên của lớp mà bạn muốn hạn chế. Chúng tôi đã nhấp vào CustomerOperationClass.

Step 3 - Nhấp vào Bảo mật.

Step 4 - Chọn cấu hình bạn muốn bật từ danh sách Cấu hình có sẵn và nhấp vào Thêm hoặc chọn cấu hình bạn muốn vô hiệu hóa từ danh sách Cấu hình đã bật và nhấp vào Xóa.

Step 5 - Nhấp vào Lưu.

Đặt Apex Security từ Permission Set

Step 1 - Từ Thiết lập, nhấp vào Quản lý Người dùng → Bộ Quyền.

Step 2 - Chọn một tập hợp quyền.

Step 3 - Nhấp vào Apex Class Access.

Step 4 - Nhấp vào Chỉnh sửa.

Step 5 - Chọn các lớp Apex mà bạn muốn bật từ danh sách Các lớp Apex Có sẵn và nhấp vào Thêm hoặc chọn các lớp Apex mà bạn muốn vô hiệu hóa từ danh sách Lớp Apex Đã bật và nhấp vào loại bỏ.

Step 6 - Nhấp vào nút Lưu.

Apex gọi là quá trình thực thi lớp Apex. Lớp Apex chỉ có thể được thực thi khi nó được gọi thông qua một trong các cách được liệt kê bên dưới:

  • Trình kích hoạt và khối ẩn danh

  • Một trình kích hoạt được gọi cho các sự kiện được chỉ định

  • Apex không đồng bộ

  • Lập lịch một lớp Apex để chạy theo các khoảng thời gian được chỉ định hoặc chạy một công việc hàng loạt

  • Lớp Dịch vụ Web

  • Lớp Dịch vụ Email Apex

  • Apex Web Services, cho phép hiển thị các phương pháp của bạn thông qua các dịch vụ Web SOAP và REST

  • Bộ điều khiển Visualforce

  • Dịch vụ email Apex để xử lý email đến

  • Gọi Apex bằng JavaScript

  • Bộ công cụ Ajax để gọi các phương thức dịch vụ Web được triển khai trong Apex

Bây giờ chúng ta sẽ hiểu một số cách phổ biến để gọi Apex.

Từ thực thi khối ẩn danh

Bạn có thể gọi lớp Apex thông qua thực thi ẩn danh trong Bảng điều khiển dành cho nhà phát triển như được hiển thị bên dưới:

Step 1 - Mở Bảng điều khiển dành cho nhà phát triển.

Step 2 - Nhấp vào Gỡ lỗi.

Step 3- Cửa sổ ẩn danh thực thi sẽ mở ra như hình dưới đây. Bây giờ, hãy nhấp vào nút Thực thi -

Step 4 - Mở Nhật ký gỡ lỗi khi nó xuất hiện trong ngăn Nhật ký.

Từ trình kích hoạt

Bạn cũng có thể gọi một lớp Apex từ Trigger. Các trình kích hoạt được gọi khi một sự kiện cụ thể xảy ra và các trình kích hoạt có thể gọi lớp Apex khi thực thi.

Sau đây là mã mẫu cho thấy cách một lớp được thực thi khi một Trigger được gọi.

Thí dụ

// Class which will gets called from trigger
public without sharing class MyClassWithSharingTrigger {

   public static Integer executeQuery (List<apex_customer__c> CustomerList) {
      // perform some logic and operations here
      Integer ListSize = CustomerList.size();
      return ListSize;
   }
}

// Trigger Code
trigger Customer_After_Insert_Example on APEX_Customer__c (after insert) {
   System.debug('Trigger is Called and it will call Apex Class');
   MyClassWithSharingTrigger.executeQuery(Trigger.new);  // Calling Apex class and 
                                                         // method of an Apex class
}

// This example is for reference, no need to execute and will have detail look on 
// triggers later chapters.

Từ mã bộ điều khiển trang Visualforce

Lớp Apex cũng có thể được gọi từ trang Visualforce. Chúng ta có thể chỉ định bộ điều khiển hoặc phần mở rộng bộ điều khiển và lớp Apex được chỉ định được gọi.

Thí dụ

VF Page Code

Apex Class Code (Controller Extension)

Trình kích hoạt Apex giống như các thủ tục được lưu trữ thực thi khi một sự kiện cụ thể xảy ra. Một trình kích hoạt thực thi trước và sau khi một sự kiện xảy ra trên hồ sơ.

Cú pháp

trigger triggerName on ObjectName (trigger_events) { Trigger_code_block }

Thực thi trình kích hoạt

Sau đây là các sự kiện mà chúng ta có thể xác nhận kích hoạt -

  • insert
  • update
  • delete
  • merge
  • upsert
  • undelete

Ví dụ về kích hoạt 1

Giả sử chúng tôi nhận được yêu cầu kinh doanh rằng chúng tôi cần tạo Bản ghi hóa đơn khi trường 'Trạng thái khách hàng' của Khách hàng chuyển thành Hoạt động từ Không hoạt động. Đối với điều này, chúng tôi sẽ tạo một trình kích hoạt trên đối tượng APEX_Customer__c bằng cách làm theo các bước sau:

Step 1 - Đi tới sObject

Step 2 - Nhấp vào Khách hàng

Step 3 - Nhấp vào nút 'Mới' trong danh sách liên quan đến Trình kích hoạt và thêm mã kích hoạt như cung cấp bên dưới.

// Trigger Code
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   List InvoiceList = new List();
   
   for (APEX_Customer__c objCustomer: Trigger.new) {
      
      if (objCustomer.APEX_Customer_Status__c == 'Active') {
         APEX_Invoice__c objInvoice = new APEX_Invoice__c();
         objInvoice.APEX_Status__c = 'Pending';
         InvoiceList.add(objInvoice);
      }
   }
   
   // DML to insert the Invoice List in SFDC
   insert InvoiceList;
}

Giải trình

Trigger.new- Đây là biến ngữ cảnh lưu trữ các bản ghi hiện tại trong ngữ cảnh kích hoạt, đang được chèn hoặc cập nhật. Trong trường hợp này, biến này có các bản ghi của đối tượng Khách hàng đã được cập nhật.

Có các biến ngữ cảnh khác có sẵn trong ngữ cảnh - trigger.old, trigger.newMap, trigger.OldMap.

Ví dụ về trình kích hoạt 2

Trình kích hoạt trên sẽ thực thi khi có thao tác cập nhật trên hồ sơ Khách hàng. Giả sử, bản ghi hóa đơn chỉ cần được chèn khi Trạng thái khách hàng chuyển từ Không hoạt động sang Hoạt động chứ không phải mọi lúc; đối với điều này, chúng ta có thể sử dụng một biến ngữ cảnh kháctrigger.oldMap sẽ lưu khóa dưới dạng id bản ghi và giá trị dưới dạng các giá trị bản ghi cũ.

// Modified Trigger Code
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
   
   for (APEX_Customer__c objCustomer: Trigger.new) {
      
      // condition to check the old value and new value
      if (objCustomer.APEX_Customer_Status__c == 'Active' &&
      
      trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
         APEX_Invoice__c objInvoice = new APEX_Invoice__c();
         objInvoice.APEX_Status__c = 'Pending';
         InvoiceList.add(objInvoice);
      }
   }
   
   // DML to insert the Invoice List in SFDC
   insert InvoiceList;
}

Giải trình

Chúng tôi đã sử dụng biến Trigger.oldMap mà như đã giải thích trước đó, là một biến ngữ cảnh lưu trữ Id và giá trị cũ của các bản ghi đang được cập nhật.

Các mẫu thiết kế được sử dụng để làm cho mã của chúng tôi hiệu quả hơn và tránh đạt đến giới hạn thống đốc. Thông thường các nhà phát triển có thể viết mã không hiệu quả có thể gây ra lặp lại các đối tượng. Điều này có thể dẫn đến mã không hiệu quả, hoạt động kém và có khả năng vi phạm các giới hạn của thống đốc. Điều này thường xảy ra nhất trong các trình kích hoạt, vì chúng có thể hoạt động dựa trên một tập hợp các bản ghi.

Chúng ta sẽ xem một số chiến lược thiết kế mẫu quan trọng trong chương này.

Mẫu thiết kế kích hoạt hàng loạt

Trong trường hợp kinh doanh thực tế, có thể bạn cần phải xử lý hàng nghìn bản ghi trong một lần. Nếu trình kích hoạt của bạn không được thiết kế để xử lý các tình huống như vậy, thì nó có thể bị lỗi khi xử lý hồ sơ. Có một số phương pháp hay nhất mà bạn cần tuân theo khi triển khai các trình kích hoạt. Tất cả các trình kích hoạt là trình kích hoạt hàng loạt theo mặc định và có thể xử lý nhiều bản ghi cùng một lúc. Bạn nên luôn có kế hoạch xử lý nhiều bản ghi cùng một lúc.

Hãy xem xét một trường hợp kinh doanh, trong đó, bạn cần xử lý số lượng lớn hồ sơ và bạn đã viết trình kích hoạt như được đưa ra bên dưới. Đây là ví dụ tương tự mà chúng tôi đã lấy để chèn bản ghi hóa đơn khi Trạng thái khách hàng thay đổi từ Không hoạt động thành Hoạt động.

// Bad Trigger Example
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   
   for (APEX_Customer__c objCustomer: Trigger.new) {
      
      if (objCustomer.APEX_Customer_Status__c == 'Active' && 
         trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
         
         // condition to check the old value and new value
         APEX_Invoice__c objInvoice = new APEX_Invoice__c();
         objInvoice.APEX_Status__c = 'Pending';
         insert objInvoice;   //DML to insert the Invoice List in SFDC
      }
   }
}

Bây giờ bạn có thể thấy rằng Tuyên bố DML đã được viết trong khối vòng lặp sẽ hoạt động khi chỉ xử lý một số bản ghi nhưng khi bạn đang xử lý một số hàng trăm bản ghi, nó sẽ đạt đến giới hạn Tuyên bố DML cho mỗi giao dịch là governor limit. Chúng tôi sẽ có một cái nhìn chi tiết về Giới hạn của Thống đốc trong một chương tiếp theo.

Để tránh điều này, chúng tôi phải làm cho trình kích hoạt hiệu quả để xử lý nhiều bản ghi cùng một lúc.

Ví dụ sau sẽ giúp bạn hiểu như vậy -

// Modified Trigger Code-Bulk Trigger
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
   
   for (APEX_Customer__c objCustomer: Trigger.new) {
      
      if (objCustomer.APEX_Customer_Status__c == 'Active' &&
         trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
         
         //condition to check the old value and new value
         APEX_Invoice__c objInvoice = new APEX_Invoice__c();
         objInvoice.APEX_Status__c = 'Pending';
         InvoiceList.add(objInvoice);//Adding records to List
      }
   }
   
   insert InvoiceList;
   // DML to insert the Invoice List in SFDC, this list contains the all records 
   // which need to be modified and will fire only one DML
}

Trình kích hoạt này sẽ chỉ kích hoạt 1 câu lệnh DML vì nó sẽ hoạt động trên một Danh sách và Danh sách có tất cả các bản ghi cần được sửa đổi.

Bằng cách này, bạn có thể tránh các giới hạn thống đốc câu lệnh DML.

Lớp trình trợ giúp kích hoạt

Viết toàn bộ mã trong trình kích hoạt cũng không phải là một thực hành tốt. Do đó, bạn nên gọi lớp Apex và ủy quyền xử lý từ Trigger sang lớp Apex như hình dưới đây. Lớp Trigger Helper là lớp thực hiện tất cả các xử lý cho trigger.

Hãy để chúng tôi xem xét lại ví dụ tạo bản ghi hóa đơn của chúng tôi.

// Below is the Trigger without Helper class
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
   
   for (APEX_Customer__c objCustomer: Trigger.new) {
      
      if (objCustomer.APEX_Customer_Status__c == 'Active' &&
         trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
         
         // condition to check the old value and new value
         APEX_Invoice__c objInvoice = new APEX_Invoice__c();
         objInvoice.APEX_Status__c = 'Pending';
         InvoiceList.add(objInvoice);
      }
   }
   
   insert InvoiceList; // DML to insert the Invoice List in SFDC
}

// Below is the trigger with helper class
// Trigger with Helper Class
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   CustomerTriggerHelper.createInvoiceRecords(Trigger.new, trigger.oldMap);
   // Trigger calls the helper class and does not have any code in Trigger
}

Lớp người trợ giúp

public class CustomerTriggerHelper {
   public static void createInvoiceRecords (List<apex_customer__c>
   
   customerList, Map<id, apex_customer__c> oldMapCustomer) {
      List<apex_invoice__c> InvoiceList = new Listvapex_invoice__c>();
      
      for (APEX_Customer__c objCustomer: customerList) {
         
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            oldMapCustomer.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            
            // condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            
            // objInvoice.APEX_Status__c = 'Pending';
            InvoiceList.add(objInvoice);
         }
      }
      
      insert InvoiceList;  // DML to insert the Invoice List in SFDC
   }
}

Trong điều này, tất cả quá trình xử lý đã được ủy quyền cho lớp người trợ giúp và khi chúng ta cần một chức năng mới, chúng ta có thể chỉ cần thêm mã vào lớp người trợ giúp mà không cần sửa đổi trình kích hoạt.

Kích hoạt đơn trên mỗi sObject

Luôn tạo một trình kích hoạt duy nhất trên mỗi đối tượng. Nhiều trình kích hoạt trên cùng một đối tượng có thể gây ra xung đột và lỗi nếu nó đạt đến giới hạn của thống đốc.

Bạn có thể sử dụng biến ngữ cảnh để gọi các phương thức khác nhau từ lớp trợ giúp theo yêu cầu. Hãy xem xét ví dụ trước của chúng tôi. Giả sử rằng phương thức createInvoice của chúng ta chỉ nên được gọi khi bản ghi được cập nhật và trên nhiều sự kiện. Sau đó, chúng tôi có thể kiểm soát việc thực thi như bên dưới:

// Trigger with Context variable for controlling the calling flow
trigger Customer_After_Insert on APEX_Customer__c (after update, after insert) {
   
   if (trigger.isAfter && trigger.isUpdate) {
      // This condition will check for trigger events using isAfter and isUpdate
      // context variable
      CustomerTriggerHelper.createInvoiceRecords(Trigger.new);
      
      // Trigger calls the helper class and does not have any code in Trigger
      // and this will be called only when trigger ids after update
   }
}

// Helper Class
public class CustomerTriggerHelper {
   
   //Method To Create Invoice Records
   public static void createInvoiceRecords (List<apex_customer__c> customerList) {
      
      for (APEX_Customer__c objCustomer: customerList) {
         
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            
            // condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            objInvoice.APEX_Status__c = 'Pending';
            InvoiceList.add(objInvoice);
         }
      }
      
      insert InvoiceList; // DML to insert the Invoice List in SFDC
   }
}

Các giới hạn thực thi của Thống đốc đảm bảo việc sử dụng tài nguyên hiệu quả trên nền tảng nhiều đối tượng Force.com. Đó là giới hạn do Salesforce.com chỉ định về việc thực thi mã để xử lý hiệu quả.

Giới hạn của Thống đốc là gì?

Như chúng ta đã biết, Apex chạy trong môi trường nhiều người thuê, tức là, một tài nguyên duy nhất được chia sẻ bởi tất cả các khách hàng và tổ chức. Vì vậy, cần phải đảm bảo rằng không ai độc quyền tài nguyên và do đó, Salesforce.com đã tạo ra bộ giới hạn chi phối và giới hạn việc thực thi mã. Bất cứ khi nào vượt qua bất kỳ giới hạn thống đốc nào, nó sẽ xuất hiện lỗi và sẽ tạm dừng việc thực thi chương trình.

Từ quan điểm của Nhà phát triển, điều quan trọng là đảm bảo rằng mã của chúng tôi phải có thể mở rộng và không đạt đến giới hạn.

Tất cả các giới hạn này được áp dụng trên cơ sở giao dịch. Một lần thực hiện kích hoạt duy nhất là một giao dịch.

Như chúng ta đã thấy, mẫu thiết kế trình kích hoạt giúp tránh lỗi giới hạn. Bây giờ chúng ta sẽ thấy những giới hạn quan trọng khác.

Tránh giới hạn truy vấn SOQL

Bạn chỉ có thể đưa ra 100 truy vấn cho mỗi giao dịch, nghĩa là khi mã của bạn sẽ đưa ra hơn 100 truy vấn SOQL thì nó sẽ báo lỗi.

Thí dụ

Ví dụ này cho thấy cách đạt đến giới hạn truy vấn SOQL:

Trình kích hoạt sau lặp lại danh sách khách hàng và cập nhật mô tả của bản ghi con (Hóa đơn) với chuỗi 'Ok to Pay'.

// Helper class:Below code needs o be checked.
public class CustomerTriggerHelper {
  
  public static void isAfterUpdateCall(Trigger.new) {
      createInvoiceRecords(trigger.new);//Method call
      updateCustomerDescription(trigger.new);
   }
   
   // Method To Create Invoice Records
   public static void createInvoiceRecords (List<apex_customer__c> customerList) {
      for (APEX_Customer__c objCustomer: customerList) {
         
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            
            // condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            objInvoice.APEX_Status__c = 'Pending';
            InvoiceList.add(objInvoice);
         }
      }
      insert InvoiceList; // DML to insert the Invoice List in SFDC
   }
   
   // Method to update the invoice records
   public static updateCustomerDescription (List<apex_customer__c> customerList) {
      for (APEX_Customer__c objCust: customerList) {
         List<apex_customer__c> invList = [SELECT Id, Name,
            APEX_Description__c FROM APEX_Invoice__c WHERE APEX_Customer__c = :objCust.id];
         
         // This query will fire for the number of records customer list has and will
         // hit the governor limit when records are more than 100
         for (APEX_Invoice__c objInv: invList) {
            objInv.APEX_Description__c = 'OK To Pay';
            update objInv;
            // Update invoice, this will also hit the governor limit for DML if large
            // number(150) of records are there
         }
      }
   }
}

Khi phương thức 'updateCustomerDescription' được gọi và số lượng bản ghi khách hàng nhiều hơn 100, thì nó sẽ đạt đến giới hạn SOQL. Để tránh điều này, đừng bao giờ viết truy vấn SOQL trong For Loop. Trong trường hợp này, truy vấn SOQL đã được viết trong vòng lặp For.

Sau đây là một ví dụ sẽ chỉ ra cách tránh DML cũng như giới hạn SOQL. Chúng tôi đã sử dụng truy vấn mối quan hệ lồng nhau để tìm nạp các bản ghi hóa đơn và sử dụng biến ngữ cảnhtrigger.newMap để lấy bản đồ id và hồ sơ Khách hàng.

// SOQL-Good Way to Write Query and avoid limit exception
// Helper Class
public class CustomerTriggerHelper {
   public static void isAfterUpdateCall(Trigger.new) {
      createInvoiceRecords(trigger.new);  //Method call
      updateCustomerDescription(trigger.new, trigger.newMap);
   }
   
   // Method To Create Invoice Records
   public static void createInvoiceRecords (List<apex_customer__c> customerList) {
      for (APEX_Customer__c objCustomer: customerList) {
         
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            
            // condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            objInvoice.APEX_Status__c = 'Pending';
            InvoiceList.add(objInvoice);
         }
      }
      insert InvoiceList; // DML to insert the Invoice List in SFDC
   }
   
   // Method to update the invoice records
   public static updateCustomerDescription (List<apex_customer__c>
      customerList, Map<id, apex_customer__c> newMapVariable) {
      List<apex_customer__c> customerListWithInvoice = [SELECT id,
         Name,(SELECT Id, Name, APEX_Description__c FROM APEX_Invoice__r) FROM
         APEX_Customer__c WHERE Id IN :newMapVariable.keySet()];
      
      // Query will be for only one time and fetches all the records
      List<apex_invoice__c> invoiceToUpdate = new
      List<apex_invoice__c>();
      
      for (APEX_Customer__c objCust: customerList) {
         for (APEX_Invoice__c objInv: invList) {
            objInv.APEX_Description__c = 'OK To Pay';
            invoiceToUpdate.add(objInv);
            // Add the modified records to List
         }
      }
      update invoiceToUpdate;
   }
}

Cuộc gọi hàng loạt DML

Ví dụ này cho thấy trình kích hoạt Hàng loạt cùng với mẫu lớp của trình trợ giúp trình kích hoạt. Bạn phải lưu lớp trợ giúp trước và sau đó lưu trình kích hoạt.

Note - Dán mã bên dưới vào lớp 'CustomerTriggerHelper' mà chúng tôi đã tạo trước đó.

// Helper Class
public class CustomerTriggerHelper {
   public static void isAfterUpdateCall(List<apex_customer__c> customerList,
      Map<id, apex_customer__c> mapIdToCustomers, Map<id, apex_customer__c>
      mapOldItToCustomers) {
      createInvoiceRecords(customerList, mapOldItToCustomers);   //Method call
      updateCustomerDescription(customerList,mapIdToCustomers,
      mapOldItToCustomers);
   }
   
   // Method To Create Invoice Records
   public static void createInvoiceRecords (List<apex_customer__c>
      customerList, Map<id, apex_customer__c> mapOldItToCustomers) {
      List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
      List<apex_customer__c> customerToInvoice = [SELECT id, Name FROM
         APEX_Customer__c LIMIT 1];
      
      for (APEX_Customer__c objCustomer: customerList) {
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            mapOldItToCustomers.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            //condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            objInvoice.APEX_Status__c = 'Pending';
            objInvoice.APEX_Customer__c = objCustomer.id;
            InvoiceList.add(objInvoice);
         }
      }
      system.debug('InvoiceList&&&'+InvoiceList);
      insert InvoiceList;
      // DML to insert the Invoice List in SFDC. This also follows the Bulk pattern
   }
   
   // Method to update the invoice records
   public static void updateCustomerDescription (List<apex_customer__c>
      customerList, Map<id, apex_customer__c> newMapVariable, Map<id,
      apex_customer__c> oldCustomerMap) {
      List<apex_customer__c> customerListWithInvoice = [SELECT id,
      Name,(SELECT Id, Name, APEX_Description__c FROM Invoices__r) FROM
         APEX_Customer__c WHERE Id IN :newMapVariable.keySet()];
   
      // Query will be for only one time and fetches all the records
      List<apex_invoice__c> invoiceToUpdate = new List<apex_invoice__c>();
      List<apex_invoice__c> invoiceFetched = new List<apex_invoice__c>();
      invoiceFetched = customerListWithInvoice[0].Invoices__r;
      system.debug('invoiceFetched'+invoiceFetched);
      system.debug('customerListWithInvoice****'+customerListWithInvoice);
   
      for (APEX_Customer__c objCust: customerList) {
         system.debug('objCust.Invoices__r'+objCust.Invoices__r);
         if (objCust.APEX_Active__c == true &&
            oldCustomerMap.get(objCust.id).APEX_Active__c == false) {
            for (APEX_Invoice__c objInv: invoiceFetched) {
               system.debug('I am in For Loop'+objInv);
               objInv.APEX_Description__c = 'OK To Pay';
               invoiceToUpdate.add(objInv);
               // Add the modified records to List
            }
         }
      }
     system.debug('Value of List ***'+invoiceToUpdate);
     update invoiceToUpdate;
      // This statement is Bulk DML which performs the DML on List and avoids
      // the DML Governor limit
   }
}

// Trigger Code for this class: Paste this code in 'Customer_After_Insert'
// trigger on Customer Object
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   CustomerTriggerHelper.isAfterUpdateCall(Trigger.new, trigger.newMap,
      trigger.oldMap);
   // Trigger calls the helper class and does not have any code in Trigger
}

Các giới hạn khác của Thống đốc Salesforce

Bảng sau liệt kê các giới hạn quan trọng của thống đốc.

Sự miêu tả Giới hạn
Tổng kích thước đống 6 MB / 12 MB
Tổng số câu lệnh DML đã phát hành 150
Tổng số bản ghi được truy xuất bởi một truy vấn SOSL 2000
Tổng số truy vấn SOSL đã phát hành 20
Tổng số bản ghi được truy xuất bởi Database.getQueryLocator 10000
Tổng số bản ghi được truy xuất bởi các truy vấn SOQL 50000

Trong chương này, chúng ta sẽ hiểu về Xử lý hàng loạt trong Apex. Hãy xem xét một tình huống trong đó, chúng tôi sẽ xử lý một số lượng lớn các bản ghi hàng ngày, có thể là làm sạch dữ liệu hoặc có thể xóa một số dữ liệu không sử dụng.

Batch Apex là gì?

Batch Apex là thực thi không đồng bộ của mã Apex, được thiết kế đặc biệt để xử lý số lượng lớn các bản ghi và có tính linh hoạt cao hơn trong giới hạn thống đốc so với mã đồng bộ.

Khi nào thì sử dụng Batch Apex?

  • Khi bạn muốn xử lý số lượng lớn bản ghi hàng ngày hoặc thậm chí vào khoảng thời gian cụ thể thì bạn có thể sử dụng Batch Apex.

  • Ngoài ra, khi bạn muốn một hoạt động là không đồng bộ thì bạn có thể triển khai Batch Apex. Batch Apex được hiển thị như một giao diện phải được triển khai bởi nhà phát triển. Các công việc hàng loạt có thể được gọi theo chương trình trong thời gian chạy bằng Apex. Batch Apex hoạt động trên các loạt bản ghi nhỏ, bao gồm toàn bộ tập hợp bản ghi của bạn và chia nhỏ quá trình xử lý thành các phần dữ liệu có thể quản lý được.

Sử dụng Batch Apex

Khi chúng ta đang sử dụng Batch Apex, chúng ta phải triển khai Database.Batchable giao diện do Salesforce cung cấp, rồi gọi lớp theo chương trình.

Bạn có thể theo dõi lớp học bằng cách làm theo các bước sau:

Để giám sát hoặc dừng việc thực hiện công việc hàng loạt Apex Batch, hãy đi tới Thiết lập → Giám sát → Công việc Apex hoặc Công việc → Công việc Apex.

Giao diện Database.Batchable có ba phương pháp sau cần được triển khai:

  • Start
  • Execute
  • Finish

Bây giờ chúng ta hãy hiểu chi tiết từng phương pháp.

Khởi đầu

Phương thức Start là một trong ba phương thức của giao diện Database.Batchable.

Syntax

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

Phương thức này sẽ được gọi khi bắt đầu Công việc Hàng loạt và thu thập dữ liệu mà Công việc Hàng loạt sẽ hoạt động.

Hãy xem xét các điểm sau để hiểu phương pháp:

  • Sử dụng Database.QueryLocatorđối tượng khi bạn đang sử dụng một truy vấn đơn giản để tạo phạm vi đối tượng được sử dụng trong công việc hàng loạt. Trong trường hợp này, giới hạn hàng dữ liệu SOQL sẽ bị bỏ qua.

  • Sử dụng đối tượng có thể lặp lại khi bạn có các tiêu chí phức tạp để xử lý các bản ghi. Database.QueryLocator xác định phạm vi của các bản ghi sẽ được xử lý.

Hành hình

Bây giờ chúng ta hãy hiểu phương thức Execute của giao diện Database.Batchable.

Syntax

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

trong đó, list <sObject <được trả về bởi phương thức Database.QueryLocator.

Phương thức này được gọi sau phương thức Start và thực hiện tất cả các xử lý cần thiết cho Batch Job.

Hoàn thành

Bây giờ chúng ta sẽ thảo luận về phương thức Kết thúc của giao diện Database.Batchable.

Syntax

global void finish(Database.BatchableContext BC) {}

Phương thức này được gọi ở cuối và bạn có thể thực hiện một số hoạt động hoàn thiện như gửi email với thông tin về tình trạng và hồ sơ công việc hàng loạt đã xử lý.

Ví dụ về Batch Apex

Hãy để chúng tôi xem xét một ví dụ về Công ty Hóa chất hiện tại của chúng tôi và giả định rằng chúng tôi có yêu cầu cập nhật trường Trạng thái Khách hàng và Mô tả Khách hàng của Hồ sơ Khách hàng đã được đánh dấu là Đang hoạt động và có Ngày như hôm nay. Việc này phải được thực hiện hàng ngày và phải gửi email cho Người dùng về trạng thái của Xử lý hàng loạt. Cập nhật Trạng thái Khách hàng là 'Đã xử lý' và Mô tả Khách hàng là 'Đã cập nhật Thông qua Công việc Hàng loạt'.

// Batch Job for Processing the Records
global class CustomerProessingBatch implements Database.Batchable<sobject> {
   global String [] email = new String[] {'[email protected]'};
   // Add here your email address here
  
   // Start Method
   global Database.Querylocator start (Database.BatchableContext BC) {
      return Database.getQueryLocator('Select id, Name, APEX_Customer_Status__c,
      APEX_Customer_Decscription__c From APEX_Customer__c WHERE createdDate = today
      AND APEX_Active__c = true');
      // Query which will be determine the scope of Records fetching the same
   }
   
   // Execute method
   global void execute (Database.BatchableContext BC, List<sobject> scope) {
      List<apex_customer__c> customerList = new List<apex_customer__c>();
      List<apex_customer__c> updtaedCustomerList = new List<apex_customer__c>();
      
      // List to hold updated customer
      for (sObject objScope: scope) {
         APEX_Customer__c newObjScope = (APEX_Customer__c)objScope ;
         
         // type casting from generic sOject to APEX_Customer__c
         newObjScope.APEX_Customer_Decscription__c = 'Updated Via Batch Job';
         newObjScope.APEX_Customer_Status__c = 'Processed';
         updtaedCustomerList.add(newObjScope); // Add records to the List
         System.debug('Value of UpdatedCustomerList '+updtaedCustomerList);
      }
      
      if (updtaedCustomerList != null && updtaedCustomerList.size()>0) {
         // Check if List is empty or not
         Database.update(updtaedCustomerList); System.debug('List Size '
          + updtaedCustomerList.size());
         // Update the Records
      }
   }
   
   // Finish Method
   global void finish(Database.BatchableContext BC) {
      Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
      
      // Below code will fetch the job Id
      AsyncApexJob a = [Select a.TotalJobItems, a.Status, a.NumberOfErrors,
      a.JobType, a.JobItemsProcessed, a.ExtendedStatus, a.CreatedById,
      a.CompletedDate From AsyncApexJob a WHERE id = :BC.getJobId()];
      
      // get the job Id
      System.debug('$$$ Jobid is'+BC.getJobId());
      
      // below code will send an email to User about the status
      mail.setToAddresses(email);
      mail.setReplyTo('[email protected]'); // Add here your email address
      mail.setSenderDisplayName('Apex Batch Processing Module');
      mail.setSubject('Batch Processing '+a.Status);
      mail.setPlainTextBody('The Batch Apex job processed'
         + a.TotalJobItems+'batches with '+a.NumberOfErrors+'failures'+'Job Item
      processed are'+a.JobItemsProcessed);
      Messaging.sendEmail(new Messaging.Singleemailmessage [] {mail});
   }
}

Để thực thi mã này, trước tiên hãy lưu nó và sau đó dán mã sau vào Thực thi ẩn danh. Thao tác này sẽ tạo đối tượng của lớp và phương thức Database.execute sẽ thực hiện công việc Batch. Sau khi công việc hoàn thành, một email sẽ được gửi đến địa chỉ email được chỉ định. Đảm bảo rằng bạn có hồ sơ khách hàng cóActive như đã kiểm tra.

// Paste in Developer Console
CustomerProessingBatch objClass = new CustomerProessingBatch();
Database.executeBatch (objClass);

Khi lớp này được thực thi, hãy kiểm tra địa chỉ email bạn đã cung cấp, nơi bạn sẽ nhận được email với thông tin. Ngoài ra, bạn có thể kiểm tra trạng thái của công việc hàng loạt thông qua trang Giám sát và các bước như được cung cấp ở trên.

Nếu bạn kiểm tra nhật ký gỡ lỗi, thì bạn có thể tìm thấy kích thước Danh sách cho biết có bao nhiêu bản ghi đã được xử lý.

Limitations

Chúng tôi chỉ có thể xử lý 5 công việc hàng loạt cùng một lúc. Đây là một trong những hạn chế của Batch Apex.

Lên lịch công việc hàng loạt Apex bằng Trang chi tiết Apex

Bạn có thể lên lịch lớp Apex qua trang chi tiết Apex như dưới đây:

Step 1 - Vào Setup ⇒ Apex Classes, Click vào Apex Classes.

Step 2 - Bấm vào nút Schedule Apex.

Step 3 - Cung cấp thông tin chi tiết.

Lên lịch công việc hàng loạt Apex bằng giao diện có thể lập lịch

Bạn có thể lên lịch công việc hàng loạt Apex bằng Giao diện có thể lập lịch như được cung cấp bên dưới -

// Batch Job for Processing the Records
global class CustomerProessingBatch implements Database.Batchable<sobject> {
   global String [] email = new String[] {'[email protected]'};
   // Add here your email address here
   
   // Start Method
   global Database.Querylocator start (Database.BatchableContext BC) {
      return Database.getQueryLocator('Select id, Name, APEX_Customer_Status__c,
      APEX_Customer_Decscription__c From APEX_Customer__c WHERE createdDate = today
      AND APEX_Active__c = true');
      // Query which will be determine the scope of Records fetching the same
   }
   
   // Execute method
   global void execute (Database.BatchableContext BC, List<sobject> scope) {
      List<apex_customer__c> customerList = new List<apex_customer__c>();
      List<apex_customer__c> updtaedCustomerList = new
      List<apex_customer__c>();//List to hold updated customer
      
      for (sObject objScope: scope) {
         APEX_Customer__c newObjScope = (APEX_Customer__c)objScope ;//type
         casting from generic sOject to APEX_Customer__c
         newObjScope.APEX_Customer_Decscription__c = 'Updated Via Batch Job';
         newObjScope.APEX_Customer_Status__c = 'Processed';
         updtaedCustomerList.add(newObjScope);//Add records to the List
         System.debug('Value of UpdatedCustomerList '+updtaedCustomerList);
      }
      
      if (updtaedCustomerList != null && updtaedCustomerList.size()>0) {
         // Check if List is empty or not
         Database.update(updtaedCustomerList); System.debug('List Size'
            + updtaedCustomerList.size());
         // Update the Records
      }
   }
 
   // Finish Method
   global void finish(Database.BatchableContext BC) {
      Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
      
      // Below code will fetch the job Id
      AsyncApexJob a = [Select a.TotalJobItems, a.Status, a.NumberOfErrors,
      a.JobType, a.JobItemsProcessed, a.ExtendedStatus, a.CreatedById,
      a.CompletedDate From AsyncApexJob a WHERE id = :BC.getJobId()];//get the job Id
      System.debug('$$$ Jobid is'+BC.getJobId());
      
      // below code will send an email to User about the status
      mail.setToAddresses(email);
      mail.setReplyTo('[email protected]');//Add here your email address
      mail.setSenderDisplayName('Apex Batch Processing Module');
      mail.setSubject('Batch Processing '+a.Status);
      mail.setPlainTextBody('The Batch Apex job processed' 
         + a.TotalJobItems+'batches with '+a.NumberOfErrors+'failures'+'Job Item
      processed are'+a.JobItemsProcessed);
      Messaging.sendEmail(new Messaging.Singleemailmessage [] {mail});
   }
   
   // Scheduler Method to scedule the class
   global void execute(SchedulableContext sc) {
      CustomerProessingBatch conInstance = new CustomerProessingBatch();
      database.executebatch(conInstance,100);
   }
}

// Paste in Developer Console
CustomerProessingBatch objClass = new CustomerProcessingBatch();
Database.executeBatch (objClass);

Gỡ lỗi là một phần quan trọng trong bất kỳ sự phát triển lập trình nào. Trong Apex, chúng tôi có một số công cụ nhất định có thể được sử dụng để gỡ lỗi. Một trong số đó là phương thức system.debug () in giá trị và đầu ra của biến trong các bản ghi gỡ lỗi.

Chúng ta có thể sử dụng hai công cụ sau để gỡ lỗi:

  • Ban điêu khiển cải tiên hơn
  • Nhật ký gỡ lỗi

Gỡ lỗi qua Bảng điều khiển dành cho nhà phát triển

Bạn có thể sử dụng Bảng điều khiển dành cho nhà phát triển và thực thi chức năng ẩn danh để gỡ lỗi Apex như bên dưới:

Example

Hãy xem xét ví dụ hiện có của chúng tôi về việc tìm nạp hồ sơ khách hàng đã được tạo ngày hôm nay. Chúng ta chỉ muốn biết truy vấn có trả về kết quả hay không và nếu có, thì chúng ta sẽ kiểm tra giá trị của List.

Dán đoạn mã dưới đây vào cửa sổ ẩn danh thực thi và làm theo các bước mà chúng tôi đã thực hiện để mở cửa sổ ẩn danh thực thi.

Step 1 - Mở Bảng điều khiển dành cho nhà phát triển

Step 2 - Mở Execute nặc danh từ 'Debug' như hình bên dưới.

Step 3 - Mở cửa sổ Execute Anonymous và dán đoạn mã sau vào và nhấp vào thực thi.

// Debugging The Apex
List<apex_customer__c> customerList = new List<apex_customer__c>();
customerList = [SELECT Id, Name FROM APEX_Customer__c WHERE CreatedDate =
today];
// Our Query
System.debug('Records on List are '+customerList+' And Records are '+customerList);
// Debug statement to check the value of List and Size

Step 4 - Mở Logs như hình bên dưới.

Step 5 - Nhập 'USER' vào điều kiện lọc như hình dưới đây.

Step 6 - Mở Tuyên bố NỢ NGƯỜI DÙNG như hình bên dưới.

Gỡ lỗi qua Nhật ký gỡ lỗi

Bạn cũng có thể gỡ lỗi cùng một lớp thông qua nhật ký gỡ lỗi. Giả sử, bạn có một trình kích hoạt trong đối tượng Khách hàng và nó cần được gỡ lỗi cho một số giá trị biến, thì bạn có thể thực hiện việc này thông qua nhật ký gỡ lỗi như được hiển thị bên dưới:

Đây là Mã kích hoạt cập nhật trường Mô tả nếu khách hàng được sửa đổi đang hoạt động và bạn muốn kiểm tra giá trị của các biến và bản ghi hiện có trong phạm vi -

trigger CustomerTrigger on APEX_Customer__c (before update) {
   List<apex_customer__c> customerList = new List<apex_customer__c>();
   for (APEX_Customer__c objCust: Trigger.new) {
      System.debug('objCust current value is'+objCust);
      
      if (objCust.APEX_Active__c == true) {
         objCust.APEX_Customer_Description__c = 'updated';
         System.debug('The record which has satisfied the condition '+objCust);
      }
   }
}

Làm theo các bước dưới đây để tạo nhật ký gỡ lỗi.

Step 1- Đặt nhật ký gỡ lỗi cho người dùng của bạn. Đi tới Thiết lập và nhập 'Nhật ký gỡ lỗi' trong cửa sổ thiết lập tìm kiếm và sau đó nhấp vào Liên kết.

Step 2 - Đặt các bản ghi gỡ lỗi như sau.

Step 3- Nhập tên Người dùng cần thiết lập. Nhập tên của bạn vào đây.

Step 4 - Sửa đổi hồ sơ khách hàng khi sự kiện sẽ xảy ra để tạo nhật ký gỡ lỗi.

Step 5- Bây giờ hãy chuyển đến phần nhật ký gỡ lỗi một lần nữa. Mở nhật ký gỡ lỗi và nhấp vào Đặt lại.

Step 6 - Nhấp vào liên kết xem nhật ký gỡ lỗi đầu tiên.

Step 7 - Tìm kiếm chuỗi 'USER' bằng cách sử dụng trình duyệt tìm kiếm như hình dưới đây.

Câu lệnh gỡ lỗi sẽ hiển thị giá trị của trường mà chúng ta đã đặt điểm.

Kiểm tra là phần tích hợp của Apex hoặc bất kỳ phát triển ứng dụng nào khác. Trong Apex, chúng tôi có các lớp thử nghiệm riêng biệt để phát triển cho tất cả thử nghiệm đơn vị.

Lớp kiểm tra

Trong SFDC, mã phải có độ phủ mã 75% để được triển khai cho Sản xuất. Vùng phủ mã này được thực hiện bởi các lớp thử nghiệm. Các lớp kiểm tra là các đoạn mã kiểm tra chức năng của lớp Apex khác.

Hãy để chúng tôi viết một lớp thử nghiệm cho một trong những mã của chúng tôi mà chúng tôi đã viết trước đó. Chúng tôi sẽ viết lớp thử nghiệm để bao gồm mã lớp Trình kích hoạt và Trình trợ giúp của chúng tôi. Dưới đây là lớp trình kích hoạt và trình trợ giúp cần được bao phủ.

// Trigger with Helper Class
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   CustomerTriggerHelper.createInvoiceRecords(Trigger.new, trigger.oldMap);
      //Trigger calls the helper class and does not have any code in Trigger
}

// Helper Class:
public class CustomerTriggerHelper {
   public static void createInvoiceRecords (List<apex_customer__c>
      
      customerList, Map<id, apex_customer__c> oldMapCustomer) {
      List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
      
      for (APEX_Customer__c objCustomer: customerList) {
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            oldMapCustomer.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            
            // condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            objInvoice.APEX_Status__c = 'Pending';
            objInvoice.APEX_Customer__c = objCustomer.id;
            InvoiceList.add(objInvoice);
         }
      }
      insert InvoiceList;  // DML to insert the Invoice List in SFDC
   }
}

Tạo lớp kiểm tra

Trong phần này, chúng ta sẽ hiểu cách tạo Lớp kiểm tra.

Tạo dữ liệu

Chúng ta cần tạo dữ liệu cho lớp thử nghiệm trong chính lớp thử nghiệm của chúng ta. Theo mặc định, lớp thử nghiệm không có quyền truy cập vào dữ liệu tổ chức nhưng nếu bạn đặt @isTest (seeAllData = true), thì lớp đó cũng sẽ có quyền truy cập vào dữ liệu của tổ chức.

Chú thích @isTest

Bằng cách sử dụng chú thích này, bạn đã tuyên bố rằng đây là một lớp thử nghiệm và nó sẽ không được tính vào tổng giới hạn mã của tổ chức.

từ khóa testMethod

Các phương pháp kiểm tra đơn vị là các phương pháp không nhận đối số, không cam kết dữ liệu vào cơ sở dữ liệu, không gửi email và được khai báo bằng từ khóa testMethod hoặc chú thích isTest trong định nghĩa phương thức. Ngoài ra, các phương thức kiểm tra phải được xác định trong các lớp kiểm tra, nghĩa là các lớp được chú thích bằng isTest.

Chúng tôi đã sử dụng phương pháp kiểm tra 'myUnitTest' trong các ví dụ của chúng tôi.

Test.startTest () và Test.stopTest ()

Đây là các phương pháp kiểm tra tiêu chuẩn có sẵn cho các lớp kiểm tra. Các phương thức này chứa sự kiện hoặc hành động mà chúng tôi sẽ mô phỏng thử nghiệm của mình. Giống như trong ví dụ này, chúng tôi sẽ kiểm tra trình kích hoạt và lớp trợ giúp của chúng tôi để mô phỏng trình kích hoạt cháy bằng cách cập nhật các bản ghi như chúng tôi đã thực hiện để bắt đầu và dừng khối. Điều này cũng cung cấp giới hạn thống đốc riêng cho mã nằm trong khối khởi động và khối dừng.

System.assert ()

Phương pháp này kiểm tra đầu ra mong muốn với thực tế. Trong trường hợp này, chúng tôi đang mong đợi một bản ghi Hóa đơn được chèn vào, vì vậy chúng tôi đã thêm xác nhận để kiểm tra như vậy.

Example

/**
* This class contains unit tests for validating the behavior of Apex classes
* and triggers.
*
* Unit tests are class methods that verify whether a particular piece
* of code is working properly. Unit test methods take no arguments,
* commit no data to the database, and are flagged with the testMethod
* keyword in the method definition.
*
* All test methods in an organization are executed whenever Apex code is deployed
* to a production organization to confirm correctness, ensure code
* coverage, and prevent regressions. All Apex classes are
* required to have at least 75% code coverage in order to be deployed
* to a production organization. In addition, all triggers must have some code coverage.
*
* The @isTest class annotation indicates this class only contains test
* methods. Classes defined with the @isTest annotation do not count against
* the organization size limit for all Apex scripts.
*
* See the Apex Language Reference for more information about Testing and Code Coverage.
*/

@isTest
private class CustomerTriggerTestClass {
   static testMethod void myUnitTest() {
      //Create Data for Customer Objet
      APEX_Customer__c objCust = new APEX_Customer__c();
      objCust.Name = 'Test Customer';
      objCust.APEX_Customer_Status__c = 'Inactive';
      insert objCust;
      
      // Now, our trigger will fire on After update event so update the Records
      Test.startTest();    // Starts the scope of test
      objCust.APEX_Customer_Status__c = 'Active';
      update objCust;
      Test.stopTest();     // Ends the scope of test
      
      // Now check if it is giving desired results using system.assert
      // Statement.New invoice should be created
      List<apex_invoice__c> invList = [SELECT Id, APEX_Customer__c FROM
         APEX_Invoice__c WHERE APEX_Customer__c = :objCust.id];
      system.assertEquals(1,invList.size());
      // Check if one record is created in Invoivce sObject
   }
}

Chạy lớp kiểm tra

Làm theo các bước dưới đây để chạy lớp thử nghiệm -

Step 1 - Vào các lớp Apex ⇒ nhấp vào tên lớp 'CustomerTriggerTestClass'.

Step 2 - Bấm vào nút Run Test như hình.

Step 3 - Kiểm tra trạng thái

Step 4 - Bây giờ kiểm tra lớp và kích hoạt mà chúng tôi đã viết bài kiểm tra

Lớp học

Kích hoạt

Thử nghiệm của chúng tôi thành công và hoàn thành.

Triển khai trong SFDC là gì?

Cho đến bây giờ chúng tôi đã phát triển mã trong Phiên bản dành cho nhà phát triển, nhưng trong trường hợp thực tế, bạn phải thực hiện việc phát triển này trong Hộp cát và sau đó bạn có thể cần triển khai mã này sang một hộp cát hoặc môi trường sản xuất khác và đây được gọi là triển khai. Tóm lại, đây là sự di chuyển của siêu dữ liệu từ tổ chức này sang tổ chức khác. Lý do đằng sau điều này là bạn không thể phát triển Apex trong tổ chức sản xuất Salesforce của mình. Người dùng trực tiếp truy cập vào hệ thống trong khi bạn đang phát triển có thể làm mất ổn định dữ liệu của bạn hoặc làm hỏng ứng dụng của bạn.

Các công cụ có sẵn để triển khai -

  • Force.com IDE
  • Thay đổi bộ
  • API SOAP
  • Công cụ di chuyển Force.com

Vì chúng tôi đang sử dụng Phiên bản dành cho nhà phát triển cho mục đích phát triển và học tập của mình, chúng tôi không thể sử dụng Bộ thay đổi hoặc các công cụ khác cần đến phiên bản dành cho doanh nghiệp SFDC hoặc phiên bản trả phí khác. Do đó, chúng tôi sẽ xây dựng phương pháp triển khai Force.com IDE trong hướng dẫn này.

Force.com Eclipse IDE

Step 1 - Mở Eclipse và mở trình kích hoạt lớp cần được triển khai.

Step 2 - Sau khi bạn nhấp vào 'Triển khai tới máy chủ', sau đó nhập tên người dùng và mật khẩu của tổ chức trong đó, Thành phần cần được triển khai.

Bằng cách thực hiện các bước đã đề cập ở trên, các thành phần Apex của bạn sẽ được triển khai cho tổ chức mục tiêu.

Triển khai bằng Tập hợp Thay đổi

Bạn có thể triển khai các quy tắc Xác thực, quy tắc dòng công việc, các lớp Apex và Trình kích hoạt từ tổ chức này sang tổ chức khác bằng cách kết nối chúng thông qua cài đặt triển khai. Trong trường hợp này, các tổ chức phải được kết nối.

Để mở thiết lập triển khai, hãy làm theo các bước dưới đây. Hãy nhớ rằng tính năng này không có sẵn trong Phiên bản dành cho nhà phát triển -

Step 1 - Vào Setup và tìm kiếm 'Deploy'.

Step 2 - Bấm vào 'Outbound Change Set' để tạo bộ thay đổi để triển khai.

Step 3 - Thêm các thành phần để thay đổi tập hợp bằng cách sử dụng nút 'Thêm', sau đó Lưu và nhấp vào Tải lên.

Step 4 - Vào Tổ chức mục tiêu và nhấp vào tập hợp thay đổi đầu vào và cuối cùng nhấp vào triển khai.

Lệnh gọi API SOAP để triển khai

Chúng tôi sẽ chỉ có một cái nhìn tổng quan nhỏ về phương pháp này vì đây không phải là phương pháp được sử dụng phổ biến.

Bạn có thể sử dụng các lệnh gọi phương thức được cung cấp bên dưới để triển khai siêu dữ liệu của mình.

  • compileAndTest()
  • compileClasses()
  • compileTriggers()

Công cụ di chuyển Force.com

Công cụ này được sử dụng để triển khai theo kịch bản. Bạn phải tải xuống công cụ Force.com Migration và sau đó bạn có thể thực hiện triển khai dựa trên tệp. Bạn có thể tải xuống công cụ di chuyển Force.com và sau đó thực hiện triển khai theo tập lệnh.