Apex - Kurzanleitung

Was ist Apex?

Apex ist eine proprietäre Sprache, die von Salesforce.com entwickelt wurde. Gemäß der offiziellen Definition ist Apex eine stark typisierte, objektorientierte Programmiersprache, mit der Entwickler die Flow- und Transaktionssteuerungsanweisungen auf dem Force.com-Plattformserver in Verbindung mit Aufrufen der Force.com-API ausführen können.

Es hat eine Java-ähnliche Syntax und verhält sich wie gespeicherte Datenbankprozeduren. Damit können die Entwickler den meisten Systemereignissen Geschäftslogik hinzufügen, einschließlich Schaltflächenklicks, zugehöriger Datensatzaktualisierungen und Visualforcepages.ApexCode kann durch Webdienstanforderungen und durch Auslöser für Objekte initiiert werden. Apex ist in der Performance Edition, der Unlimited Edition, der Enterprise Edition und der Developer Edition enthalten.

Funktionen von Apex als Sprache

Lassen Sie uns nun die Funktionen von Apex als Sprache diskutieren -

Integriert

Apex hat Unterstützung für DML-Operationen wie INSERT, UPDATE, DELETE und auch die Behandlung von DML-Ausnahmen integriert. Es unterstützt die Inline-Verarbeitung von SOQL- und SOSL-Abfragen, die den Satz von sObject-Datensätzen zurückgibt. Wir werden das sObject, SOQL, SOSL in zukünftigen Kapiteln im Detail untersuchen.

Java-ähnliche Syntax und einfach zu bedienen

Apex ist einfach zu bedienen, da es die Syntax wie Java verwendet. Zum Beispiel Variablendeklaration, Schleifensyntax und bedingte Anweisungen.

Stark in Daten integriert

Apex ist datenorientiert und so konzipiert, dass mehrere Abfragen und DML-Anweisungen zusammen ausgeführt werden. Es werden mehrere Transaktionsanweisungen in der Datenbank ausgegeben.

Stark getippt

Apex ist eine stark typisierte Sprache. Es verwendet einen direkten Verweis auf Schemaobjekte wie sObject und ein ungültiger Verweis schlägt schnell fehl, wenn er gelöscht wird oder vom falschen Datentyp ist.

Multitenant-Umgebung

Apex wird in einer Umgebung mit mehreren Mandanten ausgeführt. Folglich ist die Apex-Laufzeit-Engine so konzipiert, dass sie sich eng vor außer Kontrolle geratenem Code schützt und verhindert, dass gemeinsam genutzte Ressourcen monopolisiert werden. Jeder Code, der gegen Grenzwerte verstößt, schlägt mit leicht verständlichen Fehlermeldungen fehl.

Upgrades automatisch

Apex wird im Rahmen von Salesforce-Versionen aktualisiert. Wir müssen es nicht manuell aktualisieren.

Einfaches Testen

Apex bietet integrierte Unterstützung für die Erstellung und Ausführung von Komponententests, einschließlich Testergebnissen, die angeben, wie viel Code abgedeckt ist und welche Teile Ihres Codes effizienter sein können.

Wann sollte sich Entwickler für Apex entscheiden?

Apex sollte verwendet werden, wenn wir die komplexen Geschäftsfunktionen nicht mithilfe der vorgefertigten und vorhandenen sofort einsatzbereiten Funktionen implementieren können. Im Folgenden finden Sie die Fälle, in denen Apex über Salesforce-Konfiguration verwendet werden muss.

Apex-Anwendungen

Wir können Apex verwenden, wenn wir wollen -

  • Erstellen Sie Webdienste mit der Integration anderer Systeme.

  • Erstellen Sie E-Mail-Dienste für E-Mail-Explosion oder E-Mail-Einrichtung.

  • Führen Sie eine komplexe Validierung über mehrere Objekte gleichzeitig und eine benutzerdefinierte Validierungsimplementierung durch.

  • Erstellen Sie komplexe Geschäftsprozesse, die von vorhandenen Workflow-Funktionen oder -Flows nicht unterstützt werden.

  • Erstellen Sie eine benutzerdefinierte Transaktionslogik (Logik, die über die gesamte Transaktion hinweg auftritt, nicht nur mit einem einzelnen Datensatz oder Objekt), wie mit den Datenbankmethoden zum Aktualisieren der Datensätze.

  • Führen Sie eine Logik aus, wenn ein Datensatz geändert wird, oder ändern Sie den Datensatz des zugehörigen Objekts, wenn ein Ereignis vorliegt, das den Auslöser ausgelöst hat.

Arbeitsstruktur von Apex

Wie in der folgenden Abbildung (Referenz: Salesforce Developer-Dokumentation) dargestellt, wird Apex vollständig auf der Force.com-Plattform nach Bedarf ausgeführt

Ablauf der Aktionen

Es gibt zwei Abfolgen von Aktionen, wenn der Entwickler den Code speichert und wenn ein Endbenutzer eine Aktion ausführt, die den Apex-Code wie unten gezeigt aufruft.

Entwickleraktion

Wenn ein Entwickler Apex-Code schreibt und auf der Plattform speichert, kompiliert der Plattformanwendungsserver den Code zunächst in eine Reihe von Anweisungen, die vom Apex-Laufzeitinterpreter verstanden werden können, und speichert diese Anweisungen dann als Metadaten.

Endbenutzeraktion

Wenn ein Endbenutzer die Ausführung von Apex auslöst, indem er auf eine Schaltfläche klickt oder auf eine Visualforce-Seite zugreift, ruft der Plattformanwendungsserver die kompilierten Anweisungen aus den Metadaten ab und sendet sie über den Laufzeitinterpreter, bevor er das Ergebnis zurückgibt. Der Endbenutzer stellt keine Unterschiede in der Ausführungszeit im Vergleich zur Standardanforderung für die Anwendungsplattform fest.

Da Apex die proprietäre Sprache von Salesforce.com ist, werden einige Funktionen einer allgemeinen Programmiersprache nicht unterstützt. Im Folgenden sind einige Funktionen aufgeführt, die Apex nicht unterstützt:

  • Die Elemente in der Benutzeroberfläche können nicht angezeigt werden.

  • Sie können die von SFDC bereitgestellte Standardfunktionalität nicht ändern und es ist auch nicht möglich, die Ausführung der Standardfunktionalität zu verhindern.

  • Das Erstellen mehrerer Threads ist ebenfalls nicht möglich, da dies in anderen Sprachen möglich ist.

Grundlegendes zur Apex-Syntax

Apex-Code enthält normalerweise viele Dinge, die wir möglicherweise aus anderen Programmiersprachen kennen.

Variable Aussage

Als stark typisierte Sprache müssen Sie jede Variable mit Datentyp in Apex deklarieren. Wie im folgenden Code zu sehen (Abbildung unten), wird lstAcc mit dem Datentyp als Kontenliste deklariert.

SOQL-Abfrage

Dies wird verwendet, um die Daten aus der Salesforce-Datenbank abzurufen. Die im folgenden Screenshot gezeigte Abfrage ruft Daten vom Kontoobjekt ab.

Schleifenanweisung

Diese Schleifenanweisung wird zum Durchlaufen einer Liste oder zum Durchlaufen eines Codeteils für eine bestimmte Anzahl von Malen verwendet. In dem im folgenden Screenshot gezeigten Code entspricht die Iteration der Anzahl der Datensätze, die wir haben.

Flusskontrollanweisung

Die If-Anweisung wird in diesem Code zur Flusskontrolle verwendet. Unter bestimmten Bedingungen wird entschieden, ob die Ausführung ausgeführt oder die Ausführung des jeweiligen Codeteils gestoppt werden soll. In dem unten gezeigten Code wird beispielsweise geprüft, ob die Liste leer ist oder Datensätze enthält.

DML-Anweisung

Führt den Vorgang zum Einfügen, Aktualisieren, Aktualisieren und Löschen von Datensätzen für die Datensätze in der Datenbank aus. Der unten angegebene Code hilft beispielsweise beim Aktualisieren von Konten mit einem neuen Feldwert.

Im Folgenden finden Sie ein Beispiel dafür, wie ein Apex-Code-Snippet aussehen wird. In diesem Tutorial werden wir all diese Apex-Programmierkonzepte weiter untersuchen.

In diesem Kapitel werden wir die Umgebung für unsere Salesforce Apex-Entwicklung verstehen. Es wird davon ausgegangen, dass Sie bereits eine Salesforce-Edition für die Apex-Entwicklung eingerichtet haben.

Sie können den Apex-Code entweder in Sandbox oder in der Developer Edition von Salesforce entwickeln. Eine Sandbox-Organisation ist eine Kopie Ihrer Organisation, in die Sie Code schreiben und testen können, ohne das Risiko einer Datenänderung einzugehen oder die normale Funktionalität zu stören. Gemäß der üblichen industriellen Praxis müssen Sie den Code in Sandbox entwickeln und dann in der Produktionsumgebung bereitstellen.

Für dieses Lernprogramm verwenden wir die Developer Edition von Salesforce. In der Developer Edition haben Sie nicht die Möglichkeit, eine Sandbox-Organisation zu erstellen. Die Sandbox-Funktionen sind in anderen Editionen von Salesforce verfügbar.

Apex Code Development Tools

In allen Editionen können wir eines der folgenden drei Tools verwenden, um den Code zu entwickeln:

  • Force.com-Entwicklerkonsole
  • Force.com IDE
  • Code-Editor in der Salesforce-Benutzeroberfläche

Note − Wir werden die Entwicklerkonsole in unserem Tutorial für die Codeausführung verwenden, da sie einfach und benutzerfreundlich zum Lernen ist.

Force.com-Entwicklerkonsole

Die Entwicklerkonsole ist eine integrierte Entwicklungsumgebung mit einer Sammlung von Tools, mit denen Sie Anwendungen in Ihrer Salesforce-Organisation erstellen, debuggen und testen können.

Führen Sie die folgenden Schritte aus, um die Entwicklerkonsole zu öffnen.

Step 1 − Gehen Sie zu Name → Developer Console

Step 2 − Klicken Sie auf "Developer Console" und ein Fenster erscheint wie im folgenden Screenshot.

Im Folgenden finden Sie einige Vorgänge, die mit der Entwicklerkonsole ausgeführt werden können.

  • Writing and compiling code −Sie können den Code mit dem Quellcode-Editor schreiben. Wenn Sie einen Trigger oder eine Klasse speichern, wird der Code automatisch kompiliert. Kompilierungsfehler werden gemeldet.

  • Debugging −Sie können den Code mit dem Quellcode-Editor schreiben. Wenn Sie einen Trigger oder eine Klasse speichern, wird der Code automatisch kompiliert. Kompilierungsfehler werden gemeldet.

  • Testing − Sie können Debug-Protokolle anzeigen und Prüfpunkte festlegen, die beim Debuggen helfen.

  • Checking performance −Sie können Tests für bestimmte Testklassen oder alle Klassen in Ihrer Organisation ausführen und Testergebnisse anzeigen. Sie können auch die Codeabdeckung überprüfen.

  • SOQL queries − Sie können Debug-Protokolle überprüfen, um Leistungsengpässe festzustellen.

  • Color coding and autocomplete − Der Quellcode-Editor verwendet ein Farbschema zur leichteren Lesbarkeit von Codeelementen und bietet eine automatische Vervollständigung für Klassen- und Methodennamen.

Ausführen von Code in der Entwicklerkonsole

Alle in diesem Lernprogramm erwähnten Codefragmente müssen in der Entwicklerkonsole ausgeführt werden. Befolgen Sie diese Schritte, um die Schritte in der Entwicklerkonsole auszuführen.

