Intermediate 30 min read

Build a Bulk-Safe Trigger

By the end of this lesson, you'll be able to:

  • Write the thin trigger and handler skeleton for Leave_Request__c
  • Query every existing leave request for the affected employees, once
  • Explain why this query happens before, not during, the per-record validation loop

Prerequisites: "Design the Approval Workflow"

The thin trigger

trigger LeaveRequestTrigger on Leave_Request__c (before insert) {
    new LeaveRequestTriggerHandler().beforeInsert(Trigger.new);
}

Exactly Module 24's thin-trigger pattern — before insert, since overlap validation must block the save (Module 26's addError() lesson), which only works in a before context.

Fetching existing requests in one query

public void beforeInsert(List<Leave_Request__c> newRequests) {
    Set<String> employeeNames = new Set<String>();
    for (Leave_Request__c req : newRequests) {
        employeeNames.add(req.Employee_Name__c);
    }

    List<Leave_Request__c> existingRequests = [
        SELECT Id, Employee_Name__c, Start_Date__c, End_Date__c
        FROM Leave_Request__c
        WHERE Employee_Name__c IN :employeeNames AND Status__c != 'Rejected'
    ];
    // ... validation logic uses existingRequests (next lessons) ...
}

This is Module 16's Set deduplication (Module 25's bulkification instinct) combined into one upfront step: collect every affected employee's name once, then query all of their existing (non-rejected) requests in a single statement — before any per-record comparison starts.

Why the query happens before the validation loop

// WRONG — a query per new request, exactly the anti-pattern from Module 25
for (Leave_Request__c req : newRequests) {
    List<Leave_Request__c> existing = [SELECT Id FROM Leave_Request__c WHERE Employee_Name__c = :req.Employee_Name__c];
    // ...
}

Querying inside the per-record loop would be the SOQL-in-a-loop problem from Module 25, at exactly the scale this feature is most likely to face — a bulk data load inserting hundreds of leave requests at once. Fetching everything needed before the loop begins is what keeps the actual comparison loop (next lesson) free of any database operation at all.

Exercise

Given a List<Leave_Request__c> newRequests, write the Set<String> collection of unique Employee_Name__c values.

Show hint

Loop over newRequests, adding each Employee_Name__c to a Set<String>.

APEX

Build a Bulk-Safe Trigger Quiz

1. Why query existing requests before the per-record validation loop, rather than inside it?

Log in to submit the quiz and save your score.

My Notes

Log in to keep private notes on this lesson.

Questions about this lesson

No questions yet — be the first to ask.

Log in to ask a question about this lesson.

Summary

This lesson sets up the trigger, handler, and — critically — the single upfront query that fetches every existing leave request the validation logic will need, before any per-record checking begins.