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

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 Workflow-Regeln.

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

Dieser einfache Auslöser wird ausgeführt, bevor Sie einen Account einfügen, und schreibt eine Meldung in das Debug-Protokoll.
  1. Klicken Sie in der Developer Console auf File (Datei) | New (Neu) | Apex Trigger (Apex-Auslöser).
  2. Geben Sie als Auslösernamen HelloWorldTrigger ein und wählen Sie dann "Account" für das sObject aus. Klicken Sie auf Submit (Senden).
  3. Ersetzen Sie den Standardcode durch Folgendes:
    trigger HelloWorldTrigger on Account (before insert) {
    	System.debug('Hello World!');
    }
  4. Speichern Sie mit Strg+S.
  5. Um den Auslöser zu testen, erstellen Sie einen Account.
    1. Klicken Sie auf Debug | Open Execute Anonymous Window (Debuggen | Fenster für die anonyme Ausführung öffnen).
    2. 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;
  6. 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" oder "LastModifiedDate" 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" beispielsweise enthält alle Datensätze, die in insert- oder update-Auslösern 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 Beschreibungsfeld aktualisiert.

trigger HelloWorldTrigger on Account (before insert) {
    for(Account a : Trigger.New) {
        a.Description = 'New description';
    }   
}
Hinweis

Hinweis

Das System speichert die Datensätze, durch die der before-Auslöser ausgeführt wurde, nach der Ausführung des Auslösers. Sie können die Datensätze im Auslöser ändern, ohne explizit einen DML-insert- oder -update-Vorgang aufzurufen. Wenn Sie bei diesen Datensätzen DML-Anweisungen ausführen, wird ein Fehler ausgegeben.

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

Kontextvariablen von Auslösern

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 executeanonymous().
isInsert Gibt true zurück, wenn dieser Auslöser aufgrund eines Einfügevorgangs (insert) über die Salesforce-Benutzeroberfläche, Apex oder die API ausgeführt wurde.
isUpdate Gibt true zurück, wenn dieser Auslöser aufgrund eines Aktualisierungsvorgangs (update) über die Salesforce-Benutzeroberfläche, Apex oder die API ausgeführt wurde.
isDelete Gibt true zurück, wenn dieser Auslöser aufgrund eines Löschvorgangs (delete) über die Salesforce-Benutzeroberfläche, Apex oder die API ausgeführt wurde.
isBefore Gibt true zurück, wenn dieser Auslöser ausgeführt wurde, bevor ein Datensatz gespeichert wurde.
isAfter Gibt true zurück, wenn dieser Auslöser ausgeführt wurde, nachdem alle Datensätze gespeichert wurden.
isUndelete Gibt true zurück, wenn dieser Auslöser ausgeführt wurde, nachdem ein Datensatz aus dem Papierkorb wiederhergestellt wurde. Diese Wiederherstellung kann nach einem Vorgang zum Rückgängigmachen eines Löschvorgangs (undelete) über die Salesforce-Benutzeroberfläche, Apex oder die API auftreten.
new Gibt eine Liste der neuen Versionen der sObject-Datensätze zurück.

Diese sObject-Liste ist nur in insert-, update- und undelete-Auslösern verfügbar und die Datensätze können nur in before geändert werden.

newMap Eine Zuordnung von IDs zu den neuen Versionen der sObject-Datensätze.

Diese Zuordnung ist nur in before update-, after insert-, after update- und after undelete-Auslösern verfügbar.

old Gibt eine Liste der alten Versionen der sObject-Datensätze zurück.

Diese sObject-Liste ist nur in update- und delete-Auslösern verfügbar.

oldMap Eine Zuordnung von IDs zu den alten Versionen der sObject-Datensätze.

Diese Zuordnung ist nur in update- und delete-Auslösern verfügbar.

operationType Gibt eine Enumeration des Typs System.TriggerOperation zurück, der dem aktuellen Vorgang entspricht.

Mögliche Werte der Enumeration System.TriggerOperation sind: BEFORE_INSERT, BEFORE_UPDATE, BEFORE_DELETE,AFTER_INSERT, AFTER_UPDATE, AFTER_DELETE und AFTER_UNDELETE. Wenn Sie Ihre Programmierlogik auf der Basis verschiedener AusIösertypen variieren, sollten Sie überlegen, die switch-Anweisung mit verschiedenen Permutationen eindeutiger Enumerationszustände bei der Auslöserausführung zu verwenden.

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.

Hinweis

Hinweis