Step 1 - Melden Sie sich mit Salesforce.com an login.salesforce.com. Kopieren Sie die im Tutorial erwähnten Codefragmente. Im Moment verwenden wir den folgenden Beispielcode.

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

Step 2 - Um die Entwicklerkonsole zu öffnen, klicken Sie auf Name → Entwicklerkonsole und dann wie unten gezeigt auf Anonym ausführen.

Step 3 - In diesem Schritt erscheint ein Fenster und Sie können den Code dort einfügen.

Step 4 - Wenn wir auf klicken Executewerden die Debug-Protokolle geöffnet. Sobald das Protokoll wie unten gezeigt im Fenster angezeigt wird, klicken Sie auf den Protokolldatensatz.

Geben Sie dann 'USER' in das unten gezeigte Fenster ein und die Ausgabeanweisung wird im Debug-Fenster angezeigt. Diese 'USER'-Anweisung wird zum Filtern der Ausgabe verwendet.

Im Grunde folgen Sie allen oben genannten Schritten, um ein Code-Snippet in diesem Tutorial auszuführen.

Beispiel für die Entwicklung von Unternehmensanwendungen

In unserem Tutorial implementieren wir die CRM-Anwendung für ein chemisches Geräte- und Verarbeitungsunternehmen. Diese Firma befasst sich mit Lieferanten und bietet Dienstleistungen an. Wir werden in unserem Tutorial kleine Codefragmente ausarbeiten, die sich auf dieses Beispiel beziehen, um jedes Konzept im Detail zu verstehen.

Zum Ausführen des Codes in diesem Lernprogramm müssen zwei Objekte erstellt werden: Kunden- und Rechnungsobjekte. Wenn Sie bereits wissen, wie diese Objekte in Salesforce erstellt werden, können Sie die folgenden Schritte überspringen. Andernfalls können Sie der folgenden Schritt-für-Schritt-Anleitung folgen.

Kundenobjekt erstellen

Wir werden zuerst das Kundenobjekt einrichten.

Step 1- Gehen Sie zu Setup und suchen Sie nach 'Objekt' wie unten gezeigt. Klicken Sie dann wie unten gezeigt auf den Link Objekte.

Step 2 - Sobald die Objektseite geöffnet ist, klicken Sie auf 'Create New Object'Taste wie unten gezeigt.

Step 3- Nach dem Klicken auf die Schaltfläche wird die Seite zur Erstellung neuer Objekte angezeigt, auf der Sie alle unten eingegebenen Objektdetails eingeben können. Der Objektname sollte Kunde sein. Sie müssen nur die Informationen in das Feld eingeben, wie im folgenden Screenshot gezeigt, und andere Standardeinstellungen beibehalten.

Geben Sie die Informationen ein und klicken Sie auf die Schaltfläche "Speichern".

Mit den obigen Schritten haben wir das Kundenobjekt erfolgreich erstellt.

Erstellen der benutzerdefinierten Felder für das Kundenobjekt

Nachdem wir unser Kundenobjekt eingerichtet haben, erstellen wir ein Feld 'Aktiv'. Anschließend können Sie die anderen Felder erstellen, indem Sie ähnliche Schritte ausführen. Der Name und der API-Name des Feldes werden im Screenshot angegeben.

Step 1- Wir erstellen ein Feld mit dem Namen 'Aktiv' vom Datentyp als Kontrollkästchen. Gehen Sie zu Setup und klicken Sie darauf.

Step 2 - Suchen Sie wie unten gezeigt nach 'Objekt' und klicken Sie darauf.

Step 3 - Klicken Sie auf das Objekt 'Kunde'.

Step 4 - Wenn Sie auf den Link Kundenobjekt geklickt haben und die Objektdetailseite angezeigt wird, klicken Sie auf die Schaltfläche Neu.

Step 5 - Aktivieren Sie nun den Datentyp als Kontrollkästchen und klicken Sie auf Weiter.

Step 6 - Geben Sie den Feldnamen und die Bezeichnung wie unten gezeigt ein.

Step 7 - Klicken Sie auf Sichtbar und dann auf Weiter.

Step 8 - Klicken Sie nun auf 'Speichern'.

Wenn Sie die obigen Schritte ausführen, wird unser benutzerdefiniertes Feld "Aktiv" erstellt. Sie müssen alle oben genannten Schritte zur Erstellung benutzerdefinierter Felder für die verbleibenden Felder ausführen. Dies ist die endgültige Ansicht des Kundenobjekts, sobald alle Felder erstellt wurden.

Rechnungsobjekt erstellen

Step 1 - Gehen Sie zu Setup und suchen Sie nach 'Objekt'. Klicken Sie dann wie unten gezeigt auf den Link Objekte.

Step 2 - Sobald die Objektseite geöffnet ist, klicken Sie wie unten gezeigt auf die Schaltfläche 'Neues Objekt erstellen'.

Step 3- Nach dem Klicken auf die Schaltfläche wird die Seite zur Erstellung neuer Objekte angezeigt (siehe Abbildung unten). Sie müssen die Details hier eingeben. Der Objektname sollte Rechnung sein. Dies ähnelt der Erstellung des Kundenobjekts weiter oben in diesem Lernprogramm.

Step 4 - Geben Sie die Informationen wie unten gezeigt ein und klicken Sie dann auf die Schaltfläche 'Speichern'.

Wenn Sie diese Schritte ausführen, wird Ihr Rechnungsobjekt erstellt.

Erstellen der benutzerdefinierten Felder für das Rechnungsobjekt

Wir werden das Feld Beschreibung auf Rechnungsobjekt wie unten gezeigt erstellen -

Step 1 - Gehen Sie zu Setup und klicken Sie darauf.

Step 2 - Suchen Sie wie unten gezeigt nach 'Objekt' und klicken Sie darauf.

Step 3 - Klicken Sie auf das Objekt 'Rechnung'.

Und dann klicken Sie auf "Neu".

Step 4 - Wählen Sie den Datentyp als Textbereich und klicken Sie dann auf Weiter.

Step 5 - Geben Sie die unten angegebenen Informationen ein.

Step 6 - Klicken Sie auf Sichtbar und dann auf Weiter.

Step 7 - Klicken Sie auf Speichern.

Ebenso können Sie die anderen Felder im Rechnungsobjekt erstellen.

Auf diese Weise haben wir die Objekte erstellt, die für dieses Tutorial benötigt werden. In den folgenden Kapiteln werden wir anhand dieser Objekte verschiedene Beispiele lernen.

Grundlegendes zu den Datentypen

Die Apex-Sprache ist stark typisiert, sodass jede Variable in Apex mit dem spezifischen Datentyp deklariert wird. Alle Apex-Variablen werden anfänglich auf Null initialisiert. Es wird einem Entwickler immer empfohlen, sicherzustellen, dass den Variablen die richtigen Werte zugewiesen werden. Andernfalls lösen solche Variablen bei Verwendung Nullzeigerausnahmen oder nicht behandelte Ausnahmen aus.

Apex unterstützt die folgenden Datentypen:

  • Primitiv (Integer, Double, Long, Date, Datetime, String, ID oder Boolean)

  • Sammlungen (Listen, Sets und Karten) (In Kapitel 6 zu behandeln)

  • sObject

  • Enums

  • Klassen, Objekte und Schnittstellen (in Kapitel 11, 12 und 13 zu behandeln)

In diesem Kapitel werden alle primitiven Datentypen, sObjects und Enums behandelt. In den kommenden Kapiteln werden wir uns mit Sammlungen, Klassen, Objekten und Schnittstellen befassen, da diese Schlüsselthemen sind, die individuell erlernt werden müssen.

Primitive Datentypen

In diesem Abschnitt werden die von Apex unterstützten primitiven Datentypen erläutert.

Ganze Zahl

Eine 32-Bit-Zahl ohne Dezimalpunkt. Der Wertebereich hierfür beginnt bei -2.147.483.648 und der Maximalwert liegt bei 2.147.483.647.

Example

Wir wollen eine Variable deklarieren, die die Menge der Fässer speichert, die an den Käufer der chemischen Verarbeitungsanlage geliefert werden müssen.

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

Das System.debug() Die Funktion gibt den Wert der Variablen aus, damit wir damit debuggen oder wissen können, welchen Wert die Variable derzeit hat.

Fügen Sie den obigen Code in die Entwicklerkonsole ein und klicken Sie auf Ausführen. Sobald die Protokolle generiert wurden, wird der Wert der Variablen "BarrelNumbers" als 1000 angezeigt.

Boolescher Wert

Diese Variable kann entweder wahr, falsch oder null sein. Oft kann dieser Variablentyp als Flag bei der Programmierung verwendet werden, um festzustellen, ob die bestimmte Bedingung gesetzt ist oder nicht.

Example

Wenn der boolesche VersandDispatched als true festgelegt werden soll, kann er als - deklariert werden

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

Datum

Dieser Variablentyp gibt ein Datum an. Dies kann nur das Datum und nicht die Uhrzeit speichern. Um das Datum zusammen mit der Uhrzeit zu speichern, müssen wir es in der Variablen DateTime speichern.

Example

Betrachten Sie das folgende Beispiel, um zu verstehen, wie die Datumsvariable funktioniert.

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

Lange

Dies ist eine 64-Bit-Zahl ohne Dezimalpunkt. Dies wird verwendet, wenn wir einen Wertebereich benötigen, der breiter ist als die von Integer bereitgestellten.

Example

Wenn der Umsatz des Unternehmens gespeichert werden soll, verwenden wir den Datentyp Long.

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

Objekt

Wir können dies als jeden Datentyp bezeichnen, der in Apex unterstützt wird. Beispielsweise kann die Klassenvariable ein Objekt dieser Klasse sein, und der generische Typ sObject ist ebenfalls ein Objekt, und ein ähnlich spezifischer Objekttyp wie Account ist ebenfalls ein Objekt.

Example

Betrachten Sie das folgende Beispiel, um zu verstehen, wie die Objektvariable funktioniert.

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

Note - Sie können auch ein Objekt mit vordefinierter Klasse erstellen, wie unten angegeben. -

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

Dies ist das Klassenobjekt, das als Klassenvariable verwendet wird.

String

Zeichenfolge ist ein beliebiger Satz von Zeichen in einfachen Anführungszeichen. Die Anzahl der Zeichen ist unbegrenzt. Hier wird die Heap-Größe verwendet, um die Anzahl der Zeichen zu bestimmen. Dies schränkt das Ressourcenmonopol des Apex-Programms ein und stellt auch sicher, dass es nicht zu groß wird.

Example

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

Zeit

Diese Variable wird verwendet, um die bestimmte Zeit zu speichern. Diese Variable sollte immer mit der statischen Systemmethode deklariert werden.

Klecks

Der Blob ist eine Sammlung von Binärdaten, die als Objekt gespeichert werden. Dies wird verwendet, wenn der Anhang in Salesforce in einer Variablen gespeichert werden soll. Dieser Datentyp konvertiert die Anhänge in ein einzelnes Objekt. Wenn der Blob in einen String konvertiert werden soll, können wir die Methoden toString und valueOf für denselben verwenden.

sObjekt

Dies ist ein spezieller Datentyp in Salesforce. Es ähnelt einer Tabelle in SQL und enthält Felder, die Spalten in SQL ähneln. Es gibt zwei Arten von Objekten - Standard und Benutzerdefiniert.

Beispielsweise ist Account ein Standard-sObject und jedes andere benutzerdefinierte Objekt (wie das von uns erstellte Kundenobjekt) ist ein benutzerdefiniertes sObject.

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);

Aufzählung

Enum ist ein abstrakter Datentyp, der einen Wert einer endlichen Menge angegebener Bezeichner speichert. Mit dem Schlüsselwort Enum können Sie eine Enum definieren. Enum kann wie jeder andere Datentyp in Salesforce verwendet werden.

