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 } }
Diese 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 notifyUsers()
in der Klasse CustomContactNotification
auf. Diese Dienstprogrammmethode sendet eine benutzerdefinierte Benachrichtigung an die im Auslöser definierten Salesforce-Benutzer. Die Benachrichtigung enthält die Zahl der eingefügten Kontaktdatensätze.
- Erstellen Sie eine benutzerdefinierte Desktop-Benachrichtigung.
- Geben Sie in "Setup" im Feld "Quick Find" (Schnellsuche)
Notification Builder
(Benachrichtigungsgenerator) ein und wählen Sie Custom Notifications (Benutzerdefinierte Benachrichtigungen) aus.
- Klicken Sie auf New (Neu).
- Geben Sie bei "Custom Notification Name" (Name der benutzerdefinierten Benachrichtigung)
New Contact Notification
(Benachrichtigung bei neuem Kontakt) ein.
- Geben Sie bei "API Name" (API-Name)
New_Contact_Notification
ein.
- Wählen Sie bei "Supported Channels" (Unterstützte Kanäle) Desktop aus.
- Klicken Sie auf Save (Speichern).
- Geben Sie in "Setup" im Feld "Quick Find" (Schnellsuche)
- Klicken Sie in der Developer Console auf File (Datei) | New (Neu) | Apex Class (Apex-Klasse).
- Geben Sie
CustomContactNotification
ein und klicken Sie auf OK.
- Ersetzen Sie den Standardtext der Klasse durch das nachfolgende Beispiel für die
CustomContactNotification
-Klasse.
public with sharing class CustomContactNotification { // Public method public static void notifyUsers(Set<String> recipientsIds, Integer recordCount) { // Get the ID for the custom notification type created in Setup CustomNotificationType notificationType = [SELECT Id, DeveloperName FROM CustomNotificationType WHERE DeveloperName='New_Contact_Notification']; // Create a new custom notification Messaging.CustomNotification notification = new Messaging.CustomNotification(); // Set the contents for the notification notification.setTitle('Trailhead Trigger Tutorial'); notification.setBody(recordCount + ' contact(s) were inserted.'); // Set the notification type and target notification.setNotificationTypeId(notificationType.Id); // '000000000000000AAA' is a dummy targetId value notification.setTargetId('000000000000000AAA'); // Send the notification try { notification.send(recipientsIds); System.debug('Custom notification sent successfully.'); } catch (Exception e) { System.debug('Problem sending notification: ' + e.getMessage()); } } }
- Klicken Sie in der Developer Console auf File (Datei) | New (Neu) | Apex Trigger (Apex-Auslöser).
- Geben Sie als Auslösernamen
ContactNotificationTrigger
ein und wählen Sie dann Contact (Kontakt) für das sObject aus. Klicken Sie auf Submit (Senden).
- Ersetzen Sie den Standardcode durch Folgendes:
trigger ContactNotificationTrigger on Contact (after insert, after delete) { if (Trigger.isInsert) { Integer recordCount = Trigger.new.size(); // Set the recipientIDs to the current user Set<String> recipientIDs = new Set<String>{UserInfo.getUserId()}; // Call a utility method from another class CustomContactNotification.notifyUsers(recipientIDs, recordCount); } 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|Custom notification sent successfully.
(DEBUG|Benutzerdefinierte Benachrichtigung wurde erfolgreich gesendet.) - Prüfen Sie nun, dass Sie die Benachrichtigung erhalten haben. Klicken Sie auf
, um den Bereich "Notification" (Benachrichtigung) zu öffnen. Sie sollten eine Benachrichtigung mit dem Titel “Trailhead Trigger Tutorial” und dem Text “1 contact(s) were inserted” (1 Kontakt(e) wurde(n) eingefügt) erhalten haben.
Mit dem neuen Auslöser erhalten Sie jedes Mal eine benutzerdefinierte Desktop-Benachrichtigung, 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 Fehlermeldung Cannot 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
- Apex Reference Guide: CustomNotification-Klasse
- Trailhead: Apex-Integrationsservices