Salesforce Apex-Tutorial für Anfänger

⚡ Intelligente Zusammenfassung

Die Apex-Programmierung bietet Salesforce-Entwicklern eine objektorientierte, stark typisierte Sprache, um benutzerdefinierte Geschäftslogik in das CRM zu integrieren. Sie ermöglicht die Erstellung von Klassen, Triggern und Batch-Jobs, während Governor Limits die Stabilität der gemeinsam genutzten Mandantenplattform gewährleisten.

  • 🧱 Foundation: Apex ist eine Sprache, die nicht zwischen Groß- und Kleinschreibung unterscheidet. Java-ähnliche Syntax, die nativ auf der Salesforce Lightning Platform ausgeführt werden kann.
  • 🗃️ Datenzugriff: Mit SOQL-Abfragen und DML-Anweisungen kann Ihr Code sObject-Datensätze direkt in der Salesforce-Datenbank lesen und schreiben.
  • Implementierung: Klassen, Eigenschaften und Trigger verknüpfen benutzerdefinierte Logik mit dem Einfügen, Aktualisieren, Löschen von Datensätzen und anderen Systemereignissen.
  • 📦 Maßstab: Batch Apex und andere asynchrone Optionen verarbeiten Millionen von Datensätzen in Blöcken, ohne die Plattformgrenzen zu überschreiten.
  • 🚦 Gouverneur-Grenzen: Durch Transaktionsbeschränkungen, wie z. B. 100 synchrone SOQL-Abfragen und 150 DML-Anweisungen, werden gemeinsam genutzte Ressourcen geschützt.
  • Qualität: Vor der Produktionsbereitstellung müssen mindestens 75 Prozent des Apex-Codes durch Unit-Tests abgedeckt sein.

APEX Salesforce-Programmierung – Überblick

Was ist Apex in Salesforce?

Apex Apex ist eine objektorientierte und stark typisierte Programmiersprache, die von Salesforce zur Entwicklung von Software-as-a-Service- (SaaS) und Customer-Relationship-Management- (CRM) Anwendungen entwickelt wurde. Apex unterstützt Entwickler bei der Erstellung von SaaS-Anwendungen von Drittanbietern und der Integration von Geschäftslogik in Systemereignisse durch Backend-Datenbankunterstützung und Client-Server-Schnittstellen.

Apex unterstützt Entwickler beim Hinzufügen von Geschäftslogik zu Systemereignissen wie Schaltflächenklicks, Aktualisierungen verknüpfter Datensätze und Visualforce-Seiten. Die Syntax von Apex ähnelt der von … Java. Registrieren Sie sich für Salesforce um zu erfahren, wie das CRM funktioniert.

Funktionen der Apex-Programmiersprache

Hier sind die wichtigen Funktionen von Salesforce Apex:

  • Apex ist eine Sprache, die nicht zwischen Groß- und Kleinschreibung unterscheidet.
  • Mit Apex können Sie DML-Operationen wie INSERT, UPDATE, UPSERT und DELETE an sObject-Datensätzen durchführen.
  • In Apex können Sie sObject-Datensätze mithilfe von SOQL (Salesforce Object Query Language) und SOSL (Salesforce Object Search Language) abfragen.
  • Ermöglicht das Erstellen eines Gerätetest und führen Sie es aus, um dies zu überprüfen. Codeabdeckung und die Effizienz des Codes in Apex.
  • Apex wird in einer Umgebung mit mehreren Mandanten ausgeführt Salesforce Salesforce hat Beschränkungen festgelegt, die verhindern, dass ein Benutzer die gemeinsam genutzten Ressourcen monopolisiert. Jeder Code, der eine solche Beschränkung überschreitet, schlägt fehl und es wird eine Fehlermeldung angezeigt.
  • Ein Salesforce-Objekt kann als Datentyp in Apex verwendet werden. Zum Beispiel:
    Account acc = new Account();

    Hierbei handelt es sich bei Account um ein Standard-Salesforce-Objekt.

  • Apex wird mit jeder Salesforce-Version automatisch aktualisiert.

Wann sollte ein Entwickler Apex wählen?

Apex-Code sollte nur dann geschrieben werden, wenn ein Geschäftsszenario zu komplex ist, um es mit den vorgefertigten Point-and-Click-Funktionen von Salesforce umzusetzen.

Im Folgenden finden Sie einige Szenarien, in denen Sie Apex-Code schreiben müssen:

  • So erstellen Sie Webdienste, die Salesforce mit anderen Anwendungen integrieren.
  • Um eine benutzerdefinierte Validierung für sObjects zu implementieren.
  • Um benutzerdefinierte Apex-Logik auszuführen, wenn eine DML-Operation durchgeführt wird.
  • Um Funktionalitäten zu implementieren, die mit bestehenden deklarativen Automatisierungstools wie Flow nicht realisiert werden können.
  • Einzurichten E-Mail-Dienste die den Inhalt, die Kopfzeilen und die Anhänge eingehender E-Mails verarbeiten.