Example

Sie können die möglichen Namen der chemischen Verbindung deklarieren, indem Sie den folgenden Code ausführen:

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

Java und Apex ähneln sich in vielerlei Hinsicht. Die Variablendeklaration in Java und Apex ist ebenfalls ziemlich gleich. Wir werden einige Beispiele diskutieren, um zu verstehen, wie lokale Variablen deklariert werden.

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

Beachten Sie, dass allen Variablen der Wert null zugewiesen ist.

Declaring Variables

Sie können die Variablen in Apex wie String und Integer wie folgt deklarieren:

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

Apex variables are Case-Insensitive

Dies bedeutet, dass der unten angegebene Code einen Fehler auslöst, da die Variable 'm' zweimal deklariert wurde und beide als gleich behandelt werden.

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

Eine Apex-Variable ist ab dem Punkt gültig, an dem sie im Code deklariert ist. Es ist also nicht erlaubt, dieselbe Variable erneut und im Codeblock neu zu definieren. Wenn Sie eine Variable in einer Methode deklarieren, ist dieser Variablenbereich nur auf diese bestimmte Methode beschränkt. Auf Klassenvariablen kann jedoch in der gesamten Klasse zugegriffen werden.

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>();

String in Apex ist wie in jeder anderen Programmiersprache ein beliebiger Zeichensatz ohne Zeichenbeschränkung.

Example

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

String-Methoden

Die Zeichenfolgenklasse in Salesforce verfügt über viele Methoden. Wir werden uns einige der wichtigsten und am häufigsten verwendeten String-Methoden in diesem Kapitel ansehen.

enthält

Diese Methode gibt true zurück, wenn die angegebene Zeichenfolge den genannten Teilstring enthält.

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);

gleich

Diese Methode gibt true zurück, wenn die angegebene Zeichenfolge und die in der Methode übergebene Zeichenfolge dieselbe binäre Zeichenfolge haben und nicht null sind. Mit dieser Methode können Sie auch die SFDC-Datensatz-ID vergleichen. Bei dieser Methode wird zwischen Groß- und Kleinschreibung unterschieden.

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

Diese Methode gibt true zurück, wenn stringtoCompare dieselbe Zeichenfolge wie die angegebene Zeichenfolge hat. Bei dieser Methode wird jedoch nicht zwischen Groß- und Kleinschreibung unterschieden.

Syntax

public Boolean equalsIgnoreCase(String stringtoCompare)

Example

Der folgende Code gibt true zurück, da Zeichenfolgen und Sequenzen identisch sind, wobei die Groß- und Kleinschreibung ignoriert wird.

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);

entfernen

Diese Methode entfernt die in stringToRemove bereitgestellte Zeichenfolge aus der angegebenen Zeichenfolge. Dies ist nützlich, wenn Sie bestimmte Zeichen aus der Zeichenfolge entfernen möchten und den genauen Index der zu entfernenden Zeichen nicht kennen. Diese Methode unterscheidet zwischen Groß- und Kleinschreibung und funktioniert nicht, wenn dieselbe Zeichenfolge auftritt, die Groß- und Kleinschreibung jedoch unterschiedlich ist.

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

Diese Methode entfernt die in stringToRemove bereitgestellte Zeichenfolge aus der angegebenen Zeichenfolge, jedoch nur, wenn sie am Ende auftritt. Diese Methode unterscheidet nicht zwischen Groß- und Kleinschreibung.

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);

beginnt mit

Diese Methode gibt true zurück, wenn die angegebene Zeichenfolge mit dem in der Methode angegebenen Präfix beginnt.

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);

Arrays in Apex sind grundsätzlich dieselben wie Listen in Apex. Es gibt keine logische Unterscheidung zwischen Arrays und Listen, da ihre interne Datenstruktur und Methoden ebenfalls identisch sind, aber die Array-Syntax ist wie bei Java wenig traditionell.

Unten ist die Darstellung einer Reihe von Produkten -

Index 0 - HCL

Index 1 - H2SO4

Index 2 - NACL

Index 3 - H2O

Index 4 - N2

Index 5 - U296

Syntax

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

Beispiel

Angenommen, wir müssen den Namen unserer Produkte speichern - wir können das Array verwenden, in dem wir die Produktnamen wie unten gezeigt speichern. Sie können auf das jeweilige Produkt zugreifen, indem Sie den Index angeben.

//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]);
}

Zugriff auf das Array-Element mithilfe des Index

Sie können auf jedes Element im Array zugreifen, indem Sie den unten gezeigten Index verwenden.

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

Wie in jeder anderen Programmiersprache sind Konstanten die Variablen, die ihren Wert nicht ändern, sobald sie deklariert oder einem Wert zugewiesen wurden.

In Apex werden Konstanten verwendet, wenn Variablen definiert werden sollen, die während der gesamten Programmausführung einen konstanten Wert haben sollen. Apex-Konstanten werden mit dem Schlüsselwort 'final' deklariert.

Beispiel

Betrachten Sie a CustomerOperationClass Klasse und eine konstante Variable regularCustomerDiscount drin -

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;
   }
}

Um die Ausgabe der obigen Klasse anzuzeigen, müssen Sie den folgenden Code im anonymen Fenster der Entwicklerkonsole ausführen:

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

Entscheidungsstrukturen erfordern, dass der Programmierer eine oder mehrere Bedingungen angibt, die vom Programm bewertet oder getestet werden sollen, zusammen mit einer Anweisung oder Anweisungen, die ausgeführt werden sollen, wenn die Bedingung als wahr bestimmt wird, und optional andere Anweisungen, die ausgeführt werden sollen, wenn die Bedingung wird als falsch bestimmt.

In diesem Kapitel werden wir die grundlegende und fortgeschrittene Struktur von Entscheidungsfindung und bedingten Aussagen in Apex untersuchen. Die Entscheidungsfindung ist erforderlich, um den Ausführungsfluss zu steuern, wenn bestimmte Bedingungen erfüllt sind oder nicht. Es folgt die allgemeine Form einer typischen Entscheidungsstruktur, die in den meisten Programmiersprachen zu finden ist

Sr.Nr. Aussage & Beschreibung
1 if-Anweisung

Eine if-Anweisung besteht aus einem booleschen Ausdruck, gefolgt von einer oder mehreren Anweisungen.

2 if ... else-Anweisung

Auf eine if-Anweisung kann eine optionale Anweisung folgen else Anweisung, die ausgeführt wird, wenn der Boolesche Ausdruck false ist.

3 if ... elseif ... else-Anweisung

Auf eine if-Anweisung kann eine optionale Anweisung folgen else if...else Anweisung, die sehr nützlich ist, um verschiedene Bedingungen mit einer einzelnen if ... else if-Anweisung zu testen.

4 verschachtelte if-Anweisung

Sie können eine verwenden if or else if Aussage in einem anderen if or else if Aussage (n).

Schleifen werden verwendet, wenn ein bestimmter Code mit der gewünschten Anzahl von Iterationen wiederholt werden soll. Apex unterstützt den traditionellen Standard für Schleifen sowie andere erweiterte Schleifentypen. In diesem Kapitel werden wir ausführlich auf die Schleifen in Apex eingehen.

Eine Schleifenanweisung ermöglicht es uns, eine Anweisung oder eine Gruppe von Anweisungen mehrmals auszuführen. Das Folgende ist das Allgemeine einer Schleifenanweisung in den meisten Programmiersprachen -

In den folgenden Tabellen sind die verschiedenen Schleifen aufgeführt, die die Schleifenanforderungen in der Apex-Programmiersprache behandeln. Klicken Sie auf die folgenden Links, um deren Details zu überprüfen.

Sr.Nr. Schleifentyp & Beschreibung
1 für Schleife

Diese Schleife führt eine Reihe von Anweisungen für jedes Element in einer Reihe von Datensätzen aus.

2 SOQL für Schleife

Führen Sie eine Folge von Anweisungen direkt über der zurückgegebenen SOQL-Abfrage aus.

3 Java-ähnliche for-Schleife

Führen Sie eine Folge von Anweisungen in traditioneller Java-ähnlicher Syntax aus.

4 while-Schleife

Wiederholt eine Anweisung oder eine Gruppe von Anweisungen, während eine bestimmte Bedingung erfüllt ist. Es testet die Bedingung, bevor der Schleifenkörper ausgeführt wird.

5 do ... while-Schleife

Wie eine while-Anweisung, nur dass sie die Bedingung am Ende des Schleifenkörpers testet.

Sammlungen ist ein Variablentyp, der mehrere Datensätze speichern kann. Beispielsweise kann List mehrere Datensätze von Kontoobjekten speichern. Lassen Sie uns nun einen detaillierten Überblick über alle Sammlungsarten geben.

Listen

Die Liste kann eine beliebige Anzahl von Datensätzen von Grundelementen, Sammlungen, sObjects, benutzerdefinierten und im Apex-Typ integrierten Datensätzen enthalten. Dies ist eine der wichtigsten Arten der Sammlung und verfügt über einige Systemmethoden, die speziell auf die Verwendung mit List zugeschnitten sind. Der Listenindex beginnt immer mit 0. Dies gilt auch für das Array in Java. Eine Liste sollte mit dem Schlüsselwort 'Liste' deklariert werden.

Example

Unten finden Sie die Liste, die die Liste eines primitiven Datentyps (Zeichenfolge) enthält, dh die Liste der Städte.

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

Das Deklarieren der Anfangswerte der Liste ist optional. Wir werden hier jedoch die Anfangswerte deklarieren. Das Folgende ist ein Beispiel, das dasselbe zeigt.

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

Kontenliste (sObject)

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

Wir können auch die verschachtelte Liste deklarieren. Es kann bis zu fünf Ebenen gehen. Dies wird als mehrdimensionale Liste bezeichnet.

Dies ist die Liste der Ganzzahlen.

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

Die Liste kann eine beliebige Anzahl von Datensätzen enthalten, die Größe des Heapspeichers ist jedoch begrenzt, um das Leistungsproblem zu vermeiden und die Ressourcen zu monopolisieren.

Methoden für Listen

Für Listen stehen Methoden zur Verfügung, die wir beim Programmieren verwenden können, um einige Funktionen wie das Berechnen der Listengröße, das Hinzufügen eines Elements usw. zu erreichen.

Im Folgenden sind einige der am häufigsten verwendeten Methoden aufgeführt:

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

Das folgende Beispiel zeigt die Verwendung all dieser Methoden

// 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);

Sie können auch die Array-Notation verwenden, um die Liste wie unten angegeben zu deklarieren. Dies ist jedoch keine allgemeine Vorgehensweise bei der Apex-Programmierung.

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

Sets

Ein Set ist ein Sammlungstyp, der mehrere ungeordnete eindeutige Datensätze enthält. Ein Set kann keine doppelten Datensätze enthalten. Sets können wie Listen verschachtelt werden.

Example

Wir werden die Produktreihe definieren, die das Unternehmen verkauft.

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

Methoden für Mengen

Set unterstützt Methoden, die wir beim Programmieren verwenden können, wie unten gezeigt (wir erweitern das obige Beispiel) -

// 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);

Karten

Es ist ein Schlüsselwertpaar, das den eindeutigen Schlüssel für jeden Wert enthält. Sowohl Schlüssel als auch Wert können von einem beliebigen Datentyp sein.

Example

Das folgende Beispiel zeigt die Karte des Produktnamens mit dem Produktcode.

// 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);

Methoden für Karten

Im Folgenden finden Sie einige Beispiele, die die Methoden demonstrieren, die mit Map verwendet werden können.

// 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);

