Skip to content

Add Identity Map design pattern #191

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion fflib/src/classes/fflib_Application.cls
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,21 @@ public class fflib_Application
* @exception Is thrown if the record Ids are not all the same or the SObjectType is not registered
**/
public List<SObject> selectById(Set<Id> recordIds)
{
return selectById(recordIds, null);
}

/**
* Helper method to fetch the given SObject records from the registered records in the unitOfWork and
* query any non-registered records
* Internally creates an instance of the registered Selector and calls its
* selectSObjectById method
*
* @param recordIds The SObject record Ids, must be all the same SObjectType
* @param unitOfWork Instance of fflib_ISObjectUnitOfWork for fetching registered records
* @exception Is thrown if the record Ids are not all the same or the SObjectType is not registered
**/
public List<SObject> selectById(Set<Id> recordIds, fflib_ISObjectUnitOfWork unitOfWork)
{
// No point creating an empty Domain class, nor can we determine the SObjectType anyway
if(recordIds==null || recordIds.size()==0)
Expand All @@ -199,7 +214,15 @@ public class fflib_Application
throw new DeveloperException('Unable to determine SObjectType, Set contains Id\'s from different SObject types');

// Construct Selector class and query by Id for the records
return newInstance(domainSObjectType).selectSObjectsById(recordIds);
fflib_ISObjectSelector selector = newInstance(domainSObjectType);
if (null == unitOfWork)
{
return selector.selectSObjectsById(recordIds);
}
else
{
return selector.selectSObjectsById(recordIds, unitOfWork);
}
}

/**
Expand Down
5 changes: 5 additions & 0 deletions fflib/src/classes/fflib_ISObjectSelector.cls
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,9 @@ public interface fflib_ISObjectSelector
* Selects by Id records using the fields defined by the Selector configuration
**/
List<SObject> selectSObjectsById(Set<Id> idSet);