Sobald Sie wissen, wann Apex die richtige Wahl ist, geht es im nächsten Schritt darum zu verstehen, was mit Ihrem Code passiert, nachdem Sie ihn gespeichert haben.

Arbeitsstruktur von Apex

Im Folgenden wird der Ablauf der Aktionen im Apex-Code beschrieben:

  • Entwickleraktion: Wenn der Entwickler Code auf der Plattform speichert, wird der gesamte Apex-Code in eine Reihe von Anweisungen kompiliert, die der Apex-Laufzeitinterpreter versteht. Diese Anweisungen werden dann als Metadaten auf der Plattform gespeichert.
  • Aktion des Endbenutzers: Wenn ein Benutzerereignis Apex-Code ausführt, ruft der Plattformserver die kompilierten Anweisungen aus den Metadaten ab und führt sie durch den Apex-Interpreter, bevor er das Ergebnis zurückgibt.

Das folgende Diagramm zeigt, wie die Aktionen des Entwicklers und des Endbenutzers mit dem Lightning Platform-Anwendungsserver interagieren:

Arbeitsstruktur von Apex

Apex-Entwicklungsumgebung

Apex-Code kann entweder in einer Sandbox oder in einer Developer Edition-Organisation von Salesforce entwickelt werden.

Es empfiehlt sich, den Code in einer Sandbox-Umgebung zu entwickeln und ihn anschließend in die Produktionsumgebung zu übertragen, wie unten dargestellt:

Apex-Entwicklungsumgebung

Apex-Code-Entwicklungstools: Im Folgenden werden die drei Tools vorgestellt, die in allen Salesforce-Editionen zur Entwicklung von Apex-Code zur Verfügung stehen:

  • Entwicklerkonsole
  • Visual Studio Code mit dem Salesforce Extension Pack (dies ersetzt die nicht mehr existierende Force.com IDE)
  • Code Editor in der Salesforce Setup-Benutzeroberfläche

Nachdem Ihre Umgebung eingerichtet ist, wollen wir uns die Bausteine ​​der Sprache selbst ansehen, angefangen bei den Datentypen.

Datentypen in Apex

Folgende Datentypen werden von Apex unterstützt:

Primitive

Ganze Zahl, DoubleLong, Date, Datetime, Decimal, Time, Blob, String, ID und Boolean gelten als primitive Datentypen. Alle primitiven Datentypen werden als Wert und nicht als Referenz übergeben.

Kollektionen

In Apex sind drei Arten von Kollektionen verfügbar:

  • Liste: Es handelt sich um eine geordnete Sammlung von primitiven Datentypen, sObjects, Sammlungen oder Apex-Objekten, die auf Indizes basiert.
  • Set: Eine ungeordnete Sammlung von eindeutigen Elementen, die keine Duplikate enthält.
  • Karte: Es handelt sich um eine Sammlung eindeutiger Schlüssel, die einzelnen Werten zugeordnet sind. Diese Werte können primitive Datentypen, sObjects, Sammlungen oder Apex-Objekte sein.

sObjekt

Dies ist ein spezieller Datentyp in Salesforce. Es ähnelt einer Tabelle in SQL und enthält Felder, die Spalten in SQL ähneln.

Enums

Ein Enum ist ein absolutestract ist ein Datentyp, der einen Wert aus einer endlichen Menge festgelegter Bezeichner speichert.

Klassen, Objekte und Schnittstellen

Benutzerdefinierte Apex-Klassen und -Schnittstellen können ebenfalls als Datentypen verwendet werden. Ein Objekt bezeichnet eine Instanz eines beliebigen Datentyps, der in Apex unterstützt wird.

Apex-Syntax

Variable Aussage

Da Apex eine stark typisierte Sprache ist, ist es in Apex zwingend erforderlich, eine Variable mit einem Datentyp zu deklarieren.

Beispielsweise:

Contact con = new Contact();

Hier wird die Variable con mit Contact als Datentyp deklariert.

SOQL-Abfrage

SOQL steht für Salesforce Object Query Language. SOQL wird verwendet, um sObject-Datensätze aus der Salesforce-Datenbank abzurufen. Zum Beispiel:

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

Die obige Abfrage ruft einen Account-Datensatz aus der Salesforce-Datenbank ab.

Loop-Anweisung

Eine Schleife dient dazu, die Datensätze einer Liste zu durchlaufen. Die Anzahl der Durchläufe entspricht der Anzahl der Datensätze in der Liste. Zum Beispiel:

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