Kartenwerte sind möglicherweise ungeordnet. Daher sollten wir uns nicht auf die Reihenfolge verlassen, in der die Werte gespeichert sind, und versuchen, immer mit Schlüsseln auf die Karte zuzugreifen. Der Kartenwert kann null sein. Map-Schlüssel, wenn sie als String deklariert werden, unterscheiden zwischen Groß- und Kleinschreibung. Beispielsweise werden ABC und abc als unterschiedliche Schlüssel betrachtet und als eindeutig behandelt.

Was ist eine Klasse?

Eine Klasse ist eine Vorlage oder ein Entwurf, aus dem Objekte erstellt werden. Ein Objekt ist eine Instanz einer Klasse. Dies ist die Standarddefinition von Klasse. Apex-Klassen ähneln Java-Klassen.

Zum Beispiel, InvoiceProcessorKlasse beschreibt die Klasse, die alle Methoden und Aktionen enthält, die auf der Rechnung ausgeführt werden können. Wenn Sie eine Instanz dieser Klasse erstellen, wird diese die einzelne Rechnung darstellen, die sich derzeit im Kontext befindet.

Klassen erstellen

Sie können Klassen in Apex auch über die Entwicklerkonsole, die Force.com Eclipse-IDE und die Detailseite der Apex-Klasse erstellen.

Von der Entwicklerkonsole

Führen Sie die folgenden Schritte aus, um eine Apex-Klasse in der Entwicklerkonsole zu erstellen.

Step 1 - Gehen Sie zu Name und klicken Sie auf die Entwicklerkonsole.

Step 2 - Klicken Sie auf Datei ⇒ Neu und dann auf die Apex-Klasse.

Von Force.com IDE

Führen Sie die folgenden Schritte aus, um eine Klasse aus Force.com IDE zu erstellen.

Step 1 - Öffnen Sie die Force.com Eclipse IDE

Step 2 - Erstellen Sie ein neues Projekt, indem Sie auf Datei ⇒ Neu ⇒ Apex-Klasse klicken.

Step 3 - Geben Sie den Namen für die Klasse ein und klicken Sie auf OK.

Sobald dies erledigt ist, wird die neue Klasse erstellt.

Von der Apex Class Detail Page

Führen Sie die folgenden Schritte aus, um eine Klasse auf der Apex-Klassendetailseite zu erstellen.

Step 1 - Klicken Sie auf Name ⇒ Setup.

Step 2- Suchen Sie nach 'Apex Class' und klicken Sie auf den Link. Daraufhin wird die Seite mit den Apex-Klassendetails geöffnet.

Step 3 - Klicken Sie auf 'Neu', geben Sie den Namen für die Klasse ein und klicken Sie dann auf Speichern.

Apex-Klassenstruktur

Unten finden Sie die Beispielstruktur für die Apex-Klassendefinition.

Syntax

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

Diese Definition verwendet eine Kombination aus Zugriffsmodifikatoren, Freigabemodi, Klassennamen und Klassenkörper. Wir werden alle diese Optionen weiter untersuchen.

Example

Es folgt eine Beispielstruktur für die Apex-Klassendefinition:

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;
   }
}

Zugriffsmodifikatoren

Privat

Wenn Sie den Zugriffsmodifikator als "Privat" deklarieren, ist diese Klasse nur lokal bekannt und Sie können außerhalb dieses bestimmten Teils nicht auf diese Klasse zugreifen. Standardmäßig haben Klassen diesen Modifikator.

Öffentlichkeit

Wenn Sie die Klasse als 'Öffentlich' deklarieren, bedeutet dies, dass diese Klasse für Ihre Organisation und Ihren definierten Namespace zugänglich ist. Normalerweise werden die meisten Apex-Klassen mit diesem Schlüsselwort definiert.

Global

Wenn Sie die Klasse als "global" deklarieren, können alle Apex-Codes unabhängig von Ihrer Organisation darauf zugreifen. Wenn Sie eine Methode mit dem Schlüsselwort web service definiert haben, müssen Sie die enthaltende Klasse mit dem globalen Schlüsselwort deklarieren.

Modi teilen

Lassen Sie uns nun die verschiedenen Arten des Teilens diskutieren.

Mit Teilen

Dies ist eine Besonderheit von Apex-Klassen in Salesforce. Wenn eine Klasse mit dem Schlüsselwort "With Sharing" angegeben wird, hat dies folgende Auswirkungen: Wenn die Klasse ausgeführt wird, werden die Zugriffseinstellungen und die Profilberechtigung des Benutzers berücksichtigt. Angenommen, die Aktion des Benutzers hat die Datensatzaktualisierung für 30 Datensätze ausgelöst, aber der Benutzer hat nur Zugriff auf 20 Datensätze und 10 Datensätze sind nicht verfügbar. Wenn die Klasse dann die Aktion zum Aktualisieren der Datensätze ausführt, werden nur 20 Datensätze aktualisiert, auf die der Benutzer Zugriff hat, und die restlichen 10 Datensätze werden nicht aktualisiert. Dies wird auch als Benutzermodus bezeichnet.

Ohne zu teilen

Selbst wenn der Benutzer keinen Zugriff auf 10 von 30 Datensätzen hat, werden alle 30 Datensätze aktualisiert, wenn die Klasse im Systemmodus ausgeführt wird, dh sie wurde mit dem Schlüsselwort Without Sharing definiert. Dies wird als Systemmodus bezeichnet.

Virtuell

Wenn Sie das Schlüsselwort 'virtual' verwenden, bedeutet dies, dass diese Klasse erweitert werden kann und Überschreibungen zulässig sind. Wenn die Methoden überschrieben werden müssen, sollten die Klassen mit dem Schlüsselwort virtual deklariert werden.

Abstrakt

Wenn Sie die Klasse als 'abstrakt' deklarieren, enthält sie nur die Signatur der Methode und nicht die tatsächliche Implementierung.

Klassenvariablen

Syntax

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

In der obigen Syntax -

  • Variablendatentyp und Variablenname sind obligatorisch
  • Zugriffsmodifikatoren und Wert sind optional.

Example

public static final Integer myvalue;

Klassenmethoden

Es gibt zwei Modifikatoren für Klassenmethoden in Apex - Public oder Protected. Der Rückgabetyp ist für die Methode obligatorisch. Wenn die Methode nichts zurückgibt, müssen Sie als Rückgabetyp void angeben. Zusätzlich wird Body für die Methode benötigt.

Syntax

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

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

Erklärung der Syntax

Die in eckigen Klammern angegebenen Parameter sind optional. Die folgenden Komponenten sind jedoch unerlässlich:

  • return_data_type
  • method_name

Zugriffsmodifikatoren für Klassenmethoden

Mithilfe von Zugriffsmodifikatoren können Sie die Zugriffsebene für die Klassenmethoden angeben. Zum Beispiel kann von überall in der Klasse und außerhalb der Klasse auf die öffentliche Methode zugegriffen werden. Auf die private Methode kann nur innerhalb der Klasse zugegriffen werden. Global ist für alle Apex-Klassen zugänglich und kann als Webdienstmethode verfügbar gemacht werden, auf die andere Apex-Klassen zugreifen können.

Example

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

Diese Methode hat den Rückgabetyp Integer und akzeptiert keinen Parameter.

Eine Methode kann Parameter haben, wie im folgenden Beispiel gezeigt -

// 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;
}

Klassenkonstruktoren

Ein Konstruktor ist ein Code, der aufgerufen wird, wenn ein Objekt aus dem Klassenplan erstellt wird. Es hat den gleichen Namen wie der Klassenname.

Wir müssen den Konstruktor nicht für jede Klasse definieren, da standardmäßig ein Konstruktor ohne Argumente aufgerufen wird. Konstruktoren sind nützlich für die Initialisierung von Variablen oder wenn ein Prozess zum Zeitpunkt der Klasseninitialisierung ausgeführt werden soll. Beispielsweise möchten Sie bestimmten Integer-Variablen beim Aufruf der Klasse Werte als 0 zuweisen.

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;
   }
}

Sie können die Methode der Klasse auch über den Konstruktor aufrufen. Dies kann nützlich sein, wenn Sie Apex für Visual Force Controller programmieren. Wenn ein Klassenobjekt erstellt wird, wird der Konstruktor wie unten gezeigt aufgerufen -

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

Konstruktoren überladen

Konstruktoren können überladen sein, dh in einer Klasse können mehr als ein Konstruktor mit unterschiedlichen Parametern definiert sein.

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;
   }
}

Sie können diese Klasse so ausführen, wie wir sie im vorherigen Beispiel ausgeführt haben.

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

Eine Instanz der Klasse heißt Object. In Bezug auf Salesforce kann das Objekt von Klasse sein oder Sie können auch ein Objekt von sObject erstellen.

Objekterstellung aus Klasse

Sie können ein Klassenobjekt erstellen, wie Sie es möglicherweise in Java oder einer anderen objektorientierten Programmiersprache getan haben.

Es folgt eine Beispielklasse namens 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);
   }
}

Dies ist eine Instanzklasse, dh um die Variablen oder Methoden dieser Klasse aufzurufen oder darauf zuzugreifen, müssen Sie eine Instanz dieser Klasse erstellen und können dann alle Operationen ausführen.

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

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

sObjekterstellung

sObjects sind die Objekte von Salesforce, in denen Sie die Daten speichern. Beispielsweise sind Konto, Kontakt usw. benutzerdefinierte Objekte. Sie können Objektinstanzen dieser sObjects erstellen.

Das folgende Beispiel zeigt die sObject-Initialisierung und zeigt, wie Sie mithilfe der Punktnotation auf das Feld dieses bestimmten Objekts zugreifen und die Werte den Feldern zuweisen können.

// 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);

Statische Initialisierung

Statische Methoden und Variablen werden beim Laden einer Klasse nur einmal initialisiert. Statische Variablen werden nicht als Teil des Ansichtsstatus für eine Visualforce-Seite übertragen.

Das Folgende ist ein Beispiel für eine statische Methode sowie eine statische Variable.

// 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

Statische Variablen werden beim Laden der Klasse nur einmal instanziiert, und dieses Phänomen kann verwendet werden, um die Triggerrekursion zu vermeiden. Der Wert der statischen Variablen ist im selben Ausführungskontext gleich, und jede Klasse, jeder Trigger oder jeder Code, der ausgeführt wird, kann darauf verweisen und die Rekursion verhindern.

Eine Schnittstelle ist wie eine Apex-Klasse, in der keine der Methoden implementiert wurde. Es enthält nur die Methodensignaturen, aber der Hauptteil jeder Methode ist leer. Um eine Schnittstelle zu verwenden, muss eine andere Klasse sie implementieren, indem sie einen Body für alle in der Schnittstelle enthaltenen Methoden bereitstellt.

Schnittstellen werden hauptsächlich zum Bereitstellen der Abstraktionsschicht für Ihren Code verwendet. Sie trennen die Implementierung von der Deklaration der Methode.

Nehmen wir ein Beispiel unserer Chemiefirma. Angenommen, wir müssen Premium- und Stammkunden den Rabatt gewähren, und die Rabatte für beide sind unterschiedlich.

Wir werden eine Schnittstelle namens the erstellen 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;
   }
}

Wenn Sie die Schnittstelle implementieren, muss die Methode dieser Schnittstelle implementiert werden. Wenn Sie die Interface-Methoden nicht implementieren, wird ein Fehler ausgegeben. Sie sollten Schnittstellen verwenden, wenn Sie die Methodenimplementierung für den Entwickler obligatorisch machen möchten.

Standard Salesforce-Schnittstelle für Batch Apex

SFDC verfügt über Standardschnittstellen wie Database.Batchable, Schedulable usw. Wenn Sie beispielsweise die Database.Batchable-Schnittstelle implementieren, müssen Sie die drei in der Schnittstelle definierten Methoden implementieren - Start, Execute und Finish.