Die Klasse "EmailManager" ist im Klassenbeispiel des Abschnitts "Erste Schritte mit Apex" enthalten. Sie müssen die Klasse "EmailManager" in Ihrer Organisation speichern und die Methode "sendMail()" in eine statische Methode ändern, bevor Sie diesen Auslöser speichern.

  1. Klicken Sie in der Developer Console auf File (Datei) | New (Neu) | Apex Trigger (Apex-Auslöser).
  2. Geben Sie als Auslösernamen ExampleTrigger ein und wählen Sie dann Contact für das sObject aus. Klicken Sie auf Submit (Senden).
  3. 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
        }
    }
  4. Speichern Sie mit Strg+S.
  5. Um den Auslöser zu testen, erstellen Sie einen Kontakt.
    1. Klicken Sie auf Debug | Open Execute Anonymous Window (Debuggen | Fenster für die anonyme Ausführung öffnen).
    2. 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;
  6. Ü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 (DEBUG|E-Mail erfolgreich gesendet)
  7. 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 Acount-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.

  1. 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ösernamen AddRelatedRecord 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;
        }
    }
  2. Um den Auslöser zu testen, erstellen Sie auf der Salesforce-Benutzeroberfläche einen Account und nennen Sie ihn Apples & Oranges.
  3. Suchen Sie in der Themenliste "Opportunities" auf der Seite des Accounts nach der neuen Opportunity. Der Auslöser hat diese Opportunity automatisch hinzugefügt!

Über die Grundlagen hinaus

Der Auslöser, den Sie hinzugefügt haben, durchläuft alle Datensätze, die Teil des Auslöserkontexts sind, d. h., die For-Schleife durchläuft "Trigger.New". Die Schleife in diesem Auslöser könnte jedoch effizienter sein. Wir benötigen nicht wirklich Zugriff auf jeden Account in diesem Auslöserkontext, sondern nur auf einen Teil davon, nämlich die Accounts ohne Opportunities. Im nächsten Abschnitt wird veranschaulicht, wie dieser Auslöser effizienter gestaltet werden kann. Im Abschnitt "Designmuster für Massenauslöser" wird gezeigt, wie die SOQL-Abfrage geändert wird, sodass nur die Accounts ohne Opportunities abgerufen werden. Anschließend lernen Sie, wie Sie nur diese Datensätze durchlaufen.

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.

  1. 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.');
        }
        
    }
  2. Wechseln Sie auf der Salesforce-Benutzeroberfläche zur Seite des Accounts Apples & Oranges und klicken Sie auf Löschen.
  3. 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).

  4. Deaktivieren Sie den Auslöser "AccountDeletion". Wenn Sie diesen Auslöser im aktiven Status belassen, können Sie Ihre Abfragen nicht überprüfen.
    1. Suchen Sie im Setup nach Apex Triggers (Apex-Auslöser).
    2. Klicken Sie auf der Seite "Apex Triggers (Apex-Auslöser)" neben dem Auslöser "AccountDeletion" auf Edit (Bearbeiten).
    3. Deaktivieren Sie die Option Is Active (Ist aktiv).
    4. Klicken Sie auf Speichern.

Über die Grundlagen hinaus

Durch Aufrufen von "addError()" in einem Auslöser werden alle Vorgänge per Rollback zurückgesetzt, es sei denn, ein DML-Massenvorgang wird mit Teilerfolg aufgerufen.

  • Wenn der Ursprung des Auslösers eine DML-Anweisung in Apex ist, führt jeder Fehler dazu, dass der gesamte Vorgang zurückgesetzt wird. Die Laufzeit-Engine verarbeitet jedoch weiterhin jeden Datensatz im Vorgang, um eine ausführliche Fehlerliste zusammenzustellen.
  • Wenn der Ursprung des Auslösers ein DML-Massenaufruf in der Lightning-Plattform-API ist, stellt die Laufzeit-Engine die fehlerhaften Datensätze beiseite. Anschließend versucht die Laufzeit-Engine, eine teilweise Speicherung der Datensätze vorzunehmen, die keine Fehler erzeugt haben.

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.

Hinweis

Hinweis

In dem Beispiel wird zur Veranschaulichung ein hypothetischer Endpunkt-URL verwendet. Sie können dieses Beispiel nur ausführen, wenn Sie den Endpunkt in einen gültigen URL ändern und für Ihren Endpunkt einen Remote-Standort in Salesforce hinzufügen.

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

Lernen Sie weiter kostenlos!
Registrieren Sie sich für einen Account, um fortzufahren.
Was ist für Sie drin?
  • Holen Sie sich personalisierte Empfehlungen für Ihre Karriereplanung
  • Erproben Sie Ihre Fähigkeiten mithilfe praktischer Aufgaben und Quizze
  • Verfolgen Sie Ihre Fortschritte nach und teilen Sie sie mit Arbeitgebern
  • Nutzen Sie Mentoren und Karrierechancen