Im obigen Codeausschnitt ist listOfAccounts eine Variable vom Datentyp List.

Flusskontrollerklärung

Eine Ablaufsteuerungsanweisung ist dann sinnvoll, wenn Sie bestimmte Codezeilen basierend auf bestimmten Bedingungen ausführen möchten.

Beispielsweise:

List<Account> listOfAccounts = [SELECT Id, Name FROM Account LIMIT 100];
// execute the logic if the size of the account list is greater than zero
if(listOfAccounts.size() > 0){
	//your logic
}

Der obige Codeabschnitt fragt Kontodatensätze aus der Datenbank ab und prüft die Listengröße.

DML-Anweisung

DML steht für Data Manipulation Language (Datenmanipulationssprache). DML-Anweisungen werden verwendet, um Daten in der Salesforce-Datenbank zu bearbeiten. Zum Beispiel:

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

Apex-Zugriffsspezifizierer

Folgende Zugriffsspezifizierer werden von Apex unterstützt:

Öffentliche

Dieser Zugriffsspezifizierer ermöglicht den Zugriff auf eine Klasse, Methode oder Variable, die von Apex innerhalb eines Namespace verwendet werden kann.

Private

Dieser Zugriffsmodifizierer ermöglicht den Zugriff auf eine Klasse, Methode oder Variable zur lokalen Verwendung, also innerhalb des Codeabschnitts, in dem sie definiert ist. Alle Methoden und Variablen ohne definierten Zugriffsmodifizierer erhalten standardmäßig den Zugriffsmodifizierer „private“.

Geschützt

Dieser Zugriffsspezifizierer ermöglicht den Zugriff auf eine Methode oder Variable, die von allen inneren Klassen innerhalb der definierenden Apex-Klasse verwendet werden kann.

Globalen

Dieser Zugriffsspezifizierer ermöglicht den Zugriff auf eine Klasse, Methode oder Variable, die von Apex sowohl innerhalb als auch außerhalb eines Namespace verwendet werden kann. Es empfiehlt sich, das Schlüsselwort `global` nur dann zu verwenden, wenn es unbedingt erforderlich ist.

Schlüsselwörter in Apex

Mit Teilen

Wird eine Klasse mit diesem Schlüsselwort definiert, werden alle für den aktuellen Benutzer geltenden Freigaberegeln durchgesetzt. Fehlt dieses Schlüsselwort, wird der Code im Systemkontext ausgeführt.

Beispielsweise:

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

Ohne zu teilen

Wenn eine Klasse mit diesem Schlüsselwort definiert wird, werden die für den aktuellen Benutzer geltenden Freigaberegeln nicht durchgesetzt.

Beispielsweise:

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

Statisch

Eine mit dem Schlüsselwort `static` definierte Variable oder Methode wird einmalig initialisiert und der Klasse zugeordnet. Statische Variablen und Methoden können direkt über den Klassennamen aufgerufen werden, ohne dass eine Instanz der Klasse erstellt werden muss.

Ende

Eine mit dem Schlüsselwort `final` definierte Konstante oder Methode kann nicht überschrieben werden. Zum Beispiel:

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

Wenn Sie versuchen, den Wert dieser INT_CONST-Variablen zu überschreiben, erhalten Sie die Ausnahme: System.FinalException: Final-Variable wurde bereits initialisiert.

Return

Dieses Schlüsselwort gibt einen Wert von einer Methode zurück. Zum Beispiel:

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

Null

Sie definiert eine Nullkonstante und kann einer Variablen zugewiesen werden. Zum Beispiel:

Boolean b = null;

Assistent

Wenn eine Klasse mit dem Schlüsselwort virtual definiert wird, kann sie erweitert und überschrieben werden.

Abstract

Wenn eine Klasse mit dem absoluten Wert definiert wirdtracDas Schlüsselwort t muss mindestens eine Methode mit dem Schlüsselwort abs enthalten.tract, und diese Methode sollte nur eine Signatur haben.

Beispielsweise:

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

Apex-Saite

Eine Zeichenkette ist eine Folge von Zeichen ohne Längenbegrenzung. Zum Beispiel:

String name = 'Test';

Die String-Klasse in Salesforce bietet mehrere integrierte Methoden. Im Folgenden werden einige häufig verwendete Methoden aufgeführt:

abkürzen(maxWidth)

Diese Methode kürzt eine Zeichenkette auf die angegebene Länge und gibt sie zurück, falls die Zeichenkette länger als die angegebene Länge ist; andernfalls gibt sie die ursprüngliche Zeichenkette zurück. Ist der Wert der Variable `maxWidth` kleiner als 4, löst diese Methode eine Laufzeitausnahme aus: `System.StringException: Minimum abbreviation width is 4`.

Beispielsweise:

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