Im Folgenden finden Sie ein Beispiel für die von Standard Salesforce bereitgestellte Database.Batchable-Schnittstelle, über die E-Mails an Benutzer mit dem Stapelstatus gesendet werden. Diese Schnittstelle verfügt über drei Methoden: Start, Ausführen und Beenden. Über diese Schnittstelle können wir die Batchable-Funktionalität implementieren und sie stellt auch die BatchableContext-Variable bereit, mit der wir weitere Informationen über den ausgeführten Batch abrufen und andere Funktionen ausführen können.

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);
   }
}

Um diese Klasse auszuführen, müssen Sie den folgenden Code in der Entwicklerkonsole ausführen.

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

In diesem Kapitel wird erläutert, wie Sie die verschiedenen Funktionen zur Datenbankänderung in Salesforce ausführen. Es gibt zwei Sprüche, mit denen wir die Funktionen ausführen können.

DML-Anweisungen

DML sind die Aktionen, die ausgeführt werden, um das Einfügen, Aktualisieren, Löschen, Upsert, Wiederherstellen von Datensätzen, Zusammenführen von Datensätzen oder Konvertieren von Leads durchzuführen.

DML ist einer der wichtigsten Bestandteile von Apex, da fast jeder Geschäftsfall Änderungen und Modifikationen an der Datenbank beinhaltet.

Datenbankmethoden

Alle Operationen, die Sie mit DML-Anweisungen ausführen können, können auch mit Datenbankmethoden ausgeführt werden. Datenbankmethoden sind die Systemmethoden, mit denen Sie DML-Operationen ausführen können. Datenbankmethoden bieten im Vergleich zu DML-Anweisungen mehr Flexibilität.

In diesem Kapitel werden wir uns den ersten Ansatz mit DML-Anweisungen ansehen. Wir werden uns die Datenbankmethoden in einem nachfolgenden Kapitel ansehen.

DML-Anweisungen

Betrachten wir nun noch einmal die Instanz des Chemielieferanten. Unsere Rechnungsdatensätze enthalten Felder wie Status, bezahlter Betrag, verbleibender Betrag, nächstes Zahlungsdatum und Rechnungsnummer. Rechnungen, die heute erstellt wurden und den Status "Ausstehend" haben, sollten auf "Bezahlt" aktualisiert werden.

Operation einfügen

Der Einfügevorgang wird verwendet, um neue Datensätze in der Datenbank zu erstellen. Mit der Anweisung DML einfügen können Sie Datensätze für jedes Standard- oder benutzerdefinierte Objekt erstellen.

Example

Wir können neue Datensätze im Objekt APEX_Invoice__c erstellen, da täglich neue Rechnungen für neue Kundenaufträge generiert werden. Wir erstellen zuerst einen Kundendatensatz und können dann einen Rechnungsdatensatz für diesen neuen Kundendatensatz erstellen.

// 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);

Vorgang aktualisieren

Der Aktualisierungsvorgang besteht darin, Aktualisierungen für vorhandene Datensätze durchzuführen. In diesem Beispiel aktualisieren wir das Feld Status eines vorhandenen Rechnungsdatensatzes auf "Bezahlt".

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]);

Upsert-Betrieb

Die Upsert-Operation wird verwendet, um eine Aktualisierungsoperation auszuführen. Wenn die zu aktualisierenden Datensätze nicht in der Datenbank vorhanden sind, erstellen Sie auch neue Datensätze.

Example

Angenommen, die Kundendatensätze im Kundenobjekt müssen aktualisiert werden. Wir werden den vorhandenen Kundendatensatz aktualisieren, falls er bereits vorhanden ist, andernfalls einen neuen erstellen. Dies basiert auf dem Wert des Felds APEX_External_Id__c. Dieses Feld ist unser Feld, um festzustellen, ob die Datensätze bereits vorhanden sind oder nicht.

Note - Bevor Sie diesen Code ausführen, erstellen Sie bitte einen Datensatz im Kundenobjekt mit dem externen ID-Feldwert '12341' und führen Sie dann den unten angegebenen Code aus. -

// 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);
   }
}

Vorgang löschen

Sie können den Löschvorgang mit der DML löschen ausführen.

Example

In diesem Fall löschen wir die Rechnungen, die zu Testzwecken erstellt wurden, dh diejenigen, die den Namen "Test" enthalten.

Sie können dieses Snippet auch über die Entwicklerkonsole ausführen, ohne die Klasse zu erstellen.

// 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');

Vorgang wiederherstellen

Sie können den gelöschten und im Papierkorb vorhandenen Datensatz wiederherstellen. Alle Beziehungen, die der gelöschte Datensatz hat, werden ebenfalls wiederhergestellt.

Example

Angenommen, die im vorherigen Beispiel gelöschten Datensätze müssen wiederhergestellt werden. Dies kann anhand des folgenden Beispiels erreicht werden. Der Code im vorherigen Beispiel wurde für dieses Beispiel geändert.

// 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');

Datenbankklassenmethoden sind eine weitere Möglichkeit, mit DML-Anweisungen zu arbeiten, die flexibler sind als DML-Anweisungen wie Einfügen, Aktualisieren usw.

Unterschiede zwischen Datenbankmethoden und DML-Anweisungen

DML-Anweisungen Datenbankmethoden
Teilaktualisierungen sind nicht zulässig. Wenn Sie beispielsweise 20 Datensätze in der Liste haben, werden entweder alle Datensätze aktualisiert oder keine. Teilaktualisierungen sind zulässig. Sie können den Parameter in der Datenbankmethode als true oder false angeben, true, um die teilweise Aktualisierung zuzulassen, und false, wenn dies nicht zulässig ist.
Sie können die Liste der erfolgreichen und fehlgeschlagenen Datensätze nicht abrufen. Sie können die Liste der erfolgreichen und fehlgeschlagenen Datensätze abrufen, wie wir im Beispiel gesehen haben.
Example - Listenname einfügen Example - Database.insert (listName, False), wobei false angibt, dass eine teilweise Aktualisierung nicht zulässig ist.

Operation einfügen

Das Einfügen neuer Datensätze über Datenbankmethoden ist ebenfalls recht einfach und flexibel. Betrachten wir das vorherige Szenario, in dem wir mithilfe der DML-Anweisungen neue Datensätze eingefügt haben. Wir werden dasselbe mit Datenbankmethoden einfügen.

Beispiel

// 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());
      }
   }
}

Vorgang aktualisieren

Betrachten wir nun unser Business-Case-Beispiel mithilfe der Datenbankmethoden. Angenommen, wir müssen das Statusfeld des Rechnungsobjekts aktualisieren, gleichzeitig benötigen wir jedoch auch Informationen wie den Status von Datensätzen, fehlgeschlagene Datensatz-IDs, die Anzahl der Erfolge usw. Dies ist mit DML-Anweisungen nicht möglich. Daher müssen wir Datenbankmethoden verwenden um den Status unserer Operation zu erhalten.

Beispiel

Wir werden das Feld "Status" der Rechnung aktualisieren, wenn es sich im Status "Ausstehend" befindet und das Erstellungsdatum heute ist.

Der unten angegebene Code hilft beim Aktualisieren der Rechnungsdatensätze mithilfe der Database.update-Methode. Erstellen Sie außerdem einen Rechnungsdatensatz, bevor Sie diesen Code ausführen.

// 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());
      }
   }
}

In diesem Lernprogramm werden nur die Einfüge- und Aktualisierungsvorgänge behandelt. Die anderen Operationen sind diesen Operationen und dem, was wir im letzten Kapitel gemacht haben, ziemlich ähnlich.

Jedes Unternehmen oder jede Anwendung verfügt über Suchfunktionen als eine der Grundvoraussetzungen. Zu diesem Zweck bietet Salesforce.com zwei Hauptansätze mit SOSL und SOQL. Lassen Sie uns den SOSL-Ansatz in diesem Kapitel ausführlich diskutieren.

SOSL

Das Durchsuchen der Textzeichenfolge über das Objekt und über das Feld erfolgt mithilfe von SOSL. Dies ist die Salesforce-Objektsuchsprache. Es kann eine bestimmte Zeichenfolge über mehrere Objekte hinweg durchsuchen.

SOSL-Anweisungen werden zu einer Liste von sObjects ausgewertet, wobei jede Liste die Suchergebnisse für einen bestimmten sObject-Typ enthält. Die Ergebnislisten werden immer in derselben Reihenfolge zurückgegeben, in der sie in der SOSL-Abfrage angegeben wurden.

Beispiel für eine SOSL-Abfrage

Stellen Sie sich einen Business Case vor, in dem wir ein Programm entwickeln müssen, das eine bestimmte Zeichenfolge durchsuchen kann. Angenommen, wir müssen im Feld Kundenname des Rechnungsobjekts nach der Zeichenfolge 'ABC' suchen. Der Code lautet wie folgt:

Zuerst müssen Sie einen einzelnen Datensatz im Rechnungsobjekt mit dem Kundennamen 'ABC' erstellen, damit wir bei der Suche ein gültiges Ergebnis erhalten.

// 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

Dies ist fast das gleiche wie bei SOQL. Sie können dies verwenden, um die Objektdatensätze jeweils nur von einem Objekt abzurufen. Sie können verschachtelte Abfragen schreiben und auch die Datensätze von einem übergeordneten oder untergeordneten Objekt abrufen, für das Sie gerade eine Abfrage durchführen.

Wir werden SOQL im nächsten Kapitel untersuchen.

Dies ist die Salesforce-Objektabfragesprache, die für die Arbeit mit der SFDC-Datenbank entwickelt wurde. Es kann einen Datensatz nach einem bestimmten Kriterium nur in einem einzelnen sObject durchsuchen.

Wie SOSL kann es nicht über mehrere Objekte hinweg suchen, unterstützt jedoch verschachtelte Abfragen.

SOQL-Beispiel

Betrachten Sie unser laufendes Beispiel für Chemical Company. Angenommen, wir benötigen eine Liste von Datensätzen, die heute erstellt werden und deren Kundenname nicht "Test" ist. In diesem Fall müssen wir die unten angegebene SOQL-Abfrage verwenden -

// 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
}

Sie können die SOQL-Abfrage wie unten gezeigt über den Abfrage-Editor in der Entwicklerkonsole ausführen.

Führen Sie die unten angegebene Abfrage in der Entwicklerkonsole aus. Suchen Sie nach den heute erstellten Rechnungsdatensätzen.

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

Sie müssen die Felder auswählen, für die Sie die Werte benötigen. Andernfalls können Laufzeitfehler auftreten.

Beziehungsfelder durchqueren

Dies ist einer der wichtigsten Teile in SFDC, da wir oft die übergeordnete untergeordnete Objektbeziehung durchlaufen müssen

Es kann auch Fälle geben, in denen Sie zwei zugeordnete Objektdatensätze in die Datenbank einfügen müssen. Beispielsweise hat das Rechnungsobjekt eine Beziehung zum Kundenobjekt, und daher kann ein Kunde viele Rechnungen haben.

Angenommen, Sie erstellen die Rechnung und müssen diese Rechnung dann dem Kunden zuordnen. Sie können den folgenden Code für diese Funktionalität verwenden:

// 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

Führen Sie dieses Codefragment in der Entwicklerkonsole aus. Kopieren Sie nach der Ausführung die Rechnungs-ID von der Entwicklerkonsole und öffnen Sie diese in SFDC wie unten gezeigt. Sie können sehen, dass der übergeordnete Datensatz bereits dem Rechnungsdatensatz zugewiesen wurde, wie unten gezeigt.

Untergeordnete Datensätze abrufen

