As Salesforce developers, we have mostly come across scenarios where we need to insert a Parent record and then insert a Child record by relating it to the parent record. In such cases, using an Apex parent-child utility class helps streamline this process. And for every use case, we just re-write the code for each of our use cases.
Well then, we are just not implementing a core OOPS concept here; Polymorphism. Re-usable multi-utility codes are essential in maintaining a stable Salesforce environment and which in turn ensures easy understanding of the coding patterns followed in the system.
Let’s get into how we create a reusable Apex parent-child utility class for our use case.
The secret ingredient to getting it done is simply by using the Schema class and handling the records as sObjects instead of specifically mentioning the API name of the sObjects we are trying to relate.
Let’s consider an example where we are trying to create an Opportunity along with a few Opportunity Products in the same transaction. And maybe add another scenario here, where we need to create a few records in our custom object relating it to our newly created Opportunity.
The following code is a reusable Apex parent-child utility class which can be used for relating any objects,
/********************************************************************************************************/
/*
*Created by : Adarsh S S
*Created Date : 21.08.2024
*Description : This utility class relates two different object records dynamically.
__________________________ Change Log ____________________________________
Modified by Case-Log Version Change Date Description
_________________________________________________________________________
*/
public class CreateRelationshipUtility {
public Map<String, List<Relation>> relationshipMap = new Map<String, List<Relation>> ();
/*
* Method Name : createRelationshipMapping
* Description : This method is used to relate the child and parent records.
* @param details (Relation) : Instance of the Wrapper Class.
* @return : None
* Created by : Adarsh S S
* Created Date : 21.08.2024
*/
public void createRelationshipMapping(Relation relationship) {
String childsObjectName = relationship.childRecord.getsObjectType().getDescribe().getName();
String parentsObjectName = relationship.parentRecord.getsObjectType().getDescribe().getName();
String key = childsObjectName + '~' + parentsObjectName;
List<Relation> relatedRecords = new List<Relation> ();
if(!relationshipMap.containsKey(key)) {
relatedRecords = new List<Relation> ();
relationshipMap.put(key, relatedRecords);
}
relationshipMap.get(key).add(relationship);
}
/*
* Method Name : registerRelationship
* Description : This method is used to registed the relationship bewteen the child and parent records.
* @param details (String, String) : sObjectName of the Child Record, sObjectName of the Parent Record
* @return : None
* Created by : Adarsh S S
* Created Date : 21.08.2024
*/
public void registerRelationship(String childsObjectName, String parentsObjectName) {
String key = childsObjectName + '~' + parentsObjectName;
for(Relation relateRecord : relationshipMap.get(key)) {
//The relationship field is filled here
relateRecord.childRecord.put(relateRecord.relationField, relateRecord.parentRecord.Id);
}
}
public class Relation {
public sObject childRecord;
public sObject parentRecord;
public Schema.sObjectField relationField;
}
}
/********************************************************************************************************/
The utility class is now utilized for our example as follows,
/********************************************************************************************************/
/*
*Created by : Adarsh S S
*Created Date : 21.08.2024
*Description : This class is used to handle Opportunity records and its implementations.
___________________________________ Change Log _______________________________________
Modifiedby Case-Log Version Change Date Description
______________________________________________________________________________________
*/
public class OpportunityController {
/*
* Method Name : createOpportunity
* Description : This method is used to create Opportunity and related records.
* @param details : None
* @return : None
* Created by : Adarsh S S
* Created Date : 21.08.2024
*/
public void createOpportunity() {
CreateRelationshipUtility relationUtility = new CreateRelationshipUtility();
//Creating the parent record - Opportunity
Opportunity opp = new Opportunity(Name = 'Test Opportunity - New', StageName = 'Prospecting', CloseDate = Date.today().addDays(30));
List<OpportunityLineItem> oppLineItemsToInsertList = new List<OpportunityLineItem> ();
List<Safety_Measure__c> safetyMeasuresToInsertList = new List<Safety_Measure__c> ();
PricebookEntry pbEntry = [SELECT Id FROM PricebookEntry LIMIT 1];
for(Integer itr = 1; itr <= 5; itr++) {
//Creating the child records to Parent - OpportunityLineItem (Opportunity Products)
OpportunityLineItem item = new OpportunityLineItem(Quantity = itr, UnitPrice = itr * 5, PricebookEntryId = pbEntry.Id);
CreateRelationshipUtility.Relation relation = new CreateRelationshipUtility.Relation();
relation.childRecord = item;
relation.parentRecord = opp;
relation.relationField = OpportunityLineItem.OpportunityId;
relationUtility.createRelationshipMapping(relation);
oppLineItemsToInsertList.add(item);
}
for(Integer itr = 1; itr <= 5; itr++) {
//Creating the child records to Parent - Safety_Measure__c (A custom object related with Opportunity)
Safety_Measure__c measure = new Safety_Measure__c();
CreateRelationshipUtility.Relation relation = new CreateRelationshipUtility.Relation();
relation.childRecord = measure;
relation.parentRecord = opp;
relation.relationField = Safety_Measure__c.Opportunity__c;
relationUtility.createRelationshipMapping(relation);
safetyMeasuresToInsertList.add(measure);
}
insert opp;
//This method is used to link the OpportunityLineItem with the parent Opportunity record
relationUtility.registerRelationship('OpportunityLineItem', 'Opportunity');
insert oppLineItemsToInsertList;
//This method is used to link the Safety_Measure__c with the parent Opportunity record
relationUtility.registerRelationship('Safety_Measure__c', 'Opportunity');
insert safetyMeasuresToInsertList;
}
}
/********************************************************************************************************/
The createRelationshipMapping()
method of the Utility class creates the entity relationships before the DML of the records. And, the registerRelationship()
method of the Utility class dynamically creates the relationship field on the related record making it usable for relating any two objects (Standard and Custom sObjects). This highlights the flexibility of using an Apex parent-child utility class in enterprise-level Salesforce development.
And now we have a simple yet effective solution to relate two records without having to re-write the code — all thanks to a scalable Apex parent-child utility class approach.
👉 Want more tips like this? Browse our Salesforce blog for more Apex insights and reusable coding patterns.
Happy coding!