profitieren()

Diese Methode wandelt den ersten Buchstaben einer Zeichenfolge in die Groß-/Kleinschreibung des Titels um und gibt ihn zurück.

Beispielsweise:

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

enthält(Teilzeichenfolge)

Diese Methode gibt true zurück, wenn die Zeichenkette, die die Methode aufruft, die angegebene Teilzeichenkette enthält.

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

equal(stringOrId)

Diese Methode gibt true zurück, wenn der übergebene Parameter nicht null ist und die gleiche binäre Zeichenfolge darstellt wie die Zeichenkette, die die Methode aufruft.

Beim Vergleich von ID-Werten können die ID-Längen unterschiedlich sein. Wenn beispielsweise eine Zeichenkette, die eine 15-stellige ID darstellt, mit einem Objekt verglichen wird, das eine 18-stellige ID darstellt, gibt diese Methode dennoch „true“ zurück. Beispiel:

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

Im obigen Beispiel vergleicht die equals-Methode eine 15-stellige Objekt-ID mit einer 18-stelligen Objekt-ID. Wenn beide IDs die gleiche Binärsequenz darstellen, gibt sie true zurück.

Verwenden Sie diese Methode, um Vergleiche unter Berücksichtigung der Groß- und Kleinschreibung durchzuführen.

escapeSingleQuotes(stringToEscape)

Diese Methode fügt vor jedem einzelnen Anführungszeichen in einer Zeichenkette ein Escape-Zeichen (\) ein und gibt das Ergebnis zurück. Dadurch wird SOQL-Injection beim Erstellen einer dynamischen SOQL-Abfrage verhindert. Es wird sichergestellt, dass alle einzelnen Anführungszeichen als umschließende Zeichenketten und nicht als Datenbankbefehle interpretiert werden.

Beispielsweise:

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

entfernen(Teilzeichenfolge)

Diese Methode entfernt alle Vorkommen der genannten Teilzeichenkette aus der Zeichenkette, die die Methode aufruft, und gibt die resultierende Zeichenkette zurück.

Beispielsweise:

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

Teilzeichenfolge (StartIndex)

Diese Methode gibt eine Teilzeichenkette zurück, die beim Zeichen an der Position startIndex beginnt und bis zum Ende der Zeichenkette reicht.

Beispielsweise:

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

umkehren()

Diese Methode kehrt die Reihenfolge aller Zeichen einer Zeichenkette um und gibt sie zurück. Zum Beispiel:

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

trim ()

Diese Methode entfernt alle führenden und nachfolgenden Leerzeichen aus einer Zeichenkette und gibt diese zurück.

valueOf(toConvert)

Diese Methode gibt die String-Repräsentation des übergebenen Objekts zurück.

Zeichenketten, Klassen und Schlüsselwörter kommen zusammen, wenn man anfängt, Logik in wiederverwendbare Einheiten zu verpacken – genau dafür sind Apex-Klassen da.

Apex-Klasse

Eine Apex-Klasse ist eine Blaupause oder Vorlage, aus der Objekte erstellt werden. Ein Objekt ist eine Instanz einer Klasse.

Es gibt drei Möglichkeiten, Apex-Klassen in Salesforce zu erstellen:

  • Entwicklerkonsole
  • Visual Studio Code mit dem Salesforce Extension Pack
  • Apex-Klassendetailseite in Setup

In Apex können Sie eine äußere Klasse definieren, die auch als Top-Level-Klasse bezeichnet wird, und Sie können auch Klassen innerhalb einer äußeren Klasse definieren, die als innere Klassen bezeichnet werden.

Bei der Deklaration einer äußeren Klasse muss zwingend ein Zugriffsmodifizierer wie global oder public verwendet werden.

Bei der Deklaration innerer Klassen ist kein Zugriffsmodifizierer erforderlich.

Eine Apex-Klasse wird mit dem Schlüsselwort class gefolgt vom Klassennamen definiert.

Das Schlüsselwort `extends` dient dazu, eine bestehende Klasse in einer Apex-Klasse zu erweitern, und das Schlüsselwort `implements` dient dazu, eine Schnittstelle in einer Apex-Klasse zu implementieren.

Salesforce Apex unterstützt keine Mehrfachvererbung; eine Apex-Klasse kann nur eine bestehende Apex-Klasse erweitern, aber mehrere Schnittstellen implementieren.

Eine Apex-Klasse kann einen benutzerdefinierten Konstruktor enthalten. Ist kein benutzerdefinierter Konstruktor verfügbar, wird ein Standardkonstruktor verwendet. Der Code im Konstruktor wird ausgeführt, wenn eine Instanz der Klasse erstellt wird.

Syntax einer Apex-Klasse:

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