Betrachten wir nun ein Beispiel, bei dem alle Rechnungen, die sich auf einen bestimmten Kundendatensatz beziehen, an einem Ort sein müssen. Dazu müssen Sie den Namen der untergeordneten Beziehung kennen. Um den Namen der untergeordneten Beziehung anzuzeigen, rufen Sie die Felddetailseite des untergeordneten Objekts auf und überprüfen Sie den Wert "Untergeordnete Beziehung". In unserem Beispiel handelt es sich um Rechnungen, an deren Ende __r angehängt ist.

Beispiel

In diesem Beispiel müssen wir Daten einrichten, einen Kunden mit dem Namen "ABC-Kundendatensatz" erstellen und diesem Kunden dann 3 Rechnungen hinzufügen.

Jetzt holen wir die Rechnungen ab, die der Kunde 'ABC Customer' hat. Es folgt die Abfrage für dasselbe -

// 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

Sie können die Datensatzwerte in den Debug-Protokollen sehen.

Abrufen eines übergeordneten Datensatzes

Angenommen, Sie müssen den Kundennamen der Rechnung abrufen, dessen Erstellungsdatum heute liegt. Dann können Sie die unten angegebene Abfrage für dieselbe verwenden.

Beispiel

Rufen Sie den Wert des übergeordneten Datensatzes zusammen mit dem untergeordneten Objekt ab.

// 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
}

Hier haben wir die Notation APEX_Customer__r.Name verwendet, wobei APEX_Customer__r der Name der übergeordneten Beziehung ist. Hier müssen Sie das __r am Ende des übergeordneten Felds anhängen und können dann den Wert des übergeordneten Felds abrufen.

Aggregierte Funktionen

SOQL hat eine Aggregatfunktion wie in SQL. Aggregierte Funktionen ermöglichen es uns, die Daten zusammenzufassen und zusammenzufassen. Lassen Sie uns nun die Funktion im Detail verstehen.

Angenommen, Sie wollten wissen, wie hoch der durchschnittliche Umsatz ist, den wir mit dem Kunden 'ABC-Kunde' erzielen. Dann können Sie diese Funktion verwenden, um den Durchschnitt zu ermitteln.

Beispiel

// 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);

Überprüfen Sie die Ausgabe in Debug-Protokollen. Beachten Sie, dass jede Abfrage, die eine Aggregatfunktion enthält, ihre Ergebnisse in einem Array von zurückgibtAggregateResultObjekte. AggregateResult ist ein schreibgeschütztes sObject und wird nur für Abfrageergebnisse verwendet. Dies ist nützlich, wenn wir den Bericht über große Datenmengen erstellen müssen.

Es gibt auch andere Aggregatfunktionen, mit denen Sie eine Datenzusammenfassung durchführen können.

MIN() - Hiermit kann der Mindestwert ermittelt werden

MAX() - Hiermit kann der Maximalwert ermittelt werden.

Apex-Variablen binden

Sie können die Apex-Variable in der SOQL-Abfrage verwenden, um die gewünschten Ergebnisse abzurufen. Apex-Variablen können durch die Colon-Notation (:) referenziert werden.

Beispiel

// 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-Sicherheit bezieht sich auf das Anwenden von Sicherheitseinstellungen und das Durchsetzen der Freigaberegeln für die Ausführung von Code. Apex-Klassen verfügen über Sicherheitseinstellungen, die über zwei Schlüsselwörter gesteuert werden können.

Datensicherheits- und Freigaberegeln

Apex wird im Allgemeinen im Systemkontext ausgeführt, dh mit den Berechtigungen des aktuellen Benutzers. Sicherheits- und Freigaberegeln auf Feldebene werden bei der Codeausführung nicht berücksichtigt. Nur der anonyme Blockcode wird mit der Erlaubnis des Benutzers ausgeführt, der den Code ausführt.

Unser Apex-Code sollte die vertraulichen Daten nicht dem Benutzer zugänglich machen, der über Sicherheits- und Freigabeeinstellungen verborgen ist. Daher ist die Apex-Sicherheit und die Durchsetzung der Freigaberegel am wichtigsten.

Mit Schlüsselwort teilen

Wenn Sie dieses Schlüsselwort verwenden, erzwingt der Apex-Code die Freigabeeinstellungen des aktuellen Benutzers für Apex-Code. Dadurch wird die Profilberechtigung nicht erzwungen, sondern nur die Einstellungen für die Freigabe auf Datenebene.

Betrachten wir ein Beispiel, in dem unser Benutzer Zugriff auf 5 Datensätze hat, die Gesamtzahl der Datensätze jedoch 10 beträgt. Wenn die Apex-Klasse also mit dem Schlüsselwort "With Sharing" deklariert wird, werden nur 5 Datensätze zurückgegeben, für die der Benutzer hat Zugriff auf.

Example

Stellen Sie zunächst sicher, dass Sie mindestens 10 Datensätze im Kundenobjekt mit 'Name' von 5 Datensätzen als 'ABC-Kunde' und 5 Datensätzen als 'XYZ-Kunde' erstellt haben. Erstellen Sie dann eine Freigaberegel, die den 'ABC-Kunden' für alle Benutzer freigibt. Wir müssen auch sicherstellen, dass wir das OWD des Kundenobjekts als Privat festgelegt haben.

Fügen Sie den unten angegebenen Code in den Block "Anonym" in der Entwicklerkonsole ein.

// 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();

Ohne Schlüsselwort zu teilen

Wie der Name schon sagt, wird die mit diesem Schlüsselwort deklarierte Klasse im Systemmodus ausgeführt, dh unabhängig vom Zugriff des Benutzers auf den Datensatz ruft die Abfrage alle Datensätze ab.

// 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.

Festlegen der Sicherheit für die Apex-Klasse

Sie können eine Apex-Klasse für ein bestimmtes Profil aktivieren oder deaktivieren. Die Schritte dazu sind unten angegeben. Sie können festlegen, welches Profil Zugriff auf welche Klasse haben soll.

Festlegen der Apex-Klassensicherheit auf der Seite mit der Klassenliste

Step 1 - Klicken Sie im Setup auf Entwickeln → Apex-Klassen.

Step 2- Klicken Sie auf den Namen der Klasse, die Sie einschränken möchten. Wir haben auf CustomerOperationClass geklickt.

Step 3 - Klicken Sie auf Sicherheit.

Step 4 - Wählen Sie in der Liste Verfügbare Profile die Profile aus, die Sie aktivieren möchten, und klicken Sie auf Hinzufügen, oder wählen Sie in der Liste Aktivierte Profile die Profile aus, die Sie deaktivieren möchten, und klicken Sie auf Entfernen.

Step 5 - Klicken Sie auf Speichern.

Festlegen der Apex-Sicherheit über den Berechtigungssatz

Step 1 - Klicken Sie im Setup auf Benutzer verwalten → Berechtigungssätze.

Step 2 - Wählen Sie einen Berechtigungssatz.

Step 3 - Klicken Sie auf Apex Class Access.

Step 4 - Klicken Sie auf Bearbeiten.

Step 5 - Wählen Sie die Apex-Klassen, die Sie aktivieren möchten, aus der Liste Verfügbare Apex-Klassen aus und klicken Sie auf Hinzufügen, oder wählen Sie die Apex-Klassen, die Sie deaktivieren möchten, aus der Liste Aktivierte Apex-Klassen aus und klicken Sie auf Entfernen.

Step 6 - Klicken Sie auf die Schaltfläche Speichern.

Das Aufrufen von Apex bezieht sich auf den Prozess der Ausführung der Apex-Klasse. Die Apex-Klasse kann nur ausgeführt werden, wenn sie auf eine der unten aufgeführten Arten aufgerufen wird:

  • Trigger und anonymer Block

  • Ein Trigger, der für bestimmte Ereignisse aufgerufen wird

  • Asynchroner Apex

  • Planen der Ausführung einer Apex-Klasse in bestimmten Intervallen oder Ausführen eines Stapeljobs

  • Web Services-Klasse

  • Apex Email Service Klasse

  • Apex-Webdienste, mit denen Sie Ihre Methoden über SOAP- und REST-Webdienste verfügbar machen können

  • Visualforce-Controller

  • Apex Email Service zur Verarbeitung eingehender E-Mails

  • Apex mit JavaScript aufrufen

  • Das Ajax-Toolkit zum Aufrufen von in Apex implementierten Webdienstmethoden

Wir werden nun einige gängige Methoden zum Aufrufen von Apex verstehen.

Vom Anonymen Block ausführen

Sie können die Apex-Klasse über anonymes Ausführen in der Entwicklerkonsole aufrufen, wie unten gezeigt -

Step 1 - Öffnen Sie die Entwicklerkonsole.

Step 2 - Klicken Sie auf Debug.

Step 3- Das Fenster "Anonym ausführen" wird wie unten gezeigt geöffnet. Klicken Sie nun auf die Schaltfläche Ausführen -

Step 4 - Öffnen Sie das Debug-Protokoll, wenn es im Bereich "Protokolle" angezeigt wird.

Vom Auslöser

Sie können eine Apex-Klasse auch über Trigger aufrufen. Trigger werden aufgerufen, wenn ein bestimmtes Ereignis auftritt, und Trigger können die Apex-Klasse bei der Ausführung aufrufen.

Der folgende Beispielcode zeigt, wie eine Klasse ausgeführt wird, wenn ein Trigger aufgerufen wird.

Beispiel

// 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.

Aus Visualforce Page Controller-Code

Die Apex-Klasse kann auch von der Visualforce-Seite aufgerufen werden. Wir können den Controller oder die Controller-Erweiterung angeben und die angegebene Apex-Klasse wird aufgerufen.

Beispiel

VF Page Code

Apex Class Code (Controller Extension)

Apex-Trigger sind wie gespeicherte Prozeduren, die ausgeführt werden, wenn ein bestimmtes Ereignis auftritt. Ein Trigger wird ausgeführt, bevor und nachdem ein Ereignis aufgezeichnet wurde.

Syntax

trigger triggerName on ObjectName (trigger_events) { Trigger_code_block }

Auslösen des Triggers

Es folgen die Ereignisse, bei denen wir den Auslöser auslösen können -

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

Trigger Beispiel 1

Angenommen, wir haben eine Geschäftsanforderung erhalten, dass wir einen Rechnungsdatensatz erstellen müssen, wenn das Feld "Kundenstatus" des Kunden von "Inaktiv" in "Aktiv" geändert wird. Dazu erstellen wir einen Trigger für das Objekt APEX_Customer__c, indem wir die folgenden Schritte ausführen:

Step 1 - Gehen Sie zu sObject

Step 2 - Klicken Sie auf Kunde

Step 3 - Klicken Sie in der Trigger-Themenliste auf die Schaltfläche 'Neu' und fügen Sie den Triggercode wie unten angegeben hinzu.

// 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;
}

Erläuterung

Trigger.new- Dies ist die Kontextvariable, in der die aktuell im Triggerkontext befindlichen Datensätze gespeichert werden, die entweder eingefügt oder aktualisiert werden. In diesem Fall enthält diese Variable die Datensätze des Kundenobjekts, die aktualisiert wurden.

Es gibt andere Kontextvariablen, die im Kontext verfügbar sind - trigger.old, trigger.newMap, trigger.OldMap.

Trigger Beispiel 2

Der obige Trigger wird ausgeführt, wenn die Kundendatensätze aktualisiert werden. Angenommen, der Rechnungsdatensatz muss nur eingefügt werden, wenn sich der Kundenstatus von Inaktiv in Aktiv ändert, und nicht jedes Mal. Hierfür können wir eine andere Kontextvariable verwendentrigger.oldMap Dadurch wird der Schlüssel als Datensatz-ID und der Wert als alte Datensatzwerte gespeichert.

// 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;
}

Erläuterung

Wir haben die Variable Trigger.oldMap verwendet, bei der es sich, wie bereits erläutert, um eine Kontextvariable handelt, in der die ID und der alte Wert der Datensätze gespeichert werden, die aktualisiert werden.

