4

In a controller for a visualforce page, that I have constructed, I have the following:

public User current_user {
    get {
        return [SELECT Name /*... other fields ...*/ FROM User WHERE Id =: UserInfo.getUserId()];
    } set;
}

This is one of my variables that is not necessarily causing an issue, however I cannot share the other variables due to security reasons. The variables are very similar in structure, however.

Here is an example method, called from the visualforce page:

public/pageReference void updateMethod() { 
    // ... arbitrary code that only modifies local variables ...
    OtherClass.someMethod(current_user.Name);
    // ... cont ...
}

I've noticed that my SOQL query count approaches the limit as updateMethod is called (regardless of the source, i.e. visualforce page / test method). My test methods have actually failed due to LimitExceptions because of this.

When variables with getter and setter methods are called, are the getters recompiled / reran? If so, how would I go about preventing re-querying but also allowing the variable to be edited by the visualforce page?

  • In the getter method of the property have a If condition to check if it was already queried and if not then query. – javanoob Dec 27 '16 at 15:00
7

Yes, they re-run every time. A common pattern to avoid it is called Lazy Loading:

public User current_user
{
    get
    {
        if (current_user == null)
        {
            current_user = [
                SELECT Name FROM User WHERE Id = :UserInfo.getUserId()
            ];
        }
        return current_user;
    }
    private set;
}

This approach has a couple benefits:

  • If you never call the getter, you never consume a query.
  • If you call the getter a million times, it will still only perform the assignment logic once.
|improve this answer|||||
  • Lazy-loading – battery.cord Dec 27 '16 at 15:01
  • What is the significance of the private set;? Just curious. – Konnor McDowell Dec 27 '16 at 15:04
  • 1
    It means the page (or other classes) can't set the value, only the controller itself. You should use private set for all your properties as a default, and only use public setters when you know you need them. – Adrian Larson Dec 27 '16 at 15:05
  • 1
    Its important to note that this pattern also requires the understanding that changes to the DB require you to NULL the property in order to get the updated values (or manually update the property). Ran into that before when I forgot something was lazy loaded and code did not function as expected because property was never updated. – Eric Dec 27 '16 at 16:55
  • 1
    i don't take enough advantage of it myself; learned this from some other SFSE post. You can even do this: String s; String t = 'abc'; if ((s = t) == 'abc') system.debug(Logginglevel.info,s); s will have value abc - but I find this style of coding hard to read – cropredy Dec 27 '16 at 20:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.