Das Schlüsselwort `new` dient zum Erstellen einer Instanz einer Apex-Klasse. Nachfolgend die Syntax zum Erstellen einer Instanz einer Apex-Klasse:

myApexClass obj = new myApexClass();

Apex-Getter und -Setter

Eine Apex-Eigenschaft ähnelt einer Apex-Variablen. Für eine Apex-Eigenschaft sind ein Getter und ein Setter erforderlich. Mit ihnen kann Code ausgeführt werden, bevor auf den Eigenschaftswert zugegriffen oder dieser geändert wird. Der Code im Getter wird ausgeführt, wenn ein Eigenschaftswert gelesen wird. Der Code im Setter wird ausgeführt, wenn ein Eigenschaftswert geändert wird. Eigenschaften, die nur einen Getter besitzen, gelten als schreibgeschützt, Eigenschaften, die nur einen Setter besitzen, als schreibgeschützt und Eigenschaften mit beiden Methoden als beschreibbar. Syntax einer Apex-Eigenschaft:

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

Hierbei ist access_modifier der Zugriffsmodifizierer der Eigenschaft, return_type der Datentyp der Eigenschaft und property_name der Name der Eigenschaft.

Nachfolgend ein Beispiel für eine Apex-Eigenschaft mit Getter- und Setter-Methoden:

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

Hierbei handelt es sich bei der Eigenschaft um den Namen „name“, es ist eine öffentliche Eigenschaft, und sie gibt einen String-Datentyp zurück.

Es ist nicht zwingend erforderlich, Code in den Getter- und Setter-Blöcken zu haben. Diese Blöcke können leer gelassen werden, um eine automatische Eigenschaft zu definieren. Zum Beispiel:

public double MyReadWriteProp{ get; set; }

Getter- und Setter-Zugriffsmethoden können auch mit eigenen Zugriffsmodifizierern definiert werden. Wenn eine Zugriffsmethode mit einem Modifikator definiert wird, überschreibt dieser den Zugriffsmodifizierer der Eigenschaft. Zum Beispiel:

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

Klassen definieren wiederverwendbare Logik, die Sie explizit aufrufen. Trigger, die im nächsten Abschnitt behandelt werden, werden automatisch ausgeführt, sobald sich Datensätze ändern.

Apex-Trigger

Apex-Trigger ermöglichen es Ihnen, benutzerdefinierten Apex-Code vor und nach einer DML-Operation auszuführen.

Apex unterstützt die folgenden zwei Arten von Triggern:

Vor dem Auslösen: Diese Trigger dienen dazu, den Wert eines Feldes zu überprüfen und zu aktualisieren, bevor der Datensatz in der Datenbank gespeichert wird.

Nach Auslösern: Diese Trigger ermöglichen den Zugriff auf Feldwerte (wie die Datensatz-ID und das Feld „Letzte Änderung“), die vom System nach dem Speichern eines Datensatzes in der Datenbank festgelegt werden. Mithilfe dieser Feldwerte können andere Datensätze geändert werden. Datensätze, die durch Trigger ausgelöst werden, sind schreibgeschützt.

Es empfiehlt sich, Massentrigger zu schreiben. Ein Massentrigger kann sowohl einen einzelnen Datensatz als auch mehrere Datensätze gleichzeitig verarbeiten.

Syntax eines Apex-Triggers:

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

Hierbei ist TriggerName der Name des Triggers, ObjectName der Name des Objekts, auf das der Trigger geschrieben wird, und trigger_events eine durch Kommas getrennte Liste von Ereignissen.

Folgende Ereignisse werden von Apex-Triggern unterstützt: vor dem Einfügen, vor dem Aktualisieren, vor dem Löschen, nach dem Einfügen, nach dem Aktualisieren, nach dem Löschen, nach dem Wiederherstellen.

Statische Schlüsselwörter können nicht in einem Apex-Trigger verwendet werden. Alle Schlüsselwörter, die für innere Klassen gelten, können in einem Apex-Trigger verwendet werden.

Jeder Trigger definiert implizite Variablen, die den Laufzeitkontext zurückgeben. Diese Variablen sind in der Klasse `System.Trigger` definiert und werden Kontextvariablen genannt. Die beiden folgenden Screenshots zeigen die von Apex-Triggern unterstützten Kontextvariablen:

Apex-Trigger-Kontextvariablen

Apex-Trigger-Kontextvariablen (Fortsetzung)

Im Folgenden werden die Überlegungen zu Kontextvariablen in Apex-Triggern aufgeführt:

  • Verwenden Sie trigger.new und trigger.old nicht in DML-Operationen.
  • Trigger.new kann nicht gelöscht werden.
  • Trigger.new ist nach dem Ausführen von Triggern schreibgeschützt.
  • Trigger.new kann nur vor dem Ausführen von Triggern verwendet werden, um die Werte von Feldern desselben Objekts zu ändern.