Entwurfsmuster werden verwendet, um unseren Code effizienter zu gestalten und zu vermeiden, dass die Reglergrenzen überschritten werden. Oft können Entwickler ineffizienten Code schreiben, der zu einer wiederholten Instanziierung von Objekten führen kann. Dies kann zu ineffizientem Code mit schlechter Leistung und möglicherweise zur Verletzung von Governor-Grenzwerten führen. Dies tritt am häufigsten bei Triggern auf, da sie mit einer Reihe von Datensätzen arbeiten können.

In diesem Kapitel werden einige wichtige Entwurfsmusterstrategien vorgestellt.

Bulk löst Entwurfsmuster aus

Im realen Geschäftsfall ist es möglich, dass Sie Tausende von Datensätzen auf einmal verarbeiten müssen. Wenn Ihr Trigger nicht für solche Situationen ausgelegt ist, schlägt er möglicherweise bei der Verarbeitung der Datensätze fehl. Es gibt einige bewährte Methoden, die Sie bei der Implementierung der Trigger befolgen müssen. Alle Trigger sind standardmäßig Massentrigger und können mehrere Datensätze gleichzeitig verarbeiten. Sie sollten immer planen, mehr als einen Datensatz gleichzeitig zu verarbeiten.

Stellen Sie sich einen Geschäftsfall vor, bei dem Sie eine große Anzahl von Datensätzen verarbeiten müssen und den Auslöser wie unten angegeben geschrieben haben. Dies ist das gleiche Beispiel, das wir zum Einfügen des Rechnungsdatensatzes verwendet haben, als sich der Kundenstatus von Inaktiv zu Aktiv ändert.

// 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
      }
   }
}

Sie können jetzt sehen, dass die DML-Anweisung für den Schleifenblock geschrieben wurde, der funktioniert, wenn nur wenige Datensätze verarbeitet werden. Wenn Sie jedoch einige Hundert Datensätze verarbeiten, erreicht sie das DML-Anweisungslimit pro Transaktion governor limit. Wir werden in einem nachfolgenden Kapitel einen detaillierten Blick auf die Governor Limits werfen.

Um dies zu vermeiden, müssen wir den Trigger für die gleichzeitige Verarbeitung mehrerer Datensätze effizient gestalten.

Das folgende Beispiel hilft Ihnen, dasselbe zu verstehen -

// 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
}

Dieser Trigger löst nur 1 DML-Anweisung aus, da er über eine Liste ausgeführt wird und die Liste alle Datensätze enthält, die geändert werden müssen.

Auf diese Weise können Sie die Grenzwerte für DML-Anweisungs-Governor vermeiden.

Trigger Helper Class

Das Schreiben des gesamten Codes in Trigger ist ebenfalls keine gute Praxis. Daher sollten Sie die Apex-Klasse aufrufen und die Verarbeitung von Trigger an die Apex-Klasse delegieren, wie unten gezeigt. Trigger Helper-Klasse ist die Klasse, die die gesamte Verarbeitung für den Trigger ausführt.

Betrachten wir noch einmal unser Beispiel für die Erstellung von Rechnungsdatensätzen.

// 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
}

Helferklasse

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
   }
}

Dabei wurde die gesamte Verarbeitung an die Hilfsklasse delegiert. Wenn wir eine neue Funktionalität benötigen, können wir den Code einfach der Hilfsklasse hinzufügen, ohne den Auslöser zu ändern.

Einzelner Trigger für jedes Objekt

Erstellen Sie immer einen einzelnen Trigger für jedes Objekt. Mehrere Trigger für dasselbe Objekt können zu Konflikten und Fehlern führen, wenn die Governor-Grenzen erreicht werden.

Sie können die Kontextvariable verwenden, um die verschiedenen Methoden aus der Hilfsklasse gemäß der Anforderung aufzurufen. Betrachten Sie unser vorheriges Beispiel. Angenommen, unsere Methode createInvoice sollte nur aufgerufen werden, wenn der Datensatz aktualisiert wird und mehrere Ereignisse vorliegen. Dann können wir die Ausführung wie folgt steuern -

// 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
   }
}

Ausführungsbeschränkungen für Gouverneure stellen die effiziente Nutzung von Ressourcen auf der mandantenfähigen Force.com-Plattform sicher. Dies ist die von Salesforce.com festgelegte Grenze für die Codeausführung für eine effiziente Verarbeitung.

Was sind Governor Limits?

Wie wir wissen, wird Apex in einer Umgebung mit mehreren Mandanten ausgeführt, dh eine einzige Ressource wird von allen Kunden und Organisationen gemeinsam genutzt. Daher muss sichergestellt werden, dass niemand die Ressourcen monopolisiert. Daher hat Salesforce.com die Grenzwerte festgelegt, die die Codeausführung regeln und einschränken. Immer wenn eines der Governor-Limits überschritten wird, wird ein Fehler ausgegeben und die Programmausführung angehalten.

Aus Entwicklersicht ist es wichtig sicherzustellen, dass unser Code skalierbar ist und nicht an die Grenzen stößt.

Alle diese Limits werden pro Transaktion angewendet. Eine einzelne Triggerausführung ist eine Transaktion.

Wie wir gesehen haben, hilft das Trigger-Design-Muster, den Grenzwertfehler zu vermeiden. Wir werden jetzt andere wichtige Grenzen sehen.

Vermeiden von SOQL-Abfragegrenzen

Sie können nur 100 Abfragen pro Transaktion ausgeben. Wenn Ihr Code also mehr als 100 SOQL-Abfragen ausgibt, wird ein Fehler ausgegeben.

Beispiel

Dieses Beispiel zeigt, wie das SOQL-Abfragelimit erreicht werden kann -

Der folgende Auslöser durchläuft eine Kundenliste und aktualisiert die Beschreibung des untergeordneten Datensatzes (Rechnung) mit der Zeichenfolge "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
         }
      }
   }
}

Wenn die Methode 'updateCustomerDescription' aufgerufen wird und die Anzahl der Kundendatensätze mehr als 100 beträgt, wird das SOQL-Limit erreicht. Um dies zu vermeiden, schreiben Sie niemals die SOQL-Abfrage in die For-Schleife. In diesem Fall wurde die SOQL-Abfrage in die For-Schleife geschrieben.

Das folgende Beispiel zeigt, wie Sie sowohl die DML als auch das SOQL-Limit vermeiden können. Wir haben die Abfrage für verschachtelte Beziehungen verwendet, um die Rechnungsdatensätze abzurufen, und die Kontextvariable verwendettrigger.newMap um die Karte mit ID und Kundendatensätzen zu erhalten.

// 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;
   }
}

DML-Massenanrufe

Dieses Beispiel zeigt den Bulk-Trigger zusammen mit dem Trigger-Helfer-Klassenmuster. Sie müssen zuerst die Hilfsklasse und dann den Trigger speichern.

Note - Fügen Sie den folgenden Code in die zuvor erstellte Klasse 'CustomerTriggerHelper' ein.

// 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
}

Andere Salesforce Governor-Limits

In der folgenden Tabelle sind die wichtigen Grenzwerte für den Regler aufgeführt.

Beschreibung Grenze
Gesamthaufengröße 6 MB / 12 MB
Gesamtzahl der ausgegebenen DML-Anweisungen 150
Gesamtzahl der Datensätze, die von einer einzelnen SOSL-Abfrage abgerufen wurden 2000
Gesamtzahl der ausgegebenen SOSL-Abfragen 20
Gesamtzahl der von Database.getQueryLocator abgerufenen Datensätze 10000
Gesamtzahl der von SOQL-Abfragen abgerufenen Datensätze 50000

In diesem Kapitel werden wir die Stapelverarbeitung in Apex verstehen. Stellen Sie sich ein Szenario vor, in dem wir täglich eine große Anzahl von Datensätzen verarbeiten, wahrscheinlich die Bereinigung von Daten oder das Löschen nicht verwendeter Daten.

Was ist Batch Apex?

Batch Apex ist eine asynchrone Ausführung von Apex-Code, der speziell für die Verarbeitung der großen Anzahl von Datensätzen entwickelt wurde und eine größere Flexibilität bei den Governor-Limits aufweist als der synchrone Code.

Wann soll Batch Apex verwendet werden?

  • Wenn Sie eine große Anzahl von Datensätzen täglich oder sogar zu einem bestimmten Zeitpunkt verarbeiten möchten, können Sie sich für Batch Apex entscheiden.

  • Wenn eine Operation asynchron sein soll, können Sie auch den Batch-Apex implementieren. Batch Apex wird als Schnittstelle verfügbar gemacht, die vom Entwickler implementiert werden muss. Stapeljobs können zur Laufzeit mithilfe von Apex programmgesteuert aufgerufen werden. Batch Apex verarbeitet kleine Stapel von Datensätzen, deckt Ihren gesamten Datensatz ab und unterteilt die Verarbeitung in überschaubare Datenblöcke.

Verwenden von Batch Apex

Wenn wir den Batch-Apex verwenden, müssen wir die von Salesforce bereitgestellte Schnittstelle Database.Batchable implementieren und dann die Klasse programmgesteuert aufrufen.

Sie können die Klasse folgendermaßen überwachen:

Um die Ausführung des Apex-Batch-Batch-Jobs zu überwachen oder zu stoppen, gehen Sie zu Setup → Überwachung → Apex-Jobs oder Jobs → Apex-Jobs.

Die Database.Batchable-Schnittstelle verfügt über die folgenden drei Methoden, die implementiert werden müssen:

  • Start
  • Execute
  • Finish

Lassen Sie uns nun jede Methode im Detail verstehen.

Start

Die Start-Methode ist eine der drei Methoden der Database.Batchable-Schnittstelle.

Syntax

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

Diese Methode wird zu Beginn des Stapeljobs aufgerufen und sammelt die Daten, mit denen der Stapeljob ausgeführt wird.

Berücksichtigen Sie die folgenden Punkte, um die Methode zu verstehen:

  • Verwenden Sie die Database.QueryLocatorObjekt, wenn Sie eine einfache Abfrage verwenden, um den Umfang der im Stapeljob verwendeten Objekte zu generieren. In diesem Fall wird das SOQL-Datenzeilenlimit umgangen.

  • Verwenden Sie das iterierbare Objekt, wenn Sie komplexe Kriterien zum Verarbeiten der Datensätze haben. Database.QueryLocator bestimmt den Umfang der Datensätze, die verarbeitet werden sollen.

Ausführen

Lassen Sie uns nun die Execute-Methode der Database.Batchable-Schnittstelle verstehen.

Syntax

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

Dabei wird list <sObject <von der Database.QueryLocator-Methode zurückgegeben.

Diese Methode wird nach der Start-Methode aufgerufen und führt die gesamte für den Stapeljob erforderliche Verarbeitung durch.

Fertig

Wir werden nun die Finish-Methode der Database.Batchable-Schnittstelle diskutieren.

Syntax

global void finish(Database.BatchableContext BC) {}

Diese Methode wird am Ende aufgerufen und Sie können einige Abschlussaktivitäten ausführen, z. B. das Senden einer E-Mail mit Informationen zu den verarbeiteten Stapeljobdatensätzen und zum Status.

Batch-Apex-Beispiel

Betrachten wir ein Beispiel unseres bestehenden Chemieunternehmens und gehen wir davon aus, dass wir das Feld Kundenstatus und Kundenbeschreibung der Kundendatensätze aktualisieren müssen, die als aktiv markiert wurden und das Datum wie heute erstellt haben. Dies sollte täglich erfolgen und eine E-Mail an einen Benutzer über den Status der Stapelverarbeitung gesendet werden. Aktualisieren Sie den Kundenstatus als "Verarbeitet" und die Kundenbeschreibung als "Über Stapeljob aktualisiert".

