Now that we know everything about objects, classes and methods, it’s time to get to know a special type of object: sObjects in Apex (sometimes also written as SObjects).
In Apex, there are three types of objects:
- Classes that we wrote
- sObjects
- Standard classes like String, Integer, HttpCallout, etc.
sObjects fall somewhere between standard and custom classes.
What is an sObject?
As you might have guessed, sObject is short for “Salesforce Object.” The term represents, well, standard Salesforce and custom objects (e.g. a Contact, Account, Opportunity or Training__c that you created in the Salesforce UI). Let’s see what an sObject looks like in code:
Contact contact1 = new Contact();
The Apex compiler doesn’t distinguish between the Person and Contact class. The only difference is that we defined Person, whereas Contact was defined for us by the Salesforce team.
Example #1 – Different sObjects
Opportunity opp = new Opportunity ();
Contact myContact = new Contact();
Lead newLead = new Lead();
Training__c apexTraining = new Training__c();
In these examples, we’re just creating sObjects without any data. Let’s put some data inside them.
sObject fields
Every standard and custom object in Salesforce has fields. You can use them in Apex just like variables from a class.
Contact contact1 = new Contact();
contact1.Email = 'alex@mail.com';
contact1.LastName = 'Alex Johnson';
contact1.FoodPreference__c = 'Vegan';
On the last line, that’s not a standard field on the contact object in Salesforce. It’s a custom field that I created. If we look at the field’s so-called API name, we can see that it’s “FoodPreference__c.” Keep in mind that we always use API names in Apex.
The same goes for custom objects! Here, you can see the custom object “Training__c” with the custom field “UniqueIdentifier__c”:
Training__c trainingObject = Training__c();
trainingObject.UniqueIdentifier__c = 'TR-19247';
Constructors in sObjects
One of the notable features of sObjects is their constructors. Instead of using dot notation, we can initialize the value of the fields directly in the constructor. Here’s an example:
Contact myContact = new Contact(LastName = 'Johnson', Email = 'alex@mail.com', FoodPreference__c = 'Vegan');
Let’s use the same code but with better alignment:
Contact myContact = new Contact(
LastName = 'Johnson',
Email = 'johnson@mail.com',
FoodPreference__c = 'Vegan'
);
On the left side, we can see the field’s API name on the contact object (LastName, Email, FoodPreference__c). And on the right side, we put the values. Of course, we can also put values into the variables and then use variables in the constructor:
String lastName = 'Johnson';
String email = 'alex@mail.com';
String foodPreference = 'Vegan';
Contact myContact = new Contact(
LastName = lastName,
Email = email,
FoodPreference__c = foodPreference
);
There’s no real difference between this notation and dot notation. Personally, I prefer normal dot notation because it’s similar to how we use classes.
Creating records with Apex
One of the fundamental operations in Salesforce is creating records. Therefore, I want to show you how to do so in Apex. If we navigate to Salesforce and create a Contact record without any fields, we’ll see an error that some required fields that we need to fill out. Which means, we need to fill out these fields:
Similarly, we must fill out these fields in Apex:
Contact myContact = new Contact();
myContact.LastName = 'Johnson';
Looking at this image, you can see that in the Salesforce UI, we have the “save” button. In Apex, the “save” button’s role is filled by the “insert” statement. The syntax is quite simple:
insert variableName;
Here’s a complete example of how to save a record in Apex:
Contact myContact = new Contact();
myContact.LastName = 'Johnson';
insert myContact;
Example #2 – Insert Opportunity
The opportunity object in Salesforce has three required fields. Therefore, we need to fill out all of them:
Opportunity opportunity = new Opportunity();
opportunity.Name = 'LLC Cloud Prism';
opportunity.StageName = 'Prospecting';
opportunity.CloseDate = System.today();
insert opportunity;
Output:
Explanation
- Line #1: Declare and initialize a variable, then put an empty object inside the variable with the Opportunity type.
- Line #2: Assign a value to the Name field on the opportunity object. The value of the field will be LLC Cloud Prism.
- Line #3: Assign a value to the StageName field on the opportunity object. The value of the field will be Prospecting.
- Line #4: Assign a value to the CloseDate field on the opportunity object. The value of the field will be the value that the today() method from the System class returns. It’s simply the current date.
- Line #5: Insert a new record into the database with all the completed fields. Return the Id of a newly inserted record and write this Id into our opportunity variable.
Example #3 – When is Id created?
In the Salesforce UI, the Id of a record is created when you save the record. In Apex, the Id is created once you insert the record. Look at the following example and try to answer this question: On which line will the record’s Id be printed out?
Contact myContact = new Contact();
System.debug('Line 2: ' + myContact);
myContact.LastName = 'Johnson';
System.debug('Line 5: ' + myContact);
insert myContact;
System.debug('Line 8: ' + myContact);
Output
Line 2: Contact:{}
Line 5: Contact:{LastName=Johnson}
Line 8: Contact:{LastName=Johnson, Id=0037Q00000dpZRQAZ}
Explanation
In the “insert” statement, Apex will identify that it needs to create a record in Salesforce as well as check if we have all the required fields and if all the validation rules are correct. If so, it will insert the record. After the insertion, Apex will write the Id of the record back into our variable. Starting from this line, we’ll be able to use this Id. If we don’t insert the record, we’ll never see the Id.
Example #4 – Inserting contact
Contact myContact = new Contact();
myContact.LastName = 'Johnson';
myContact.FirstName = 'Alex';
myContact.Email = 'alex.johnson@mail.com';
insert myContact;
Output
Relationships in sObjects
If you know how relationships work in Salesforce, relationships in sObjects are very similar in Apex! We create relationships in Apex with record Ids. Our goal for this part will be to insert an opportunity and account in the same transaction so that account is displayed on the opportunity record (like in the screenshot below):
If you look in the Salesforce Inspector on the opportunity from above, you’ll see that we’re only saving the account Id on the opportunity record. That’s the way Salesforce handles all relationships:
For Apex, this means that when we want to create a relationship, we must know the Id. How can we know the Id? We must first insert the account. The algorithm for our task would be as follows:
- Create an account variable.
- Fill out all the required fields (Name field).
- Insert the account variable.
- Create an opportunity variable.
- Fill out all the required fields on the opportunity variable (Name, StageName, CloseDate).
- Fill out the AccountId field with the Id from the account variable.
- Insert the opportunity variable.
Here’s how it looks in code:
Account accountVariable = new Account();
accountVariable.Name = 'Alex';
insert accountVariable; // Starting from this line we can use account id.
Opportunity opportunity = new Opportunity();
opportunity.Name = 'LLC Cloud Prism';
opportunity.StageName = 'Prospecting';
opportunity.CloseDate = System.today();
opportunity.AccountId = accountVariable.Id;
insert opportunity; // starting from this line we can use opportunity id as well.
Example #5 – Insert case with Contact and Account
Account myAccount = new Account();
myAccount.Name = 'Alex';
insert myAccount; // Starting from this line we can use account id.
Contact myContact = new Contact();
myContact.LastName = 'Johnson';
insert myContact; // starting from this line we can use contact id.
Case myCase = new Case();
myCase.AccountId = myAccount.Id;
myCase.ContactId = myContact.Id;
myCase.Reason = 'Feedback';
myCase.Description = 'Thanks for all the work!';
insert myCase;
The result will be a new case record with a relationship to the new account and a new contact record.
Notes on best practices
On the internet, you’ll often see people use abbreviations for the variable names on sObjects. For example:
Contact con = new Contact();
Opportunity o = new Opportunity();
Account acc = new Account();
It’s OK to use these variable names to test something out but not for the real org. A much better and cleaner approach would be using full sObject names for variables. Apex is smart enough to understand that it’s a variable name and not the type:
Contact contact = new Contact();
Opportunity opportunity = new Opportunity();
Account account = new Account();
For more info, check out the video Naming Things in Code.
Links
- Can someone please explain what is meant by sObject? (Stack Overflow)
- Naming Things in Code (YouTube).