Die beiden folgenden Screenshots listen die Überlegungen zu spezifischen Aktionen in verschiedenen Auslöseereignissen auf:

Überlegungen zum Apex-Triggerereignis

Überlegungen zum Apex-Triggerereignis (Fortsetzung)

Trigger verarbeiten Echtzeitlogik, aber manche Aufträge sind einfach zu umfangreich für eine einzelne Transaktion. Hier kommt Batch-Apex ins Spiel.

Batch-Klasse in Apex

Eine Batch-Klasse in Salesforce dient der Verarbeitung einer großen Anzahl von Datensätzen, die bei normaler Verarbeitung die Apex-Governor-Limits überschreiten würden. Der Code wird in einer Batch-Klasse asynchron ausgeführt.

Im Folgenden sind die Vorteile einer Batch-Klasse aufgeführt:

  • Eine Batch-Klasse verarbeitet die Daten in Blöcken, und falls ein Block nicht erfolgreich verarbeitet werden kann, werden die erfolgreich verarbeiteten Blöcke nicht zurückgesetzt.
  • Jeder Datenblock in einer Batch-Klasse wird mit einem neuen Satz von Governor-Limits verarbeitet, wodurch sichergestellt wird, dass der Code innerhalb der Governor-Ausführungslimits ausgeführt wird.

Die Schnittstelle Database.Batchable muss von einer Apex-Klasse implementiert werden, um als Batch-Klasse verwendet werden zu können. Sie stellt drei Methoden bereit, die von der Batch-Klasse implementiert werden müssen:

1. start()

Diese Methode definiert den Gültigkeitsbereich der Datensätze oder Objekte, die von der Schnittstellenmethode `execute` verarbeitet werden sollen. Sie wird während der Batch-Ausführung nur einmal aufgerufen. Die Methode gibt entweder ein `Database.QueryLocator`-Objekt oder ein `Iterable`-Objekt zurück. Mit einem `Database.QueryLocator`-Objekt können 50 Millionen Datensätze per SOQL-Abfrage abgerufen werden, mit einem `Iterable`-Objekt hingegen nur 50,000. Ein `Iterable`-Objekt dient zur Definition eines komplexen Gültigkeitsbereichs für die Batch-Klasse.

Syntax der Startmethode:

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

2. execute()

Diese Methode dient der Verarbeitung jedes Datenblocks. Die Methode `execute` wird für jeden Datensatzblock aufgerufen. Die Standard-Batchgröße für die Ausführung beträgt 200 Datensätze. Die Methode `execute` benötigt zwei Argumente:

Ein Verweis auf das Database.BatchableContext-Objekt,

Eine Liste von sObjects, wie z. B. List oder eine Liste parametrisierter Typen. Syntax der execute-Methode:

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

3. finish()

Die `finish`-Methode wird einmalig während der Ausführung der Batch-Klasse aufgerufen. Nachbearbeitungsoperationen können in der `finish`-Methode durchgeführt werden, beispielsweise das Versenden einer Bestätigungs-E-Mail. Diese Methode wird aufgerufen, sobald alle Batches verarbeitet wurden. Syntax der `finish`-Methode:

global void finish(Database.BatchableContext bc){}

Database.BatchableContext-Objekt

Jede Methode der Database.Batchable-Schnittstelle besitzt eine Referenz auf ein Database.BatchableContext-Objekt.

Dieses Objekt wird verwendet, um track den Fortschritt des Batch-Jobs.

Im Folgenden sind die von BatchableContext bereitgestellten Instanzmethoden aufgeführt:

  • getChildJobId(): Diese Methode gibt die ID des Batch-Jobs zurück, der gerade verarbeitet wird.
  • getJobId(): Diese Methode gibt die ID des Batch-Jobs zurück.

Nachfolgend die Syntax einer Batch-Klasse:

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

Database.executeBatch-Methode

Die Methode Database.executeBatch wird zum Ausführen einer Batch-Klasse verwendet.

Diese Methode benötigt zwei Parameter: eine Instanz der zu verarbeitenden Batch-Klasse und einen optionalen Bereichsparameter zur Angabe der Batchgröße. Wird dieser nicht angegeben, wird die Standardgröße von 200 verwendet.

Syntax von Database.executeBatch:

Database.executeBatch(myBatchObject, scope)

Ausführen einer Batch-Klasse namens MyBatchClass:

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

Database.Stateful

Eine Batch-Klasse ist standardmäßig zustandslos. Bei jedem Aufruf der execute-Methode wird eine neue Kopie des Objekts empfangen und alle Variablen der Klasse werden initialisiert.

Database.Stateful wird implementiert, um eine Batch-Klasse zustandsbehaftet zu machen.