// 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});
   }
}

Um diesen Code auszuführen, speichern Sie ihn zuerst und fügen Sie dann den folgenden Code in Anonym ausführen ein. Dadurch wird das Objekt der Klasse erstellt und die Methode Database.execute führt den Stapeljob aus. Sobald der Auftrag abgeschlossen ist, wird eine E-Mail an die angegebene E-Mail-Adresse gesendet. Stellen Sie sicher, dass Sie einen Kundendatensatz haben, der hatActive wie geprüft.

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

Überprüfen Sie nach Ausführung dieser Klasse die von Ihnen angegebene E-Mail-Adresse, an der Sie die E-Mail mit Informationen erhalten. Sie können den Status des Stapeljobs auch über die Seite Überwachung und die oben angegebenen Schritte überprüfen.

Wenn Sie die Debug-Protokolle überprüfen, finden Sie die Listengröße, die angibt, wie viele Datensätze verarbeitet wurden.

Limitations

Wir können jeweils nur 5 Stapeljobs bearbeiten. Dies ist eine der Einschränkungen von Batch Apex.

Planen des Apex-Stapeljobs mithilfe der Apex-Detailseite

Sie können die Apex-Klasse über die unten angegebene Apex-Detailseite planen.

Step 1 - Gehen Sie zu Setup ⇒ Apex-Klassen, klicken Sie auf Apex-Klassen.

Step 2 - Klicken Sie auf die Schaltfläche Schedule Apex.

Step 3 - Geben Sie Details an.

Planen des Apex-Stapeljobs über die planbare Schnittstelle

Sie können den Apex-Stapeljob über die planbare Schnittstelle wie folgt planen:

// 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);

Das Debuggen ist ein wichtiger Bestandteil jeder Programmierentwicklung. In Apex haben wir bestimmte Tools, die zum Debuggen verwendet werden können. Eine davon ist die system.debug () -Methode, die den Wert und die Ausgabe der Variablen in den Debug-Protokollen druckt.

Wir können die folgenden zwei Tools zum Debuggen verwenden:

  • Entwicklerkonsole
  • Debug-Protokolle

Debuggen über die Entwicklerkonsole

Sie können die Entwicklerkonsole verwenden und anonyme Funktionen zum Debuggen des Apex wie folgt ausführen:

Example

Betrachten Sie unser vorhandenes Beispiel für das Abrufen der heute erstellten Kundendatensätze. Wir möchten nur wissen, ob die Abfrage die Ergebnisse zurückgibt oder nicht. Wenn ja, überprüfen wir den Wert von List.

Fügen Sie den unten angegebenen Code in das Fenster "Anonym ausführen" ein und befolgen Sie die Schritte, die wir zum Öffnen des Fensters "Anonym ausführen" ausgeführt haben.

Step 1 - Öffnen Sie die Entwicklerkonsole

Step 2 - Öffnen Sie die anonyme Ausführung von 'Debug' wie unten gezeigt.

Step 3 - Öffnen Sie das Fenster Anonym ausführen, fügen Sie den folgenden Code ein und klicken Sie auf Ausführen.

// 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 - Öffnen Sie die Protokolle wie unten gezeigt.

Step 5 - Geben Sie 'USER' im Filterzustand wie unten gezeigt ein.

Step 6 - Öffnen Sie die USER DEBUG-Anweisung wie unten gezeigt.

Debuggen über Debug-Protokolle

Sie können dieselbe Klasse auch über Debug-Protokolle debuggen. Angenommen, Sie haben einen Auslöser im Kundenobjekt und dieser muss für einige Variablenwerte debuggt werden. Dann können Sie dies über die Debug-Protokolle tun, wie unten gezeigt.

Dies ist der Triggercode, der das Feld Beschreibung aktualisiert, wenn der geänderte Kunde aktiv ist und Sie die Werte von Variablen und Datensätzen überprüfen möchten, die sich derzeit im Gültigkeitsbereich befinden.

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);
      }
   }
}

Führen Sie die folgenden Schritte aus, um die Debug-Protokolle zu erstellen.

Step 1- Legen Sie die Debug-Protokolle für Ihren Benutzer fest. Gehen Sie zu Setup und geben Sie 'Debug Log' in das Such-Setup-Fenster ein und klicken Sie dann auf Link.

Step 2 - Stellen Sie die Debug-Protokolle wie folgt ein.

Step 3- Geben Sie den Namen des Benutzers ein, der eingerichtet werden muss. Geben sie hier ihren Namen ein.

Step 4 - Ändern Sie die Kundendatensätze so, dass ein Ereignis eintreten sollte, um das Debug-Protokoll zu generieren.

Step 5- Gehen Sie nun erneut zum Abschnitt Debug-Protokolle. Öffnen Sie die Debug-Protokolle und klicken Sie auf Zurücksetzen.

Step 6 - Klicken Sie auf den Ansichtslink des ersten Debug-Protokolls.

Step 7 - Suchen Sie mit der unten gezeigten Browsersuche nach der Zeichenfolge 'USER'.

Die Debug-Anweisung zeigt den Wert des Feldes an, auf das wir den Punkt gesetzt haben.

Das Testen ist der integrierte Bestandteil von Apex oder einer anderen Anwendungsentwicklung. In Apex müssen separate Testklassen für alle Unit-Tests entwickelt werden.

Testklassen

In SFDC muss der Code eine Codeabdeckung von 75% aufweisen, um in der Produktion bereitgestellt zu werden. Diese Codeabdeckung wird von den Testklassen durchgeführt. Testklassen sind die Codefragmente, die die Funktionalität anderer Apex-Klassen testen.

Schreiben wir eine Testklasse für einen unserer Codes, die wir zuvor geschrieben haben. Wir werden eine Testklasse schreiben, um unseren Trigger- und Helper-Klassencode abzudecken. Unten finden Sie die Trigger- und Helferklasse, die abgedeckt werden muss.

// 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
   }
}

Testklasse erstellen

In diesem Abschnitt erfahren Sie, wie Sie eine Testklasse erstellen.

Datenerstellung

Wir müssen Daten für die Testklasse in unserer Testklasse selbst erstellen. Die Testklasse hat standardmäßig keinen Zugriff auf Organisationsdaten. Wenn Sie jedoch @isTest festlegen (seeAllData = true), hat sie auch Zugriff auf die Organisationsdaten.

@ isTest Annotation

Mit dieser Anmerkung haben Sie erklärt, dass dies eine Testklasse ist und nicht auf das gesamte Codelimit der Organisation angerechnet wird.

Schlüsselwort testMethod

Unit-Test-Methoden sind Methoden, die keine Argumente annehmen, keine Daten in die Datenbank übertragen, keine E-Mails senden und mit dem Schlüsselwort testMethod oder der Annotation isTest in der Methodendefinition deklariert werden. Außerdem müssen Testmethoden in Testklassen definiert werden, dh in Klassen, die mit isTest kommentiert sind.

In unseren Beispielen haben wir die Testmethode 'myUnitTest' verwendet.

Test.startTest () und Test.stopTest ()

Dies sind die Standardtestmethoden, die für Testklassen verfügbar sind. Diese Methoden enthalten das Ereignis oder die Aktion, für die wir unseren Test simulieren werden. Wie in diesem Beispiel testen wir unsere Trigger- und Helferklasse, um den Feuerauslöser zu simulieren, indem wir die Datensätze aktualisieren, wie wir es getan haben, um den Block zu starten und zu stoppen. Dies bietet auch eine separate Reglergrenze für den Code, der sich im Start- und Stoppblock befindet.

System.assert ()

Diese Methode überprüft die gewünschte Ausgabe mit der tatsächlichen. In diesem Fall erwarten wir, dass ein Rechnungsdatensatz eingefügt wird, daher haben wir assert hinzugefügt, um dies zu überprüfen.

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
   }
}

Ausführen der Testklasse

Führen Sie die folgenden Schritte aus, um die Testklasse auszuführen -

Step 1 - Gehen Sie zu Apex-Klassen ⇒ Klicken Sie auf den Klassennamen 'CustomerTriggerTestClass'.

Step 2 - Klicken Sie wie gezeigt auf die Schaltfläche Test ausführen.

Step 3 - Status prüfen

Step 4 - Überprüfen Sie nun die Klasse und den Trigger, für die wir den Test geschrieben haben

Klasse

Auslösen

Unsere Tests sind erfolgreich und abgeschlossen.

Was ist die Bereitstellung in SFDC?

Bis jetzt haben wir Code in der Developer Edition entwickelt, aber im realen Szenario müssen Sie diese Entwicklung in Sandbox durchführen und dann möglicherweise in einer anderen Sandbox oder Produktionsumgebung bereitstellen. Dies wird als Bereitstellung bezeichnet. Kurz gesagt, dies ist die Verschiebung von Metadaten von einer Organisation zu einer anderen. Der Grund dafür ist, dass Sie Apex in Ihrer Salesforce-Produktionsorganisation nicht entwickeln können. Live-Benutzer, die während der Entwicklung auf das System zugreifen, können Ihre Daten destabilisieren oder Ihre Anwendung beschädigen.

Für die Bereitstellung verfügbare Tools -

  • Force.com IDE
  • Sätze ändern
  • SOAP-API
  • Force.com-Migrationstool

Da wir die Developer Edition für unsere Entwicklungs- und Lernzwecke verwenden, können wir das Change Set oder andere Tools, die das SFDC Enterprise oder eine andere kostenpflichtige Edition benötigen, nicht verwenden. Daher werden wir in diesem Lernprogramm die Force.com-IDE-Bereitstellungsmethode erläutern.

Force.com Eclipse IDE

Step 1 - Öffnen Sie Eclipse und öffnen Sie den Klassen-Trigger, der bereitgestellt werden muss.

Step 2 - Wenn Sie auf "Auf Server bereitstellen" klicken, geben Sie den Benutzernamen und das Kennwort der Organisation ein, in der die Komponente bereitgestellt werden muss.

Durch Ausführen der oben genannten Schritte werden Ihre Apex-Komponenten für die Zielorganisation bereitgestellt.

Bereitstellung mit Change Set

Sie können Validierungsregeln, Workflowregeln, Apex-Klassen und Trigger von einer Organisation zur anderen bereitstellen, indem Sie sie über die Bereitstellungseinstellungen verbinden. In diesem Fall müssen Organisationen verbunden sein.

Führen Sie die folgenden Schritte aus, um das Bereitstellungssetup zu öffnen. Denken Sie daran, dass diese Funktion in der Developer Edition nicht verfügbar ist.

Step 1 - Gehen Sie zu Setup und suchen Sie nach 'Deploy'.

Step 2 - Klicken Sie auf "Outbound Change Set", um einen Änderungssatz für die Bereitstellung zu erstellen.

Step 3 - Fügen Sie Komponenten hinzu, um den Satz zu ändern, indem Sie auf die Schaltfläche 'Hinzufügen' klicken und dann Speichern und auf Hochladen klicken.

Step 4 - Gehen Sie zur Zielorganisation, klicken Sie auf den Satz für eingehende Änderungen und schließlich auf Bereitstellen.

Zu implementierende SOAP-API-Aufrufe

Wir werden nur einen kleinen Überblick über diese Methode geben, da dies keine häufig verwendete Methode ist.

Sie können die unten angegebenen Methodenaufrufe verwenden, um Ihre Metadaten bereitzustellen.

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

Force.com-Migrationstool

Dieses Tool wird für die Skriptbereitstellung verwendet. Sie müssen das Force.com-Migrationstool herunterladen und können dann die dateibasierte Bereitstellung durchführen. Sie können das Force.com-Migrationstool herunterladen und dann die Skriptbereitstellung durchführen.