As a Salesforce application developer, we always have a question like how many ways we can perform the DML operations when dealing with transactions. The answer is Salesforce provides two ways to perform the DML operations. Let us understand the difference between DML Statement vs. Database methods in Salesforce.
Simple DML Operation Use Case
Inserting Accounts into the Database without checking for exceptions
List<Account> accounts = new List<Account>();
accounts.add(new Account(Name = 'Test Account'));
accounts.add(new Account(Name = 'Test Account'));
System.debug('Account List Size : ' +accounts.size());
insert accounts;
Using this approach, we don’t know why the transaction is failing here and the above example is quite simple transaction to understand and we will know why it will fail but if you think about the bulk transactions with more fields then it is hard to find. We need to spend our time going through the logs to determine why it failed, and it is time-consuming to overcome that we can use the try-catch block to handle the exceptions.
Catch exceptions while performing the DML operation
If you execute the below code snippet in the anonymous window, you will see the exception saying the Required field is missing. But what about the whole transaction will it fail the whole transaction even though the first record is good? To handle this type of situation, we can use the Database class methods.
List<Account> accounts = new List<Account>();
accounts.add(new Account(Name = 'Test Account'));
accounts.add(new Account(Name = 'Test Account'));
System.debug('Account List Size : ' +accounts.size());
try {
insert accounts;
} catch(DMLException e) {
throw new DMLException('Unable to Perform the DML Operation on Account : ' +e.getMessage());
}
DML does not support partial execution, which means if an error encountered in execution at that moment whole execution will rolled back and throw error messages. Use Try and Catch to handler exception and throw error messages well.
Using Database class for inserting the records
It supports partial execution, which means if an error encountered an apex records execution. Then It will not rolled back the full transactions.
Approach: All or nothing.
Syntax: Database.insert(List<sObject> object, Boolean);
The execution of below code will throw the exception without performing any DML operation even though the first record is good. But how can we process the good ones without failing them? It is possible by changing the Boolean value to false.
List<Account> accounts = new List<Account>();
accounts.add(new Account(Name = 'Test Account 11'));
accounts.add(new Account(Name = ''));
System.debug('Account List Size : ' +accounts.size());
try {
Database.SaveResult[] results = Database.insert(accounts, true);
} catch(DMLException e) {
throw new DMLException('Unable to Perform the DML Operation on Account : ' +e.getMessage());
}
If we execute the below code it will insert the first record and only the bad record is failed saying “required field missing”
List<Account> accounts = new List<Account>();
accounts.add(new Account(Name = 'Test Account 11'));
accounts.add(new Account(Name = ''));
System.debug('Account List Size : ' +accounts.size());
try {
Database.SaveResult[] results = Database.insert(accounts, false);
// iterate over the list of returned results
for(Database.SaveResult result : results) {
if(result.isSuccess()) {
System.debug('Successfully inserted Accounts : ' + result.getId());
} else {
// iterate over the failed ones
for(Database.Error error : result.getErrors()) {
System.debug('Error Status : ' + error.getStatusCode() + ' : ' + 'Error Fields : ' + error.getFields());
}
}
}
} catch(DMLException e) {
throw new DMLException('Unable to Perform the DML Operation on Account : ' +e.getMessage());
}
Let’s see the code. I used Database.saveResult to store the DML operation results, and later in the code, I iterate over the results to get the Success record IDs and handle the exceptions by using throw statements. If you notice again, I am using the try catch block to handle the exceptions is it necessary? I would like you to know the answer for that question. One possible case of using is if you want to re-attempt the DML operation again for the failed records and if they fail again due to some other reason then the catch block will help to handle the exceptions. Adding try catch block will not do any harm to the code.
Learn more about Database method.
Method of SaveResult
getErorrs() : returns the error objects with error code and description.
getId() : returns the Id of object that you are trying to insert or update.
isSuccess() : Boolean that is set to true for the successful ones and false for the failed ones.
Differences between Database Methods and DML Statements
DML Statements | Database Methods |
---|---|
Partial Update is not allowed. For example, if you have 100 records in list, then either all the records will be updated or none. | It allows Partial updates. You can specify the Parameter in Database method as true or false. If you specify false for this parameter and a record fails, the remainder of the DML operation can still succeed. |
You cannot get the list of success and failed records. | You can get the list of success and failed records as we have seen in the example. |
ConvertLead Not Available in DML Statements | ConvertLead Operation is only available in Database class. |
Example − insert accounts; | Example − Database.insert(listName, False), where false indicates that a partial update is allowed. |
DML Statement Video
The “Differences between Database Methods and DML Statements” “Partial update is allowed. You can specify the Parameter in Database method as true or false, true to allow the partial update and false for not allowing the same.” is wrong false is to allow partial success of DML.
Yes, exactly you are right. I was just confused when I was trying to execute the example code which was working opposite to what they explained.
“Example − Database.insert(listName, False), where false indicate that partial update is not allowed.”
In the above example *’False will allow Partial update’.
“Database.insert(listName, False), where false indicates that a partial update is allowed.”
It’s correct that when it was set to FALSE, it will allow the partial update or it means that it will not trigger the rollback even if one record fails. When it was TRUE and one record failed it won’t update all the records.