Erste Schritte mit Apex-Auslösern
Lernziele
Nachdem Sie diese Lektion abgeschlossen haben, sind Sie in der Lage, die folgenden Aufgaben auszuführen:
- Schreiben eines Auslösers für ein Salesforce-Objekt
- Verwenden von Auslöser-Kontextvariablen
- Aufrufen einer Klassenmethode über einen Auslöser
- Verwenden der sObject-Methode
addError()
in einem Auslöser, um Speichervorgänge zu beschränken
Bevor Sie loslegen
Apex-Auslöser sind überaus nützlich. Dieses Modul hilft Ihnen nicht nur bei den ersten Schritten, sondern enthält auch Verweise auf andere Salesforce-Funktionen, um Ihnen die Leistungsfähigkeit von Apex-Auslösern zu zeigen. Um den größten Nutzen aus diesem Modul zu ziehen, empfehlen wir Ihnen wärmstens, sich zuerst diese Module anzusehen:
- Schnelleinstieg: Apex
- Apex – Grundlagen und Datenbank
- SOQL für Administratoren
- Grundlagen der Entwicklerkonsole
Schreiben von Apex-Auslösern
Mithilfe von Apex-Auslösern können Sie benutzerdefinierte Aktionen vor oder nach Ereignissen bei Datensätzen in Salesforce ausführen, wie etwa Einfüge-, Aktualisierungs- oder Löschvorgänge. Ebenso wie Datenbanksysteme Auslöser unterstützen, unterstützt auch Apex Auslöser zur Verwaltung von Datensätzen.
In der Regel werden Auslöser dazu verwendet, Vorgänge basierend auf bestimmten Bedingungen durchzuführen, verknüpfte Datensätze zu bearbeiten oder bestimmte Vorgänge zu unterbinden. Mithilfe von Auslösern können Sie die gleichen Aufgaben wie in Apex durchführen, einschließlich Ausführen von SOQL und DML und Aufrufen von benutzerdefinierten Apex-Methoden.
Verwenden Sie Auslöser, um Aufgaben durchzuführen, die mithilfe der Zeigen-und-Klicken-Tools auf der Salesforce-Benutzeroberfläche nicht möglich sind. Verwenden Sie beispielsweise zur Validierung eines Feldwerts oder Aktualisierung eines Felds in einem Datensatz stattdessen Validierungsregeln und Flows. Verwenden Sie Apex-Trigger. wenn Leistung und Größenordnung wichtig sind, Ihre Logik zu komplex für die Zeigen-und-Klicken-Tools ist oder Sie CPU-intensive Vorgänge ausführen.
Auslöser können für Standardobjekte der obersten Ebene, wie Accounts oder Kontakte, benutzerdefinierte Objekte und einige untergeordnete Standardobjekte definiert werden. Auslöser sind nach der Erstellung standardmäßig aktiv. Salesforce führt aktive Auslöser automatisch aus, wenn die angegebenen Datenbankereignisse eintreten.
Auslösersyntax
Die Syntax einer Auslöserdefinition unterscheidet sich von der Syntax einer Klassendefinition. Eine Auslöserdefinition beginnt mit dem Schlüsselwort trigger
. Darauf folgen der Name des Auslösers, das Salesforce-Objekt, dem der Auslöser zugeordnet ist, und die Bedingungen, unter denen der Auslöser ausgeführt wird. Die Syntax eines Auslösers sieht wie folgt aus:
trigger TriggerName on ObjectName (trigger_events) { code_block }
Wenn ein Auslöser vor oder nach Vorgängen zum Einfügen, Aktualisieren, Löschen und Rückgängigmachen eines Löschvorgangs ausgeführt werden soll, geben Sie mehrere Auslöserereignisse in einer kommagetrennten Liste an. Folgende Ereignisse können angegeben werden:
before insert
before update
before delete
after insert
after update
after delete
after undelete
Beispiel eines Auslösers
Dieser einfache Auslöser wird ausgeführt, bevor Sie einen Account einfügen, und schreibt eine Meldung in das Debug-Protokoll.
- Klicken Sie in der Developer Console auf File (Datei) | New (Neu) | Apex Trigger (Apex-Auslöser).
- Geben Sie als Auslösernamen
HelloWorldTrigger
ein und wählen Sie dann "Account" für das sObject aus. Klicken Sie auf Submit (Senden). - Ersetzen Sie den Standardcode durch Folgendes:
trigger HelloWorldTrigger on Account (before insert) { System.debug('Hello World!'); }
- Speichern Sie mit Strg+S.
- Um den Auslöser zu testen, erstellen Sie einen Account.
- Klicken Sie auf Debug | Open Execute Anonymous Window (Debuggen | Fenster für die anonyme Ausführung öffnen).
- Fügen Sie in dem neuen Fenster Folgendes hinzu und klicken Sie dann auf Execute (Ausführen).
Account a = new Account(Name='Test Trigger'); insert a;
- Suchen Sie im Debug-Protokoll nach der Anweisung
Hello World!
. Im Protokoll wird außerdem angegeben, dass der Auslöser ausgeführt wurde.
Typen von Auslösern
Es gibt zwei Typen von Auslösern.
- Before-Auslöser werden zum Aktualisieren oder Validieren von Datensatzwerten verwendet, bevor diese in der Datenbank gespeichert werden.
- After-Auslöser werden verwendet, um auf Feldwerte zuzugreifen, die vom System festgelegt werden (z. B. das Feld
Id
oderLastModifiedDate
eines Datensatzes), und um Änderungen in anderen Datensätzen zu bewirken. Die Datensätze, durch die der after-Auslöser ausgeführt wird, sind schreibgeschützt.
Verwenden von Kontextvariablen
Verwenden Sie zum Zugreifen auf die Datensätze, durch die der Auslöser ausgeführt wurde, Kontextvariablen. Trigger.new
enthält beispielsweise alle Datensätze, die in "insert"- oder "update"-Auslöser eingefügt wurden. Trigger.old
enthält die alte Version von sObjects, bevor sie in "update"-Auslösern aktualisiert wurden, oder eine Liste mit gelöschten sObjects in "delete"-Auslösern. Auslöser können ausgeführt werden, wenn ein einzelner Datensatz eingefügt wird oder wenn mehrere Datensätze als Massenvorgang über die API oder Apex eingefügt werden. Daher können Kontextvariablen wie Trigger.new
nur einen oder mehrere Datensätze enthalten. Sie können Trigger.new
durchlaufen, um jedes einzelne sObject abzurufen.
Das folgende Beispiel ist eine geänderte Version des Beispielauslösers HelloWorldTrigger
. Darin wird jeder Account in einer "for"-Schleife durchlaufen und das jeweilige Description
(Beschreibungsfeld) aktualisiert.
trigger HelloWorldTrigger on Account (before insert) { for(Account a : Trigger.new) { a.Description = 'New description'; } }
Einige andere Kontextvariablen geben einen booleschen Wert zurück, um anzugeben, ob der Auslöser aufgrund einer Aktualisierung oder eines anderen Ereignisses ausgeführt wurde. Diese Variablen sind nützlich, wenn ein Auslöser mehrere Ereignisse kombiniert. Beispiel:
trigger ContextExampleTrigger on Account (before insert, after insert, after delete) { if (Trigger.isInsert) { if (Trigger.isBefore) { // Process before insert } else if (Trigger.isAfter) { // Process after insert } } else if (Trigger.isDelete) { // Process after delete } }
Die folgende Tabelle enthält eine vollständige Liste aller für Auslöser verfügbaren Kontextvariablen.
Variable | Verwendung |
---|---|
isExecuting | Gibt "true" (wahr) zurück, wenn der aktuelle Kontext für den Apex-Code ein Auslöser ist und nicht eine Visualforce-Seite, ein Webservice oder ein API-Aufruf des Typs |
isInsert | Gibt |
isUpdate | Gibt |
isDelete | Gibt |
isBefore | Gibt |
isAfter | Gibt |
isUndelete | Gibt |
new | Gibt eine Liste der neuen Versionen der sObject-Datensätze zurück. Diese sObject-Liste ist nur in |
newMap | Eine Zuordnung von IDs zu den neuen Versionen der sObject-Datensätze. Diese Zuordnung ist nur in |
old | Gibt eine Liste der alten Versionen der sObject-Datensätze zurück. Diese sObject-Liste ist nur in |
oldMap | Eine Zuordnung von IDs zu den alten Versionen der sObject-Datensätze. Diese Zuordnung ist nur in |
operationType | Gibt eine Enumeration des Typs System.TriggerOperation zurück, der dem aktuellen Vorgang entspricht. Mögliche Werte der Enumeration |
size | Die Gesamtanzahl der Datensätze in einem Auslöseraufruf, sowohl alte als auch neue. |
Aufrufen einer Klassenmethode über einen Auslöser
Sie können öffentliche Dienstprogrammmethoden über einen Auslöser aufrufen. Das Aufrufen von Methoden anderer Klassen ermöglicht die Wiederverwendung von Code, reduziert die Größe der Auslöser und vereinfacht die Pflege des Apex-Codes. Außerdem können Sie damit objektorientierte Programmierung verwenden.
Der folgende Beispielauslöser zeigt, wie eine statische Methode über einen Auslöser aufgerufen wird. Wenn der Auslöser aufgrund eines insert-Ereignisses ausgeführt wurde, ruft das Beispiel die statische Methode "sendMail()
" in der Klasse "EmailManager
" auf. Diese Dienstprogrammmethode sendet eine E-Mail an den angegebenen Empfänger und enthält die Anzahl der eingefügten Kontaktdatensätze.
- Klicken Sie in der Developer Console auf File (Datei) | New (Neu) | Apex Class (Apex-Klasse).
- Geben Sie
EmailManager
ein und klicken Sie auf "OK". - Ersetzen Sie den Standardtext der Klasse durch das nachfolgenden Beispiel für die
EmailManager
-Klasse.public class EmailManager { // Public method public static void sendMail(String address, String subject, String body) { // Create an email message object Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); String[] toAddresses = new String[] {address}; mail.setToAddresses(toAddresses); mail.setSubject(subject); mail.setPlainTextBody(body); // Pass this email message to the built-in sendEmail method // of the Messaging class Messaging.SendEmailResult[] results = Messaging.sendEmail( new Messaging.SingleEmailMessage[] { mail }); // Call a helper method to inspect the returned results inspectResults(results); } // Helper method private static Boolean inspectResults(Messaging.SendEmailResult[] results) { Boolean sendResult = true; // sendEmail returns an array of result objects. // Iterate through the list to inspect results. // In this class, the methods send only one email, // so we should have only one result. for (Messaging.SendEmailResult res : results) { if (res.isSuccess()) { System.debug('Email sent successfully'); } else { sendResult = false; System.debug('The following errors occurred: ' + res.getErrors()); } } return sendResult; } }
- Klicken Sie in der Developer Console auf File (Datei) | New (Neu) | Apex Trigger (Apex-Auslöser).
- Geben Sie als Auslösernamen
ExampleTrigger
ein und wählen Sie dann Contact für das sObject aus. Klicken Sie auf Submit (Senden). - Ersetzen Sie den Standardcode durch Folgendes und ersetzen Sie dann den Platzhaltertext für die E-Mail-Adresse in
sendMail()
durch Ihre E-Mail-Adresse.trigger ExampleTrigger on Contact (after insert, after delete) { if (Trigger.isInsert) { Integer recordCount = Trigger.new.size(); // Call a utility method from another class EmailManager.sendMail('Your email address', 'Trailhead Trigger Tutorial', recordCount + ' contact(s) were inserted.'); } else if (Trigger.isDelete) { // Process after delete } }
- Speichern Sie mit Strg+S.
- Um den Auslöser zu testen, erstellen Sie einen Kontakt.
- Klicken Sie auf Debug | Open Execute Anonymous Window (Debuggen | Fenster für die anonyme Ausführung öffnen).
- Fügen Sie in dem neuen Fenster Folgendes hinzu und klicken Sie dann auf Execute (Ausführen).
Contact c = new Contact(LastName='Test Contact'); insert c;
- Überprüfen Sie im Debug-Protokoll, dass der Auslöser ausgeführt wurde. Suchen Sie am Ende des Protokolls nach der Debug-Meldung, die von der Dienstprogrammmethode geschrieben wurde:
DEBUG|Email sent successfully
- Kontrollieren Sie jetzt, dass Sie eine E-Mail mit dem Nachrichtentext
1 contact(s) were inserted.
(1 Kontakt(e) wurde(n) eingefügt) erhalten haben.
Mit dem neuen Auslöser erhalten Sie jedes Mal eine E-Mail, wenn Sie einen oder mehrere Kontakte hinzufügen.
Hinzufügen verknüpfter Datensätze
Auslöser werden oft zum Zugreifen auf und Verwalten von Datensätzen verwendet, die mit den Datensätzen im Auslöserkontext, d. h. den Datensätzen, durch die dieser Auslöser ausgeführt wurde, verknüpft sind.
Dieser Auslöser fügt für jeden neuen oder aktualisierten Account eine verknüpfte Opportunity hinzu, wenn dem betreffenden Account noch keine Opportunity zugeordnet ist. Der Auslöser führt zuerst eine SOQL-Abfrage durch, um alle untergeordneten Opportunities für die Accounts abzurufen, bei denen der Auslöser ausgeführt wurde. Als Nächstes durchläuft der Auslöser die Liste der sObjects in Trigger.new
, um jedes Account-sObject abzurufen. Wenn mit dem Account noch kein Opportunity-sObject verknüpft ist, erstellt die For-Schleife eines. Wenn der Auslöser neue Opportunities erstellt hat, werden diese durch die letzte Anweisung eingefügt.
- Fügen Sie den folgenden Auslöser mithilfe der Entwicklerkonsole hinzu (führen Sie dazu die Schritte im Beispiel
HelloWorldTrigger
aus, geben Sie jedoch als AuslösernamenAddRelatedRecord
ein).trigger AddRelatedRecord on Account(after insert, after update) { List<Opportunity> oppList = new List<Opportunity>(); // Get the related opportunities for the accounts in this trigger Map<Id,Account> acctsWithOpps = new Map<Id,Account>( [SELECT Id,(SELECT Id FROM Opportunities) FROM Account WHERE Id IN :Trigger.new]); // Add an opportunity for each account if it doesn't already have one. // Iterate through each account. for(Account a : Trigger.new) { System.debug('acctsWithOpps.get(a.Id).Opportunities.size()=' + acctsWithOpps.get(a.Id).Opportunities.size()); // Check if the account already has a related opportunity. if (acctsWithOpps.get(a.Id).Opportunities.size() == 0) { // If it doesn't, add a default opportunity oppList.add(new Opportunity(Name=a.Name + ' Opportunity', StageName='Prospecting', CloseDate=System.today().addMonths(1), AccountId=a.Id)); } } if (oppList.size() > 0) { insert oppList; } }
- Um den Auslöser zu testen, erstellen Sie auf der Salesforce-Benutzeroberfläche einen Account und nennen Sie ihn
Apples & Oranges
. - Suchen Sie in der Themenliste "Opportunities" auf der Seite des Accounts nach der neuen Opportunity. Der Auslöser hat diese Opportunity automatisch hinzugefügt!
Verwenden von Auslöserausnahmen
In manchen Fällen müssen Sie Beschränkungen für bestimmte Datenbankvorgänge hinzufügen, z. B. wenn Sie verhindern möchten, dass Datensätze gespeichert werden, sobald bestimmte Bedingungen erfüllt sind. Um das Speichern von Datensätzen in einem Auslöser zu verhindern, rufen Sie die Methode "addError()
" für das betreffende sObject auf. Die Methode "addError()
" löst einen schwerwiegenden Fehler in einem Auslöser aus. Die Fehlermeldung wird auf der Benutzeroberfläche angezeigt und protokolliert.
Der folgende Auslöser verhindert das Löschen eines Accounts, wenn damit Opportunities verknüpft sind. Standardmäßig führt das Löschen eines Accounts zu einer Kaskadenlöschung aller seiner verknüpften Datensätze. Dieser Auslöser verhindert die Kaskadenlöschung von Opportunities. Probieren Sie diesen Auslöser selbst aus. Wenn Sie das vorherige Beispiel ausgeführt haben, verfügt Ihre Organisation jetzt über einen Account namens Apples & Oranges
mit einer verknüpften Opportunity. In folgendem Beispiel wird dieser Beispielaccount verwendet.
- Fügen Sie mithilfe der Entwicklerkonsole folgenden Auslöser hinzu.
trigger AccountDeletion on Account (before delete) { // Prevent the deletion of accounts if they have related opportunities. for (Account a : [SELECT Id FROM Account WHERE Id IN (SELECT AccountId FROM Opportunity) AND Id IN :Trigger.old]) { Trigger.oldMap.get(a.Id).addError( 'Cannot delete account with related opportunities.'); } }
- Wechseln Sie auf der Salesforce-Benutzeroberfläche zur Seite des Accounts
Apples & Oranges
und klicken Sie auf Löschen. - Klicken Sie im eingeblendeten Bestätigungsfenster auf OK.
Suchen Sie nach dem Validierungsfehler mit der benutzerdefinierten FehlermeldungCannot delete account with related opportunities.
(Account mit verknüpften Opportunities kann nicht gelöscht werden).
- Deaktivieren Sie den Auslöser
AccountDeletion
. Wenn Sie diesen Auslöser im aktiven Status belassen, können Sie Ihre Abfragen nicht überprüfen.
- Suchen Sie im Setup nach
Apex Triggers
(Apex-Auslöser). - Klicken Sie auf der Seite "Apex Triggers (Apex-Auslöser)" neben dem Auslöser
AccountDeletion
auf Edit (Bearbeiten). - Deaktivieren Sie die Option Is Active (Ist aktiv).
- Klicken Sie auf Speichern.
Auslöser und Callouts
Mit Apex können Sie Aufrufe bei externen Webservices vornehmen und Ihren Apex-Code in externe Webservices integrieren. Apex-Aufrufe bei externen Webservices werden als Callouts bezeichnet. Sie können beispielsweise einen Callout bei einem Kursabfragesystem vornehmen, um die aktuellen Aktienkurse abzurufen. Beim Senden eines Callouts über einen Auslöser muss der Callout asynchron erfolgen, sodass der Auslöserprozess Sie nicht am Arbeiten hindert, während auf die Antwort vom externen Service gewartet wird. Der asynchrone Callout erfolgt in einem Prozess im Hintergrund und die Antwort wird empfangen, sobald der externe Service sie zurückgibt.
Um einen Callout über einen Auslöser vorzunehmen, rufen Sie eine Klassenmethode auf, die asynchron ausgeführt wird. Eine solche Methode wird als future-Methode bezeichnet und mit der Anmerkung "@future(callout=true)
" gekennzeichnet. Die folgende Beispielklasse enthält die future-Methode, die den Callout vornimmt.
public class CalloutClass { @future(callout=true) public static void makeCallout() { HttpRequest request = new HttpRequest(); // Set the endpoint URL. String endpoint = 'http://yourHost/yourService'; request.setEndPoint(endpoint); // Set the HTTP verb to GET. request.setMethod('GET'); // Send the HTTP request and get the response. HttpResponse response = new HTTP().send(request); } }
Das folgende Beispiel zeigt den Auslöser, der die Methode in der Klasse aufruft, um einen Callout asynchron vorzunehmen.
trigger CalloutTrigger on Account (before insert, before update) { CalloutClass.makeCallout(); }
Dieser Abschnitt bietet nur einen Überblick über Calllouts und ist nicht dazu gedacht, Callouts im Detail zu behandeln. Weitere Informationen finden Sie im Apex Developer Guide unter Invoking Callouts Using Apex.
Ressourcen
- Apex Developer Guide: Auslöser
- Apex Developer Guide: Invoking Callouts Using Apex
- Trailhead: Apex-Integrationsservices