/**
* Selects by Id records using UnitOfWork and queries non-registered records
**/
List<SObject> selectSObjectsById(Set<Id> idSet, fflib_ISObjectUnitOfWork unitOfWork);
}
136 changes: 136 additions & 0 deletions fflib/src/classes/fflib_ISObjectUnitOfWork.cls
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,142 @@
**/
public interface fflib_ISObjectUnitOfWork
{
/**
* extractCleanIds
*
* @description Remove the registered clean record ids from the given set and returns them
*
* @param sObjectType A SObjectType reference for the clean registered records
* @param idSet The set of Ids where the clean record ids will be extracted from and returns the set without them
*
* @return A set of Ids which are stored as clean and member of the given idSet
*/
Set<Id> extractCleanIds(Schema.SObjectType sObjectType, Set<Id> idSet);
/**
* extractCleanIds
*
* @description Remove the registered clean record ids from the given set and returns them
*
* @param sObjectType The name of the registered clean SObjectType
* @param idSet The set of Ids where the clean record ids will be extracted from and returns the set without them
*
* @return A set of Ids which are stored as clean and member of the given idSet
*/
Set<Id> extractCleanIds(String sObjectType, Set<Id> idSet);
/**
* extractDeletedIds
*
* @description Remove the registered deleted record ids from the given set and returns them
*
* @param sObjectType A SObjectType reference for the deleted registered records
* @param idSet The set of Ids where the deleted record ids will be extracted from and returns the set without them
*
* @return A set of Ids which are stored as deleted and member of the given idSet
*/
Set<Id> extractDeletedIds(Schema.SObjectType sObjectType, Set<Id> idSet);
/**
* extractDeletedIds
*
* @description Remove the registered deleted record ids from the given set and returns them
*
* @param sObjectType The name of the registered deleted SObjectType
* @param idSet The set of Ids where the deleted record ids will be extracted from and returns the set without them
*
* @return A set of Ids which are stored as deleted and member of the given idSet
*/
Set<Id> extractDeletedIds(String sObjectType, Set<Id> idSet);
/**
* extractDirtyIds
*
* @description Remove the registered dirty record ids from the given set and returns them
*
* @param sObjectType A SObjectType reference for the dirty registered records
* @param idSet The set of Ids where the clean Ids will be extracted from and returns the set without them
*
* @return A set of Ids which are stored as dirty and member of the given idSet
*/
Set<Id> extractDirtyIds(Schema.SObjectType sObjectType, Set<Id> idSet);
/**
* extractDirtyIds
*
* @description Remove the registered dirty record ids from the given set and returns them
*
* @param sObjectType The name of the registered dirty SObjectType
* @param idSet The set of Ids where the dirty record ids will be extracted from and returns the set without them
*
* @return A set of Ids which are stored as dirty and member of the given idSet
*/
Set<Id> extractDirtyIds(String sObjectType, Set<Id> idSet);
/**
* getClean
*
* @description Get the clean registered records of the given id set
*
* @param sObjectType The name of the registered clean SObjectType
* @param idSet A set of Id's to search for
*
* @return A list of clean registered SObjects which are member of the given idSet
*/
List<SObject> getClean(String sObjectType, Set<Id> idSet);
/**
* getClean
*
* @description Get the clean registered records of the given id set
*
* @param sObjectType A SObjectType reference registered clean SObjectType
* @param idSet A set of Id's to search for
*
* @return A list of clean registered SObjects which are member of the given idSet
*/
List<SObject> getClean(Schema.SObjectType sObjectType, Set<Id> idSet);
/**
* getDeleted
*
* @description Get the deleted registered records of the given id set
*
* @param sObjectType The name of the registered deleted SObjectType
* @param idSet A set of Id's to search for
*/
List<SObject> getDeleted(String sObjectType, Set<Id> idSet);
/**
* getDeleted
*
* @description Get the deleted registered records of the given id set
*
* @param sObjectType A SObjectType reference registered deleted SObjectType
* @param idSet A set of Id's to search for
*/
List<SObject> getDeleted(Schema.SObjectType sObjectType, Set<Id> idSet);
/**
* getDirty
*
* @description Get the dirty registered records of the given id set
*
* @param sObjectType The name of the registered clean SObjectType
* @param idSet A set of Id's to search for
*/
List<SObject> getDirty(String sObjectType, Set<Id> idSet);
/**
* getDirty
*
* @description Get the dirty registered records of the given id set
*
* @param sObjectType A SObjectType reference registered dirty SObjectType
* @param idSet A set of Id's to search for
*/
List<SObject> getDirty(Schema.SObjectType sObjectType, Set<Id> idSet);
/**
* Register a just queried SObject that has not been changed yet
*
* @param record A queried SObject instance
**/
void registerClean(SObject record);
/**
* Register a list of just queried SObject that has not been changed yet
*
* @param records A list of queried SObject instances
**/
void registerClean(List<SObject> records);
/**
* Register a newly created SObject instance to be inserted when commitWork is called
*
Expand Down
47 changes: 46 additions & 1 deletion fflib/src/classes/fflib_SObjectSelector.cls
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,53 @@ public abstract with sharing class fflib_SObjectSelector
**/
public List<SObject> selectSObjectsById(Set<Id> idSet)
{
return Database.query(buildQuerySObjectById());
return Database.query(buildQuerySObjectById());
}


/**
* selectSObjectById
*
* @description Fetch the records from the registered records, if required query non-registered records from the database
*
* @param idSet A set of ids for records to either fetch from the clean registered or the database
* @param unitOfWork Instance of fflib_ISObjectUnitOfWork for retrieving the clean registered records
*
* @returns A list of SObject's
*/
public List<SObject> selectSObjectsById(Set<Id> idSet, fflib_ISObjectUnitOfWork unitOfWork)
{
Set<Id> nonRegisteredIds = new Set<Id>(idSet);
Set<Id> cleanIds = unitOfWork.extractCleanIds(getSObjectType(), nonRegisteredIds);

List<SObject> result = new List<SObject>();
if (!nonRegisteredIds.isEmpty())
{
result.addAll(selectSObjectsById(nonRegisteredIds));
}
if (!cleanIds.isEmpty())
{
result.addAll(unitOfWork.getClean(getSObjectType(), cleanIds));
}
return result;
}




/*public List<SObject> selectSObjectByIdField(SObjectField sObjectField, Set<Id> idSet)
{
if (hasUnitOfWork())
{
return selectSObjectsByIdWithIdentityMap(idSet);
}
else
{
return Database.query(

);
}
}*/

/**
* Performs a SOQL query,
Expand Down
Loading