Dynamically querying fields by passing object name dynamically

 First you need to know why this topic, as a developer I got tension when I developing an application.In controller mostly we use fields API while querying the fields from

objects till now I used the SOQl query [select Name, CreatedDate, pincode__c from Object] like this it will work fine.

But the problem here it is, if I want to change the properties of the custom fields or delete the custom fields Salesforce will through the custom field validation error like the field is reference this apex class and page etc mostly classes.

And if you added any fields on the object based on this fields if you want to do any operation on the controller then you need to add these fields API name into the query.
       
It is very headache work.To avoid this if we use dynamic query by passing object name dynamically, then we no need to worry about above issues.

Demo:

To give the demo I taken one simple example .
           
    1.I created one Book object.
           
    2.Right it contains only four custom fields, one field is mater relation with library and standard fields.
                   
    3.I am displaying the list of records and all fields on visualforce page as a table.

Visualforce page:

<apex:page showHeader="false" controller="DemoQueryFields">
   <apex:form id="frm">
       <apex:pageBlock title="Book List">
        <apex:pageBlockSection >
        <apex:pageBlockTable id="table" value="{!bookList}" var="book" style="width: 1280px;">
            <apex:column headerValue="Book Name">
                  <apex:outputField value="{!book.Name}"/>
            </apex:column>

             <apex:column headerValue="Author">
                    <apex:outputField value="{!book.Author__c}"/>
            </apex:column>

             <apex:column headerValue="Price">
                     <apex:outputField value="{!book.Price__c}"/>
            </apex:column>

             <apex:column headerValue="Library Name">
               <apex:outputLink target="_top" title="{!book.Library__r.Name}" 
                             value="/{!book.Library__c}">{!book.Library__r.Name}
            </apex:OutputLink>
            </apex:column>

         </apex:pageBlockTable>
         </apex:pageBlockSection>

        <apex:pageBlockButtons location="bottom">
            <apex:commandButton value="Back" action="{!addYourOwnAction}" rerender="frm"/>
        </apex:pageBlockButtons>

     </apex:pageBlock>
 </apex:form>
</apex:page>

 

Controller :

public with sharing class DemoQueryFields {
   
    //Variable Declaration-start
        public List<Book__c> bookList    {get;set;}
    //End
   
    //constructor
    public DemoQueryFields(){
       
      string fieldsAPIname = '';
      fieldsAPIname=ObjectFields('Book__c');
      
     /* we are passing the object API name to our custom method to get all the fields API Name*/
           
     String qry = 'Select Library__r.Name, '+fieldsAPIname+' from Book__c ';
     
     /*if you  see the above line its look very simple but its important one .And If you want any related
        object fields through relationship the you need to use like 'Library__r.Name' and if you want any
        conditions you can add it */

        bookList= Database.query(qry);
    }
   
   
    //Getting the fields from object
     public String ObjectFields(String ObjectNameval){
        string fieldsVal = '';
        SObjectType objToken = Schema.getGlobalDescribe().get(ObjectNameval);

        /* For this method we are getting the object API name both for standard object and cutom object
               getGlobalDescribe()-method returns the map of all sobject names(Keyset) with sobject
               token(value paires)
                e.g. Assume if your org contains one custom object called Book(Book__c) with all standard
                       object.Then the result of getGlobalDescribe method will be 
                        Map<Book__c,Book object tokens> like with all standard objects.
          getGlobalDescribe().get(ObjectNameval)-As we know we get value pairs from map by using
          get() method.This will return an Book__c object type this we collected in SObjectType variable
          token. So the object token value is Book__c*/

          DescribeSObjectResult objDef = objToken.getDescribe();
           
          /*getDescribe()-An object(Book) that contains all the describe properties for the sobject(Book)
             or fields. 
                        e.g. getKeyPrefix, getLabel, getLabelPlural, getLocalName etc.
           */
               
           Map<String, SObjectField> fields = objDef.fields.getMap();
              
           /*Map of the fields value. e.g. {name=Name,author__c=Author__c,etc}*/
                    
           Set<String> fieldSet = fields.keySet();
                
           /*Collecting the fields API  into set variable fieldset.*/
                 
           for(string f : fieldSet){
                fieldsVal += f +',';
           }   
           if(fieldsVal.endsWith(','))
           fieldsVal= fieldsVal.substring(0,fieldsVal.length()-1);
                    
           /*Adding , string after every fields api name.
                e.g  fieldsVal-variable will contains the value like -Name,pincode__c,CreateDate etc.
           */
           return fieldsVal;
        }
}

 

Output Image:

 Fig.1.1 Displaying Records

        
Now what ever you are adding fields on the object that will also added to this query,You can change any fiels properties whenever without any error only thing is if you want to display on page then only you need to write or add fields on the page.I think this post will help lot while developing.

Winter'13:       
         
In winter'13 release Salesforce introduced new methods to get the Object API with have ID of any records under that object.

Method : ID.getSObjectTpye()
      
eg.  Book bookRecord=[Select Id,Name from Book__c limit 1];
               Id bookrcdID=bookRecord.id; 
               Schema.SObjectType token=bookrcdID.getSObjectType();
     
Now this 'token' variable will have the value of 'Book__c'. 

Rating: 
Average: 1 (1 vote)