Wenn Ihre Batch-Klasse die DatenbankBei der zustandsbehafteten Schnittstelle behalten alle Instanzvariablen ihre Werte, statische Variablen werden jedoch zwischen Transaktionen zurückgesetzt.

Asynchrones Apex jenseits von Batch

Batch Apex ist nur eine von mehreren Möglichkeiten, Code asynchron auszuführen. Salesforce bietet vier asynchrone Optionen an, und die Wahl der richtigen Option hängt davon ab, wie viele Daten verarbeitet werden und ob Jobs verkettet oder geplant werden müssen.

  • Zukünftige Methoden: Mit @future annotiert, eignen sie sich am besten für einfache, einmalige Operationen wie Aufrufe externer Webdienste.
  • Warteschlangenfähiger Apex: Implementiert die Queueable-Schnittstelle, akzeptiert komplexe Objekttypen, gibt eine Job-ID zurück und unterstützt die Verkettung von Jobs.
  • Batch Apex: Verarbeitet sehr große Datenmengen in Blöcken, wie oben beschrieben.
  • Geplanter Scheitelpunkt: Implementiert die Scheduable-Schnittstelle, sodass eine Klasse zu einem bestimmten Zeitpunkt ausgeführt wird, beispielsweise ein nächtlicher Aufräumvorgang.
Typ besten Für Schlüsselfunktion
Zukunftsmethode Einfache Anrufe Feuern und vergessen
Warteschlangenfähiger Apex Sequentielle Verarbeitung Jobverkettung und Überwachung
Batch Apex Millionen von Datensätzen Blockverarbeitung
Geplanter Scheitelpunkt Wiederkehrende Jobs Cron-basierte Zeitsteuerung

Unabhängig davon, welches Ausführungsmodell Sie wählen, wird jede Transaktion weiterhin an den unten aufgeführten plattformweiten Governor-Limits gemessen.

Apex-Gouverneur-Grenzwerte

Die Apex-Governor-Limits sind die von der Apex-Laufzeitumgebung festgelegten Grenzwerte, die sicherstellen, dass fehlerhafter Apex-Code und -Prozesse die gemeinsam genutzten Ressourcen nicht monopolisieren und die Verarbeitung anderer Benutzer in der Mandantenumgebung nicht beeinträchtigen. Diese Grenzwerte werden für jede Apex-Transaktion überprüft. Im Folgenden sind die von Salesforce für jede Apex-Transaktion definierten Governor-Limits aufgeführt:

Beschreibung Einschränkung
SOQL-Abfragen, die in einer synchronen Transaktion ausgeführt werden können 100
SOQL-Abfragen, die in einer asynchronen Transaktion ausgeführt werden können 200
Datensätze, die durch eine SOQL-Abfrage abgerufen werden können 50,000
Datensätze, die von Database.getQueryLocator abgerufen werden können 10,000
SOSL-Abfragen, die in einer Apex-Transaktion durchgeführt werden können 20
Datensätze, die durch eine SOSL-Abfrage abgerufen werden können 2,000
DML-Anweisungen, die in einer Apex-Transaktion ausgeführt werden können 150
Datensätze, die als Ergebnis einer DML-Anweisung, Approval.process oder Database.emptyRecycleBin verarbeitet werden können 10,000
Aufrufe, die in einer Apex-Transaktion durchgeführt werden können 100
Kumulatives Timeout-Limit für alle Aufrufe, die in einer Apex-Transaktion ausgeführt werden. 120 Sekunden
Beschränkung der Anzahl von Apex-Jobs, die mit System.enqueueJob zur Warteschlange hinzugefügt werden können 50
Ausführungszeitlimit für jede Apex-Transaktion 10 Мinuten
Beschränkung der Zeichen, die in einer Apex-Klasse und einem Trigger verwendet werden können 1 Millionen
CPU-Zeitlimit für eine synchrone Transaktion 10,000 Millisekunden
CPU-Zeitlimit für eine asynchrone Transaktion 60,000 Millisekunden
Gesamthaufengröße 6 MB (synchron) / 12 MB (asynchron)

Wie man eine Testklasse in Apex schreibt

Salesforce verlangt, dass mindestens 75 Prozent Ihres Apex-Codes durch Unit-Tests abgedeckt sind, bevor Sie ihn in der Produktionsumgebung bereitstellen dürfen. Jeder Trigger muss zudem eine gewisse Testabdeckung aufweisen. Das Schreiben von Testklassen ist daher eine Kernkompetenz in Apex und keine optionale Zusatzqualifikation.

