fflib-apex-common
fflib-apex-common copied to clipboard
configureQueryFactory for lookup based on fieldset
In fflib_SObjectSelector
we have a useful method to add lookup fields from a selector instance to an existing queryFactory
public void configureQueryFactoryFields(fflib_QueryFactory queryFactory, String relationshipFieldPath)
{
// Add fields from selector prefixing the relationship path
for(SObjectField field : getSObjectFieldList())
queryFactory.selectField(relationshipFieldPath + '.' + field.getDescribe().getName());
// Automatically select the CurrencyIsoCode for MC orgs (unless the object is a known exception to the rule)
if(Userinfo.isMultiCurrencyOrganization() && CURRENCY_ISO_CODE_ENABLED)
queryFactory.selectField(relationshipFieldPath+'.CurrencyIsoCode');
}
Use case from Force.com Enterprise Architecture second edition p 228 is
fflib_QueryFactory contestantFactory = newQueryFactory();
new DriversSelector()
.configureQueryFactoryFields(contestantFactory,'Driver__r');
return Database.query(contestantFactory.setCondition(...).toSOQL());
Seems like it would be useful (at least to me) to be able to configure the parent lookup fields via a fieldset as in:
fflib_QueryFactory contestantFactory = newQueryFactory();
new DriversSelector()
.configureQueryFactoryFields(contestantFactory,
'Driver__r',SObjectType.Driver.fieldsets.MyFieldSet);
return Database.query(contestantFactory.setCondition(...).toSOQL());
where the code for this in fflib_SObjectSelector would be something like this:
/**
* adds a specific fieldset to a given relationship (lookup) as a prefix
*/
public void configureQueryFactoryFields(fflib_QueryFactory queryFactory, String relationshipFieldPath, Schema.FieldSet fieldSet) {
// Add fields from fieldSet to queryFactory prepended by relationshipFieldPath
if (fieldSet.getSObjectType() != getSObjectType()) {
throw new fflib_QueryFactory.InvalidFieldSetException('Field set "' + fieldSet.getName() +
'" is not for SObjectType ' + getSObjectType());
}
for (Schema.FieldSetMember field: fieldSet.getFields()) {
queryFactory.selectField(relationshipFieldPath + '.' + field.getFieldPath());
}
if(Userinfo.isMultiCurrencyOrganization() && CURRENCY_ISO_CODE_ENABLED) {
queryFactory.selectField(relationshipFieldPath+'.CurrencyIsoCode');
}
}
Or is there some existing way to do this that I have overlooked (configuring a queryfactory's lookup fields via a fieldset of the parent Sobject?
@cropredyHelix I believe I am working on some functionality that would allow this, but with a slight variation from what you have suggested. Instead of passing the fieldset that you want included, I think it would make more sense to automatically include any fieldsets that are configured at the Selector layer, when overriding the getSObjectFieldSetList() method.
Do you think this would solve the ask, or do you still see benefit in passing a specific fieldset to add from?
@ctchipps so, the reason why I suggested a specific fieldset was for a use case where each SObject had two or more fieldsets defined, one of which was called ViewStateOptimized
. So, if a selector method on OpportunityLineItem was invoked in a use case where viewstate was trying to be minimized, the queryfactories for Opportunity
, PricebookEntry
, PricebookEntry.Product2, and
Opportunity.Accountcould all draw from their respective
ViewDtateOptimized` (by passing in as an arg) fieldset. Other use cases might choose different fieldsets from their lookup relationship's selector.
the override of getSobjectFieldSetList()
would possibly include more fieldsets than desired. I suppose one could subclass selectors just to specify different default fieldsets
I'm open to other ideas but the intent is to tell the queryFactory which fieldset to use when configuring a lookup relationship from the relationship's selector object.