Introduction
Imagine you are developing a new project from scratch. The project is getting bigger over time, due to increasingly complex logic, multiple Apex Triggers, Queueables and so on. At some point you are getting “LimitException: Too many SOQL queries: 101” exception. Crap, so what next? You have to go through all the classes to refactor the code and remove the redundant SOQL queries. After couple of hours you found only a few of them so sooner or later the problem comes back like a boomerang. Sounds like a nightmare? What if there is a better approach, like cache retrieved from Salesforce database records in Apex?
Solution
What you need is to create a DAO class for an object, with a static map for retrieved records, method to get records from SF database and logic to check if records are already retrieved. Still unconvinced? Let’s take a look at my approach:
public with sharing class AccountDao {
private static Map<Id, Account> cachedAccountsByIds = new Map<Id, Account>();
public static List<Account> findByIds(List<Id> ids) {
Boolean newAccountLoadNeeded = false;
for (Id accountId : ids) {
if (!cachedAccountsByIds.containsKey(accountId)) {
newAccountLoadNeeded = true;
break;
}
}
if (newAccountLoadNeeded) {
cachedAccountsByIds.putAll([
SELECT Name, Phone, BillingPostalCode
FROM Account
WHERE Id IN :ids
]);
}
return cachedAccountsByIds.values();
}
}
The first time the method will retrieve records from the Salesforce database and cache them into the static map. If you need these records again during the transaction, you won’t need additional SOQL query, because you will get it from the map. Clever, right?
Was it helpful? Check out our other great posts here.
Resources
- https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_collections_maps.htm
- https://developer.salesforce.com/wiki/apex_code_best_practices
The solution doesn’t seem to be coming up on mobile!