Eine Testklasse wird mit @isTest annotiert, und jede Testmethode ist ebenfalls mit @isTest gekennzeichnet. Testmethoden schreiben keine Daten in die Datenbank und greifen nicht auf die meisten vorhandenen Organisationsdaten zu; daher erstellt jeder Test seine eigenen Datensätze. Die Methoden Test.startTest() und Test.stopTest() weisen dem zu testenden Code neue Governor-Limits zu, und Assertions überprüfen, ob die Logik wie erwartet funktioniert hat.

Hier ist eine einfache Testklasse für die Logik zur Kontoerstellung:

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

Beachten Sie beim Erstellen von Tests folgende Richtlinien:

  • Verwenden Sie die Methode @testSetup, um einmalig gemeinsam genutzte Testdaten für alle Testmethoden in der Klasse zu erstellen.
  • Testen Sie das Verhalten bei großen Datenmengen, indem Sie 200 Datensätze einfügen, nicht nur einen.
  • Berücksichtigen Sie positive, negative und eingeschränkte Benutzerszenarien.
  • Fügen Sie immer aussagekräftige System.assert-Anweisungen hinzu; eine Testabdeckung ohne Assertions beweist gar nichts.

Apex Best Practices

Anfänger schreiben oft Apex-Code, der zwar für einen einzelnen Datensatz funktioniert, aber bei großen Datenmengen in der Praxis versagt. Die folgenden Vorgehensweisen sorgen dafür, dass Ihr Code innerhalb der Governor-Grenzen bleibt und leichter gewartet werden kann:

  • Alles verdichten: Schreiben Sie eine Logik, die Sammlungen von Datensätzen verarbeiten kann, da Trigger bis zu 200 Datensätze in einem einzigen Batch empfangen können.
  • SOQL- und DML-Schleifen vermeiden: Führe vor der Schleife eine Abfrage durch, sammle die Änderungen in einer Liste und führe nach der Schleife eine DML-Anweisung aus.
  • Ein Auslöser pro Objekt: Trigger sollten frei von Logik sein, und die Arbeit sollte an Handler-Klassen delegiert werden, wodurch die Ausführungsreihenfolge vorhersehbar wird.
  • Verwendung mit Weitergabe: Die Sicherheit sollte auf Datensatzebene durchgesetzt werden, es sei denn, es gibt einen dokumentierten Grund für die Ausführung im Systemkontext.
  • Vermeiden Sie fest codierte IDs: Die Datensatz-IDs unterscheiden sich zwischen Sandbox- und Produktionsumgebungen. Fragen Sie daher danach oder verwenden Sie stattdessen benutzerdefinierte Metadaten.
  • Überwachung von Grenzwerten im Code: Mit den Methoden der Klasse Limits, wie zum Beispiel Limits.getQueries(), können Sie den Ressourcenverbrauch zur Laufzeit überprüfen.

💡 TIPP: Testen Sie Ihren Code vor der Bereitstellung mit 200 Datensätzen in einer Sandbox. Die meisten Fehler aufgrund von Governor-Limits treten erst bei großen Datenmengen auf, und deren frühzeitige Erkennung ist wesentlich kostengünstiger als die Fehlersuche in der Produktionsumgebung.

Häufig gestellte Fragen

Nein. Apex leiht sich Geld. Java-ähnliche Syntax, aber sie unterscheidet nicht zwischen Groß- und Kleinschreibung, läuft nur auf der Salesforce Lightning Platform, integriert SOQL direkt in die Sprache und unterliegt transaktionsbezogenen Beschränkungen, Java hat nicht.

Registrieren Sie sich für eine kostenlose Salesforce Developer Edition-Organisation, die die Entwicklerkonsole enthält, und folgen Sie den praktischen Übungen auf Trailhead, die offizielle Lernplattform von Salesforce.

Visualforce ist eine Auszeichnungssprache zum Erstellen von Benutzeroberflächen, während Apex die serverseitige Sprache ist, die die zugrundeliegende Logik bereitstellt. Visualforce-Seiten rufen häufig Apex-Controller-Klassen auf, um Daten abzufragen und zu aktualisieren.

Ja. Agentforce für Entwickler, der KI-Assistent von Salesforce für Visual Studio CodeDie KI generiert und erklärt Apex-Code anhand von natürlichsprachlichen Eingabeaufforderungen. Überprüfen und testen Sie den KI-generierten Code vor der Bereitstellung stets anhand der Governor-Limits.

Mit der Annotation @InvocableMethod gekennzeichnete Apex-Klassen können als benutzerdefinierte Aktionen bereitgestellt werden, sodass Einstein-Bots und Agentforce-Agenten Ihre Geschäftslogik aufrufen können. Gleichzeitig kann Apex über Plattform-APIs auch Einstein-Prompt-Vorlagen und KI-Modelle aufrufen.

Fassen Sie diesen Beitrag mit folgenden Worten zusammen: