3

I have a static property:

public static Map<String,Opportunity> CEOpportunities{
    get{
            CEOpportunities = new Map<String,Opportunity>();
            For(Opportunity o : [select Id,Name,OwnerId from Opportunity where CE_Record_Opp__c=true and NAME like '%2015'])
            {
                CEOpportunities.put(o.OwnerId, o);
            } 

        return CEOpportunities;
    }
}

I'm accessing this Map from another class where I insert new opportunity records so the query result changes.

My question is: when does this soql query executed? Is it executed everytime I access the property? Or just the first time I access the property?

If it's only the first time I access the property, how can I get the updated query result?

UPDATE:

I'm sorry but I think I wanted to ask this case. Are the queries below executed every time I access the property? I'm not sure the property below is different from the property above. But the properties below contain only SOQL query

public static List<Account> TopAccounts{
    get{
          return [select Id,Name from Account limit 100];
    }
}

OR

public static Integer TopAccounts{
    get{
          return [select Count() from Account Where lastmodifieddate=TODAY];
    }
}
1
  • Is there any particular reason you don't just use a getCEOpportunities() method instead?
    – Mark Pond
    Aug 11, 2015 at 22:12

2 Answers 2

3

EDIT Just saw your last question - I think that if you want it to requery, you need to define a setter on your opportunities map and set it to null. This will force the opportunities to be requeried. Otherwise, you won't get that query run again until you get a new context (essentially until you refresh your page if you are using a VF page)

I was interested to see if this would be optimised by the VisualForce compiler and based on my simple test, I think it is.

If you have a static method called multiple times on a VF page, it looks like it's only called once by the page. Here is what I did:

Get method:

public static Map<Id,Account> accounts{
    get{
        if(accounts==null){
            accounts = new Map<Id,Account>([Select Id,Name From Account Limit 10]); 
            System.debug('Querying Accounts');
        }
        System.debug('Returning Accounts');
        return accounts;
    }
}

Three output texts referencing the static controller variable:

<apex:outputText>{!accounts}</apex:outputText>
<apex:outputText>{!accounts}</apex:outputText>
<apex:outputText>{!accounts}</apex:outputText>

Only one pair of debug statments:

USER_DEBUG|[9]|DEBUG|Querying Accounts
USER_DEBUG|[11]|DEBUG|Returning Accounts
5
  • It's called Lazy Loading.
    – Adrian Larson
    Aug 11, 2015 at 23:26
  • What I was trying to determine was if the get method was called by each outputText. Turns out it's only called once (which makes sense). I've been writing code professionally for 14 years, I know what Lazy Loading is. Aug 11, 2015 at 23:53
  • I'm not trying to insult you. I just found it surprising you didn't mention it considering OP didn't even use the pattern. I feel it adds to the conversation, but not enough to post a separate answer. It' not the sort of thing I would just edit into someone's post either...
    – Adrian Larson
    Aug 11, 2015 at 23:56
  • Haha - I didn't mention it because I'm sure OP was using it, but looking up at his code, it's not there. I must have added it to my answer assuming it was in the question. Hmm, I think I'm going senile. Aug 12, 2015 at 0:00
  • Haha giving them more credit than deserved! Your response makes a lot more sense now.
    – Adrian Larson
    Aug 12, 2015 at 0:02
1

Based on the OP's code, the SOQL is run each time the property is accessed.

As an example, if we run this in the console we use 4 SOQL queries and the second system.debug() reflects the change we made to the AccountNumber field.

public static Map<String,Account> mapAccounts {
    get {
        mapAccounts = new Map<String,Account>();
        for(Account objAccount : [SELECT Id, Name, AccountNumber FROM Account WHERE Name = 'test account'])
        {
            mapAccounts.put(objAccount.Name, objAccount);
        }
        return mapAccounts;
    }   
} 


List<Account> lstAccounts1 = [SELECT Id,AccountNumber FROM Account WHERE Name = 'test account'];
for(Account objAccount : lstAccounts1)
{
    objAccount.AccountNumber = '123';
}
update lstAccounts1;

system.debug('mapAccounts before: '+mapAccounts);

List<Account> lstAccounts2 = [SELECT Id,AccountNumber FROM Account WHERE Name = 'test account'];
for(Account objAccount : lstAccounts2)
{
    objAccount.AccountNumber = '999';
}
update lstAccounts2;

system.debug('mapAccounts after: '+mapAccounts); 

enter image description here enter image description here

Looping over the system.debug 100+ times will exceed the SOQL governor limits.

To avoid this behavior, use the lazy loading pattern that CaspNZ shared.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .