Apex - Guida rapida

Cos'è Apex?

Apex è un linguaggio proprietario sviluppato da Salesforce.com. Secondo la definizione ufficiale, Apex è un linguaggio di programmazione orientato agli oggetti fortemente tipizzato che consente agli sviluppatori di eseguire le istruzioni di controllo del flusso e delle transazioni sul server della piattaforma Force.com insieme alle chiamate all'API Force.com.

Ha una sintassi simile a Java e agisce come procedure memorizzate di database. Consente agli sviluppatori di aggiungere logica di business alla maggior parte degli eventi di sistema, inclusi clic sui pulsanti, aggiornamenti dei record correlati e Visualforcepages.Apexil codice può essere avviato dalle richieste del servizio Web e dai trigger sugli oggetti. Apex è incluso in Performance Edition, Unlimited Edition, Enterprise Edition e Developer Edition.

Caratteristiche di Apex come linguaggio

Parliamo ora delle caratteristiche di Apex come linguaggio:

Integrato

Apex ha il supporto integrato per le operazioni DML come INSERT, UPDATE, DELETE e anche la gestione delle eccezioni DML. Supporta la gestione delle query SOQL e SOSL inline che restituisce il set di record sObject. Studieremo in dettaglio sObject, SOQL, SOSL nei prossimi capitoli.

Java come sintassi e facile da usare

Apex è facile da usare in quanto utilizza la sintassi come Java. Ad esempio, dichiarazione di variabili, sintassi del ciclo e istruzioni condizionali.

Fortemente integrato con i dati

Apex è incentrato sui dati e progettato per eseguire più query e istruzioni DML insieme. Emette più istruzioni di transazione sul database.

Fortemente digitato

Apex è un linguaggio fortemente tipizzato. Utilizza il riferimento diretto agli oggetti dello schema come sObject e qualsiasi riferimento non valido fallisce rapidamente se viene eliminato o se è di tipo di dati errato.

Ambiente multi-tenant

Apex viene eseguito in un ambiente multi-tenant. Di conseguenza, il motore di runtime Apex è progettato per proteggersi da codice in fuga, impedendogli di monopolizzare le risorse condivise. Qualsiasi codice che viola i limiti non riesce con messaggi di errore di facile comprensione.

Aggiornamenti automatici

Apex viene aggiornato come parte delle versioni di Salesforce. Non dobbiamo aggiornarlo manualmente.

Test facile

Apex fornisce supporto integrato per la creazione e l'esecuzione di unit test, inclusi i risultati dei test che indicano quanto codice è coperto e quali parti del codice possono essere più efficienti.

Quando lo sviluppatore dovrebbe scegliere Apex?

Apex dovrebbe essere utilizzato quando non siamo in grado di implementare la complessa funzionalità aziendale utilizzando le funzionalità predefinite ed esistenti fuori dagli schemi. Di seguito sono riportati i casi in cui è necessario utilizzare apex sulla configurazione di Salesforce.

Applicazioni Apex

Possiamo usare Apex quando vogliamo:

  • Crea servizi Web integrando altri sistemi.

  • Crea servizi di posta elettronica per il blast e la configurazione della posta elettronica.

  • Esegui la convalida complessa su più oggetti contemporaneamente e anche l'implementazione della convalida personalizzata.

  • Crea processi aziendali complessi che non sono supportati dalle funzionalità o dai flussi del flusso di lavoro esistenti.

  • Crea logica transazionale personalizzata (logica che si verifica sull'intera transazione, non solo con un singolo record o oggetto) come l'utilizzo dei metodi Database per l'aggiornamento dei record.

  • Esegui una logica quando un record viene modificato o modifica il record dell'oggetto correlato quando si verifica un evento che ha causato l'attivazione del trigger.

Struttura di lavoro di Apex

Come mostrato nel diagramma seguente (Riferimento: documentazione per gli sviluppatori di Salesforce), Apex viene eseguito interamente su richiesta della piattaforma Force.com

Flusso di azioni

Ci sono due sequenze di azioni quando lo sviluppatore salva il codice e quando un utente finale esegue un'azione che richiama il codice Apex come mostrato di seguito:

Azione dello sviluppatore

Quando uno sviluppatore scrive e salva il codice Apex sulla piattaforma, il server delle applicazioni della piattaforma compila prima il codice in una serie di istruzioni che possono essere comprese dall'interprete di runtime Apex, quindi salva tali istruzioni come metadati.

Azione dell'utente finale

Quando un utente finale attiva l'esecuzione di Apex, facendo clic su un pulsante o accedendo a una pagina Visualforce, il server delle applicazioni della piattaforma recupera le istruzioni compilate dai metadati e le invia tramite l'interprete di runtime prima di restituire il risultato. L'utente finale non osserva differenze nel tempo di esecuzione rispetto alla richiesta della piattaforma applicativa standard.

Poiché Apex è il linguaggio proprietario di Salesforce.com, non supporta alcune funzionalità che fa un linguaggio di programmazione generale. Di seguito sono riportate alcune funzionalità che Apex non supporta:

  • Non può mostrare gli elementi nell'interfaccia utente.

  • Non è possibile modificare la funzionalità fornita dall'SFDC standard e inoltre non è possibile impedire l'esecuzione della funzionalità standard.

  • Inoltre, non è possibile creare più thread in quanto possiamo farlo in altre lingue.

Comprensione della sintassi Apex

Il codice Apex contiene in genere molte cose che potremmo avere familiarità con altri linguaggi di programmazione.

Dichiarazione di variabili

Come linguaggio fortemente tipizzato, devi dichiarare ogni variabile con tipo di dati in Apex. Come si vede nel codice sottostante (screenshot sotto), lstAcc è dichiarato con il tipo di dati come List of Accounts.

Query SOQL

Questo verrà utilizzato per recuperare i dati dal database di Salesforce. La query mostrata nella schermata seguente sta recuperando i dati dall'oggetto Account.

Istruzione Loop

Questa istruzione del ciclo viene utilizzata per iterare su un elenco o per iterare su una porzione di codice per un numero di volte specificato. Nel codice mostrato nello screenshot qui sotto, l'iterazione sarà uguale al numero di record che abbiamo.

Dichiarazione di controllo del flusso

L'istruzione If viene utilizzata per il controllo del flusso in questo codice. In base a determinate condizioni, si decide se avviare l'esecuzione o interrompere l'esecuzione di un particolare pezzo di codice. Ad esempio, nel codice mostrato di seguito, controlla se l'elenco è vuoto o contiene record.

Dichiarazione DML

Esegue le operazioni di inserimento, aggiornamento, upsert, cancellazione dei record sui record nel database. Ad esempio, il codice fornito di seguito aiuta ad aggiornare gli account con un nuovo valore di campo.

Di seguito è riportato un esempio di come apparirà uno snippet di codice Apex. Studieremo ulteriormente tutti questi concetti di programmazione Apex in questo tutorial.

In questo capitolo, capiremo l'ambiente per il nostro sviluppo di Salesforce Apex. Si presume che tu abbia già un'edizione Salesforce configurata per lo sviluppo Apex.

È possibile sviluppare il codice Apex nell'edizione Sandbox o Developer di Salesforce. Un'organizzazione Sandbox è una copia della tua organizzazione in cui puoi scrivere codice e testarlo senza correre il rischio di modificare i dati o disturbare la normale funzionalità. Secondo la pratica industriale standard, è necessario sviluppare il codice in Sandbox e quindi distribuirlo nell'ambiente di produzione.

Per questo tutorial, utilizzeremo l'edizione per sviluppatori di Salesforce. Nell'edizione per sviluppatori, non avrai la possibilità di creare un'organizzazione Sandbox. Le funzionalità Sandbox sono disponibili in altre edizioni di Salesforce.

Strumenti di sviluppo codice Apex

In tutte le edizioni, possiamo utilizzare uno dei seguenti tre strumenti per sviluppare il codice:

  • Console per gli sviluppatori Force.com
  • Force.com IDE
  • Editor di codice nell'interfaccia utente di Salesforce

Note − Utilizzeremo la Console per gli sviluppatori durante il nostro tutorial per l'esecuzione del codice poiché è semplice e facile da usare per l'apprendimento.

Console per gli sviluppatori Force.com

La Developer Console è un ambiente di sviluppo integrato con una raccolta di strumenti che è possibile utilizzare per creare, eseguire il debug e testare le applicazioni nella propria organizzazione Salesforce.

Segui questi passaggi per aprire la Console per gli sviluppatori:

Step 1 − Vai a Nome → Console per gli sviluppatori

Step 2 − Fare clic su "Console per gli sviluppatori" e verrà visualizzata una finestra come nella schermata seguente.

Di seguito sono riportate alcune operazioni che possono essere eseguite utilizzando la Developer Console.

  • Writing and compiling code −È possibile scrivere il codice utilizzando l'editor del codice sorgente. Quando salvi un trigger o una classe, il codice viene compilato automaticamente. Verranno segnalati eventuali errori di compilazione.

  • Debugging −È possibile scrivere il codice utilizzando l'editor del codice sorgente. Quando salvi un trigger o una classe, il codice viene compilato automaticamente. Verranno segnalati eventuali errori di compilazione.

  • Testing − È possibile visualizzare i log di debug e impostare punti di controllo che aiutano nel debug.

  • Checking performance −È possibile eseguire test di classi di test specifiche o di tutte le classi della propria organizzazione e visualizzare i risultati dei test. Inoltre, puoi ispezionare la copertura del codice.

  • SOQL queries − È possibile esaminare i registri di debug per individuare i colli di bottiglia delle prestazioni.

  • Color coding and autocomplete − L'editor del codice sorgente utilizza uno schema di colori per una più facile leggibilità degli elementi di codice e fornisce il completamento automatico per i nomi di classi e metodi.

Codice in esecuzione nella Console per gli sviluppatori

Tutti gli snippet di codice menzionati in questo tutorial devono essere eseguiti nella console per sviluppatori. Segui questi passaggi per eseguire i passaggi nella Developer Console.

Step 1 - Accedi a Salesforce.com utilizzando login.salesforce.com. Copia i frammenti di codice menzionati nel tutorial. Per ora, useremo il seguente codice di esempio.

String myString = 'MyString';
System.debug('Value of String Variable'+myString);

Step 2 - Per aprire la Console per gli sviluppatori, fare clic su Nome → Console per gli sviluppatori, quindi fare clic su Esegui anonimo come mostrato di seguito.

Step 3 - In questo passaggio, apparirà una finestra in cui potrai incollare il codice.

Step 4 - Quando clicchiamo su Execute, si apriranno i log di debug. Quando il registro viene visualizzato nella finestra come mostrato di seguito, fare clic sul record del registro.

Quindi digita "USER" nella finestra come mostrato di seguito e l'istruzione di output apparirà nella finestra di debug. Questa istruzione "USER" viene utilizzata per filtrare l'output.

Quindi, in pratica, seguirai tutti i passaggi sopra menzionati per eseguire qualsiasi frammento di codice in questo tutorial.

Esempio di sviluppo di applicazioni aziendali

Per il nostro tutorial, implementeremo l'applicazione CRM per un'azienda di apparecchiature e processi chimici. Questa azienda si occupa di fornitori e fornisce servizi. Elaboreremo piccoli frammenti di codice relativi a questo esempio durante il nostro tutorial per comprendere ogni concetto in dettaglio.

Per eseguire il codice in questo tutorial, sarà necessario creare due oggetti: gli oggetti Cliente e Fattura. Se sai già come creare questi oggetti in Salesforce, puoi saltare i passaggi indicati di seguito. Altrimenti, puoi seguire la guida passo passo di seguito.

Creazione dell'oggetto cliente

Per prima cosa configureremo l'oggetto Cliente.

Step 1- Vai a Setup e quindi cerca "Object" come mostrato di seguito. Quindi fare clic sul collegamento Oggetti come mostrato di seguito.

Step 2 - Una volta aperta la pagina dell'oggetto, fare clic sul pulsante "Create New Object'come mostrato di seguito.

Step 3- Dopo aver fatto clic sul pulsante, verrà visualizzata la nuova pagina di creazione dell'oggetto e quindi inserire tutti i dettagli dell'oggetto come inserito di seguito. Il nome dell'oggetto dovrebbe essere Cliente. Devi solo inserire le informazioni nel campo come mostrato nello screenshot qui sotto e mantenere le altre cose predefinite così com'è.

Immettere le informazioni e quindi fare clic sul pulsante "Salva" -

Seguendo i passaggi precedenti, abbiamo creato con successo l'oggetto Cliente.

Creazione dell'oggetto Campi personalizzati per cliente

Ora che abbiamo impostato il nostro oggetto Cliente, creeremo un campo "Attivo" e quindi potrai creare gli altri campi seguendo passaggi simili. Il nome e il nome API del campo verranno forniti nello screenshot.

Step 1- Creeremo un campo denominato "Attivo" di tipo di dati come Casella di controllo. Vai su Setup e fai clic su di esso.

Step 2 - Cerca "Oggetto" come mostrato di seguito e fai clic su di esso.

Step 3 - Fare clic sull'oggetto "Cliente".

Step 4 - Dopo aver fatto clic sul collegamento Oggetto cliente e visualizzata la pagina dei dettagli dell'oggetto, fare clic sul pulsante Nuovo.

Step 5 - Ora, seleziona il tipo di dati come Casella di controllo e fai clic su Avanti.

Step 6 - Immettere il nome del campo e l'etichetta come mostrato di seguito.

Step 7 - Fare clic su Visibile e quindi su Avanti.

Step 8 - Ora fai clic su "Salva".

Seguendo i passaggi precedenti, viene creato il nostro campo personalizzato "Attivo". Devi seguire tutti i passaggi precedenti per la creazione di campi personalizzati per i campi rimanenti. Questa è la vista finale dell'oggetto cliente una volta creati tutti i campi -

Creazione oggetto fattura

Step 1 - Vai a Configurazione e cerca "Oggetto", quindi fai clic sul collegamento Oggetti come mostrato di seguito.

Step 2 - Una volta aperta la pagina dell'oggetto, fare clic sul pulsante "Crea nuovo oggetto" come mostrato di seguito.

Step 3- Dopo aver fatto clic sul pulsante, la nuova pagina di creazione dell'oggetto apparirà come mostrato nello screenshot qui sotto. Devi inserire i dettagli qui. Il nome dell'oggetto dovrebbe essere Fattura. Questo è simile a come abbiamo creato l'oggetto Customer in precedenza in questo tutorial.

Step 4 - Immettere le informazioni come mostrato di seguito e quindi fare clic sul pulsante "Salva".

Seguendo questi passaggi, verrà creato il tuo oggetto Fattura.

Creazione dell'oggetto Campi personalizzati per fattura

Creeremo il campo Descrizione sull'oggetto Fattura come mostrato di seguito -

Step 1 - Vai su Setup e fai clic su di esso.

Step 2 - Cerca "Oggetto" come mostrato di seguito e fai clic su di esso.

Step 3 - Fare clic sull'oggetto "Fattura".

Quindi fare clic su "Nuovo".

Step 4 - Selezionare il tipo di dati come Area di testo e quindi fare clic sul pulsante Avanti.

Step 5 - Immettere le informazioni come indicato di seguito.

Step 6 - Fare clic su Visibile e quindi su Avanti.

Step 7 - Fare clic su Salva.

Allo stesso modo, puoi creare gli altri campi sull'oggetto Fattura.

In questo modo, abbiamo creato gli oggetti necessari per questo tutorial. Impareremo vari esempi nei capitoli successivi basati su questi oggetti.

Comprensione dei tipi di dati

Il linguaggio Apex è fortemente tipizzato, quindi ogni variabile in Apex verrà dichiarata con il tipo di dati specifico. Tutte le variabili apex vengono inizializzate inizialmente su null. È sempre consigliabile che uno sviluppatore si assicuri che i valori corretti siano assegnati alle variabili. In caso contrario, tali variabili, se utilizzate, genereranno eccezioni puntatore nullo o eccezioni non gestite.

Apex supporta i seguenti tipi di dati:

  • Primitivo (intero, doppio, lungo, data, data e ora, stringa, ID o booleano)

  • Collezioni (elenchi, set e mappe) (da trattare nel capitolo 6)

  • sObject

  • Enums

  • Classi, oggetti e interfacce (da trattare nei capitoli 11, 12 e 13)

In questo capitolo, esamineremo tutti i tipi di dati primitivi, gli oggetti e gli enum. Nei prossimi capitoli esamineremo le raccolte, le classi, gli oggetti e le interfacce poiché sono argomenti chiave da apprendere individualmente.

Tipi di dati primitivi

In questa sezione, discuteremo i tipi di dati primitivi supportati da Apex.

Numero intero

Un numero a 32 bit che non include alcun punto decimale. L'intervallo di valori per questo inizia da -2.147.483.648 e il valore massimo è fino a 2.147.483.647.

Example

Vogliamo dichiarare una variabile che immagazzinerà la quantità di barili che devono essere spediti all'acquirente dell'impianto di trasformazione chimica.

Integer barrelNumbers = 1000;
system.debug(' value of barrelNumbers variable: '+barrelNumbers);

Il System.debug() la funzione stampa il valore della variabile in modo che possiamo usarlo per eseguire il debug o per sapere quale valore contiene attualmente la variabile.

Incolla il codice sopra nella Console per gli sviluppatori e fai clic su Esegui. Una volta generati i log, il valore della variabile "barrelNumbers" verrà visualizzato come 1000.

Booleano

Questa variabile può essere vera, falsa o nulla. Molte volte, questo tipo di variabile può essere utilizzato come flag nella programmazione per identificare se la particolare condizione è impostata o meno.

Example

Se il valore booleano shippingDispatched deve essere impostato come true, può essere dichiarato come -

Boolean shipmentDispatched;
shipmentDispatched = true;
System.debug('Value of shipmentDispatched '+shipmentDispatched);

Data

Questo tipo di variabile indica una data. Questo può memorizzare solo la data e non l'ora. Per salvare la data insieme all'ora, dovremo memorizzarla nella variabile di DateTime.

Example

Considera il seguente esempio per capire come funziona la variabile Date.

//ShipmentDate can be stored when shipment is dispatched.
Date ShipmentDate = date.today();
System.debug('ShipmentDate '+ShipmentDate);

Lungo

Questo è un numero a 64 bit senza punto decimale. Viene utilizzato quando è necessario un intervallo di valori più ampio di quelli forniti da Integer.

Example

Se le entrate dell'azienda devono essere archiviate, utilizzeremo il tipo di dati come Long.

Long companyRevenue = 21474838973344648L;
system.debug('companyRevenue'+companyRevenue);

Oggetto

Possiamo fare riferimento a questo come a qualsiasi tipo di dati supportato in Apex. Ad esempio, la variabile Class può essere oggetto di quella classe e anche il tipo generico sObject è un oggetto e allo stesso modo anche il tipo di oggetto specifico come Account è un Object.

Example

Considera il seguente esempio per capire come funziona la variabile bject.

Account objAccount = new Account (Name = 'Test Chemical');
system.debug('Account value'+objAccount);

Note - Puoi anche creare un oggetto di classe predefinita, come indicato di seguito -

//Class Name: MyApexClass
MyApexClass classObj = new MyApexClass();

Questo è l'oggetto della classe che verrà utilizzato come variabile di classe.

Corda

La stringa è un insieme di caratteri all'interno di virgolette singole. Non ha alcun limite per il numero di caratteri. Qui, la dimensione dell'heap verrà utilizzata per determinare il numero di caratteri. Ciò pone un freno al monopolio delle risorse da parte del programma Apex e garantisce anche che non diventi troppo grande.

Example

String companyName = 'Abc International';
System.debug('Value companyName variable'+companyName);

Tempo

Questa variabile viene utilizzata per memorizzare l'ora particolare. Questa variabile dovrebbe sempre essere dichiarata con il metodo statico di sistema.

Blob

Il Blob è una raccolta di dati binari archiviati come oggetto. Questo verrà utilizzato quando vogliamo memorizzare l'allegato in Salesforce in una variabile. Questo tipo di dati converte gli allegati in un singolo oggetto. Se il blob deve essere convertito in una stringa, è possibile utilizzare i metodi toString e valueOf per lo stesso.

sObject

Questo è un tipo di dati speciale in Salesforce. È simile a una tabella in SQL e contiene campi simili alle colonne in SQL. Esistono due tipi di oggetti: Standard e Personalizzato.

Ad esempio, Account è un sObject standard e qualsiasi altro oggetto definito dall'utente (come l'oggetto Customer che abbiamo creato) è un sObject personalizzato.

Example

//Declaring an sObject variable of type Account
Account objAccount = new Account();

//Assignment of values to fields of sObjects
objAccount.Name = 'ABC Customer';
objAccount.Description = 'Test Account';
System.debug('objAccount variable value'+objAccount);

//Declaring an sObject for custom object APEX_Invoice_c
APEX_Customer_c objCustomer = new APEX_Customer_c();

//Assigning value to fields
objCustomer.APEX_Customer_Decscription_c = 'Test Customer';
System.debug('value objCustomer'+objCustomer);

Enum

Enum è un tipo di dati astratto che memorizza un valore di un insieme finito di identificatori specificati. È possibile utilizzare la parola chiave Enum per definire un Enum. Enum può essere utilizzato come qualsiasi altro tipo di dati in Salesforce.

Example

È possibile dichiarare i possibili nomi di Chemical Compound eseguendo il seguente codice:

//Declaring enum for Chemical Compounds
public enum Compounds {HCL, H2SO4, NACL, HG}
Compounds objC = Compounds.HCL;
System.debug('objC value: '+objC);

Java e Apex sono simili in molti modi. Anche la dichiarazione delle variabili in Java e Apex è la stessa cosa. Discuteremo alcuni esempi per capire come dichiarare le variabili locali.

String productName = 'HCL';
Integer i = 0;
Set<string> setOfProducts = new Set<string>();
Map<id, string> mapOfProductIdToName = new Map<id, string>();

Notare che a tutte le variabili viene assegnato il valore null.

Declaring Variables

Puoi dichiarare le variabili in Apex come String e Integer come segue:

String strName = 'My String';  //String variable declaration
Integer myInteger = 1;         //Integer variable declaration
Boolean mtBoolean = true;      //Boolean variable declaration

Apex variables are Case-Insensitive

Ciò significa che il codice fornito di seguito genererà un errore poiché la variabile 'm' è stata dichiarata due volte ed entrambe verranno trattate allo stesso modo.

Integer m = 100;
for (Integer i = 0; i<10; i++) {
   integer m = 1; //This statement will throw an error as m is being declared
   again
   System.debug('This code will throw error');
}

Scope of Variables

Una variabile Apex è valida dal punto in cui è dichiarata nel codice. Quindi non è consentito ridefinire nuovamente la stessa variabile e nel blocco di codice. Inoltre, se dichiari una variabile in un metodo, l'ambito della variabile sarà limitato solo a quel particolare metodo. Tuttavia, è possibile accedere alle variabili di classe in tutta la classe.

Example

//Declare variable Products
List<string> Products = new List<strings>();
Products.add('HCL');

//You cannot declare this variable in this code clock or sub code block again
//If you do so then it will throw the error as the previous variable in scope
//Below statement will throw error if declared in same code block
List<string> Products = new List<strings>();

La stringa in Apex, come in qualsiasi altro linguaggio di programmazione, è qualsiasi set di caratteri senza limite di caratteri.

Example

String companyName = 'Abc International';
System.debug('Value companyName variable'+companyName);

Metodi di stringa

La classe String in Salesforce dispone di molti metodi. In questo capitolo daremo uno sguardo ad alcuni dei metodi di stringa più importanti e usati di frequente.

contiene

Questo metodo restituirà true se la stringa data contiene la sottostringa menzionata.

Syntax

public Boolean contains(String substring)

Example

String myProductName1 = 'HCL';
String myProductName2 = 'NAHCL';
Boolean result = myProductName2.contains(myProductName1);
System.debug('O/p will be true as it contains the String and Output is:'+result);

equivale

Questo metodo restituirà true se la stringa data e la stringa passata nel metodo hanno la stessa sequenza binaria di caratteri e non sono null. Puoi anche confrontare l'ID del record SFDC utilizzando questo metodo. Questo metodo fa distinzione tra maiuscole e minuscole.

Syntax

public Boolean equals(Object string)

Example

String myString1 = 'MyString';
String myString2 = 'MyString';
Boolean result = myString2.equals(myString1);
System.debug('Value of Result will be true as they are same and Result is:'+result);

equalsIgnoreCase

Questo metodo restituirà true se stringtoCompare ha la stessa sequenza di caratteri della stringa data. Tuttavia, questo metodo non fa distinzione tra maiuscole e minuscole.

Syntax

public Boolean equalsIgnoreCase(String stringtoCompare)

Example

Il codice seguente restituirà true poiché i caratteri stringa e la sequenza sono gli stessi, ignorando la distinzione tra maiuscole e minuscole.

String myString1 = 'MySTRING';
String myString2 = 'MyString';
Boolean result = myString2.equalsIgnoreCase(myString1);
System.debug('Value of Result will be true as they are same and Result is:'+result);

rimuovere

Questo metodo rimuove la stringa fornita in stringToRemove dalla stringa data. Ciò è utile quando si desidera rimuovere alcuni caratteri specifici dalla stringa e non si è a conoscenza dell'indice esatto dei caratteri da rimuovere. Questo metodo distingue tra maiuscole e minuscole e non funzionerà se si verifica la stessa sequenza di caratteri ma le maiuscole sono diverse.

Syntax

public String remove(String stringToRemove)

Example

String myString1 = 'This Is MyString Example';
String stringToRemove = 'MyString';
String result = myString1.remove(stringToRemove);
System.debug('Value of Result will be 'This Is Example' as we have removed the MyString 
   and Result is :'+result);

removeEndIgnoreCase

Questo metodo rimuove la stringa fornita in stringToRemove dalla stringa data ma solo se si verifica alla fine. Questo metodo non fa distinzione tra maiuscole e minuscole.

Syntax

public String removeEndIgnoreCase(String stringToRemove)

Example

String myString1 = 'This Is MyString EXAMPLE';
String stringToRemove = 'Example';
String result = myString1.removeEndIgnoreCase(stringToRemove);
System.debug('Value of Result will be 'This Is MyString' as we have removed the 'Example'
   and Result is :'+result);

inizia con

Questo metodo restituirà true se la stringa data inizia con il prefisso fornito nel metodo.

Syntax

public Boolean startsWith(String prefix)

Example

String myString1 = 'This Is MyString EXAMPLE';
String prefix = 'This';
Boolean result = myString1.startsWith(prefix);
System.debug(' This will return true as our String starts with string 'This' and the 
   Result is :'+result);

Gli array in Apex sono sostanzialmente gli stessi degli elenchi in Apex. Non vi è alcuna distinzione logica tra gli array e gli elenchi poiché anche la struttura dei dati interni e i metodi sono gli stessi, ma la sintassi dell'array è poco tradizionale come Java.

Di seguito è riportata la rappresentazione di una matrice di prodotti:

Index 0 - HCL

Index 1 - H2SO4

Index 2 - NACL

Index 3 - H2O

Index 4 - N2

Index 5 - U296

Sintassi

<String> [] arrayOfProducts = new List<String>();

Esempio

Supponiamo di dover memorizzare il nome dei nostri prodotti: possiamo usare l'array in cui memorizzeremo i nomi dei prodotti come mostrato di seguito. È possibile accedere a un determinato prodotto specificando l'indice.

//Defining array
String [] arrayOfProducts = new List<String>();

//Adding elements in Array
arrayOfProducts.add('HCL');
arrayOfProducts.add('H2SO4');
arrayOfProducts.add('NACL');
arrayOfProducts.add('H2O');
arrayOfProducts.add('N2');
arrayOfProducts.add('U296');

for (Integer i = 0; i<arrayOfProducts.size(); i++) {
   //This loop will print all the elements in array
   system.debug('Values In Array: '+arrayOfProducts[i]);
}

Accesso all'elemento della matrice utilizzando index

È possibile accedere a qualsiasi elemento nell'array utilizzando l'indice come mostrato di seguito:

//Accessing the element in array
//We would access the element at Index 3
System.debug('Value at Index 3 is :'+arrayOfProducts[3]);

Come in qualsiasi altro linguaggio di programmazione, le costanti sono le variabili che non cambiano il loro valore una volta dichiarato o assegnato un valore.

In Apex, le costanti vengono utilizzate quando si desidera definire variabili che dovrebbero avere un valore costante durante l'esecuzione del programma. Le costanti Apex vengono dichiarate con la parola chiave "final".

Esempio

Considera un CustomerOperationClass classe e una variabile costante regularCustomerDiscount al suo interno -

public class CustomerOperationClass {
   static final Double regularCustomerDiscount = 0.1;
   static Double finalPrice = 0;
   
   public static Double provideDiscount (Integer price) {
      //calculate the discount
      finalPrice = price - price * regularCustomerDiscount;
      return finalPrice;
   }
}

Per vedere l'output della classe precedente, devi eseguire il seguente codice nella finestra anonima della Console per gli sviluppatori:

Double finalPrice = CustomerOperationClass.provideDiscount(100);
System.debug('finalPrice '+finalPrice);

Le strutture decisionali richiedono che il programmatore specifichi una o più condizioni che devono essere valutate o testate dal programma, insieme a una o più istruzioni da eseguire se la condizione è determinata essere vera e, facoltativamente, altre istruzioni da eseguire se condizione è determinata per essere falsa.

In questo capitolo, studieremo la struttura di base e avanzata del processo decisionale e delle dichiarazioni condizionali in Apex. Il processo decisionale è necessario per controllare il flusso di esecuzione quando determinate condizioni sono soddisfatte o meno. Di seguito è riportata la forma generale di una tipica struttura decisionale presente nella maggior parte dei linguaggi di programmazione

Sr.No. Dichiarazione e descrizione
1 istruzione if

Un'istruzione if è costituita da un'espressione booleana seguita da una o più istruzioni.

2 if ... else dichiarazione

Un'istruzione if può essere seguita da un opzionale else istruzione, che viene eseguita quando l'espressione booleana è falsa.

3 if ... elseif ... else dichiarazione

Un'istruzione if può essere seguita da un opzionale else if...else istruzione, che è molto utile per testare varie condizioni usando l'istruzione if ... else if.

4 istruzione if annidata

Puoi usarne uno if or else if dichiarazione dentro un'altra if or else if dichiarazione (i).

I cicli vengono utilizzati quando un particolare pezzo di codice deve essere ripetuto con il numero di iterazioni desiderato. Apex supporta lo standard tradizionale per loop e altri tipi avanzati di loop. In questo capitolo, discuteremo in dettaglio dei loop in Apex.

Un'istruzione loop ci consente di eseguire un'istruzione o un gruppo di istruzioni più volte e la seguente è la descrizione generale di un'istruzione loop nella maggior parte dei linguaggi di programmazione:

Le seguenti tabelle elencano i diversi loop che gestiscono i requisiti di loop nel linguaggio di programmazione Apex. Fare clic sui seguenti collegamenti per verificarne i dettagli.

Sr.No. Tipo e descrizione del loop
1 per loop

Questo ciclo esegue una serie di istruzioni per ogni elemento in una serie di record.

2 SOQL per loop

Esegue una sequenza di istruzioni direttamente sul set restituito o query SOQL.

3 Ciclo for simile a Java

Esegui una sequenza di istruzioni nella sintassi tradizionale simile a Java.

4 while loop

Ripete un'istruzione o un gruppo di istruzioni finché una determinata condizione è vera. Verifica la condizione prima di eseguire il corpo del ciclo.

5 fare ... mentre loop

Come un'istruzione while, tranne per il fatto che verifica la condizione alla fine del corpo del ciclo.

Le raccolte è un tipo di variabile che può memorizzare più record. Ad esempio, List può memorizzare più record di oggetti Account. Vediamo ora una panoramica dettagliata di tutti i tipi di raccolta.

Liste

L'elenco può contenere un numero qualsiasi di record di primitive, raccolte, oggetti, definiti dall'utente e incorporati nel tipo Apex. Questo è uno dei tipi più importanti di raccolta e inoltre ha alcuni metodi di sistema che sono stati adattati specificamente per essere utilizzati con List. L'indice della lista inizia sempre con 0. Questo è sinonimo dell'array in Java. Un elenco dovrebbe essere dichiarato con la parola chiave "Elenco".

Example

Di seguito è riportato l'elenco che contiene l'elenco di un tipo di dati primitivo (stringa), ovvero l'elenco delle città.

List<string> ListOfCities = new List<string>();
System.debug('Value Of ListOfCities'+ListOfCities);

La dichiarazione dei valori iniziali di list è facoltativa. Tuttavia, dichiareremo i valori iniziali qui. Di seguito è riportato un esempio che mostra lo stesso.

List<string> ListOfStates = new List<string> {'NY', 'LA', 'LV'};
System.debug('Value ListOfStates'+ListOfStates);

Elenco degli account (sObject)

List<account> AccountToDelete = new List<account> (); //This will be null
System.debug('Value AccountToDelete'+AccountToDelete);

Possiamo dichiarare anche l'elenco annidato. Può salire fino a cinque livelli. Questo è chiamato elenco multidimensionale.

Questa è la lista dell'insieme di numeri interi.

List<List<Set<Integer>>> myNestedList = new List<List<Set<Integer>>>();
System.debug('value myNestedList'+myNestedList);

L'elenco può contenere un numero qualsiasi di record, ma esiste una limitazione sulla dimensione dell'heap per evitare problemi di prestazioni e monopolizzare le risorse.

Metodi per gli elenchi

Sono disponibili metodi per gli elenchi che possono essere utilizzati durante la programmazione per ottenere alcune funzionalità come il calcolo della dimensione dell'elenco, l'aggiunta di un elemento, ecc.

Di seguito sono riportati alcuni metodi utilizzati più di frequente:

  • size()
  • add()
  • get()
  • clear()
  • set()

Il seguente esempio dimostra l'utilizzo di tutti questi metodi

// Initialize the List
List<string> ListOfStatesMethod = new List<string>();

// This statement would give null as output in Debug logs
System.debug('Value of List'+ ListOfStatesMethod);

// Add element to the list using add method
ListOfStatesMethod.add('New York');
ListOfStatesMethod.add('Ohio');

// This statement would give New York and Ohio as output in Debug logs
System.debug('Value of List with new States'+ ListOfStatesMethod);

// Get the element at the index 0
String StateAtFirstPosition = ListOfStatesMethod.get(0);

// This statement would give New York as output in Debug log
System.debug('Value of List at First Position'+ StateAtFirstPosition);

// set the element at 1 position
ListOfStatesMethod.set(0, 'LA');

// This statement would give output in Debug log
System.debug('Value of List with element set at First Position' + ListOfStatesMethod[0]);

// Remove all the elements in List
ListOfStatesMethod.clear();

// This statement would give output in Debug log
System.debug('Value of List'+ ListOfStatesMethod);

È possibile utilizzare anche la notazione dell'array per dichiarare l'elenco, come indicato di seguito, ma questa non è una pratica generale nella programmazione Apex -

String [] ListOfStates = new List<string>();

Imposta

Un Set è un tipo di raccolta che contiene un numero multiplo di record univoci non ordinati. Un set non può avere record duplicati. Come gli elenchi, i set possono essere nidificati.

Example

Definiremo l'insieme di prodotti che l'azienda sta vendendo.

Set<string> ProductSet = new Set<string>{'Phenol', 'Benzene', 'H2SO4'};
System.debug('Value of ProductSet'+ProductSet);

Metodi per insiemi

Set supporta metodi che possiamo utilizzare durante la programmazione come mostrato di seguito (stiamo estendendo l'esempio sopra) -

// Adds an element to the set
// Define set if not defined previously
Set<string> ProductSet = new Set<string>{'Phenol', 'Benzene', 'H2SO4'};
ProductSet.add('HCL');
System.debug('Set with New Value '+ProductSet);

// Removes an element from set
ProductSet.remove('HCL');
System.debug('Set with removed value '+ProductSet);

// Check whether set contains the particular element or not and returns true or false
ProductSet.contains('HCL');
System.debug('Value of Set with all values '+ProductSet);

Mappe

È una coppia di valori chiave che contiene la chiave univoca per ogni valore. Sia la chiave che il valore possono essere di qualsiasi tipo di dati.

Example

L'esempio seguente rappresenta la mappa del nome del prodotto con il codice del prodotto.

// Initialize the Map
Map<string, string> ProductCodeToProductName = new Map<string, string>
{'1000'=>'HCL', '1001'=>'H2SO4'};

// This statement would give as output as key value pair in Debug log
System.debug('value of ProductCodeToProductName'+ProductCodeToProductName);

Metodi per le mappe

Di seguito sono riportati alcuni esempi che dimostrano i metodi che possono essere utilizzati con Map -

// Define a new map
Map<string, string> ProductCodeToProductName = new Map<string, string>();

// Insert a new key-value pair in the map where '1002' is key and 'Acetone' is value
ProductCodeToProductName.put('1002', 'Acetone');

// Insert a new key-value pair in the map where '1003' is key and 'Ketone' is value
ProductCodeToProductName.put('1003', 'Ketone');

// Assert that the map contains a specified key and respective value
System.assert(ProductCodeToProductName.containsKey('1002'));
System.debug('If output is true then Map contains the key and output is:'
   + ProductCodeToProductName.containsKey('1002'));

// Retrieves a value, given a particular key
String value = ProductCodeToProductName.get('1002');
System.debug('Value at the Specified key using get function: '+value);

// Return a set that contains all of the keys in the map
Set SetOfKeys = ProductCodeToProductName.keySet();
System.debug('Value of Set with Keys '+SetOfKeys);

I valori della mappa potrebbero non essere ordinati e quindi non dovremmo fare affidamento sull'ordine in cui sono memorizzati i valori e cercare di accedere alla mappa sempre utilizzando le chiavi. Il valore della mappa può essere nullo. Mappare le chiavi quando dichiarato String fa distinzione tra maiuscole e minuscole; ad esempio, ABC e abc verranno considerate chiavi diverse e trattate come uniche.

Cos'è una classe?

Una classe è un modello o un progetto da cui vengono creati gli oggetti. Un oggetto è un'istanza di una classe. Questa è la definizione standard di Classe. Le classi Apex sono simili alle classi Java.

Per esempio, InvoiceProcessorclass descrive la classe che ha tutti i metodi e le azioni che possono essere eseguite sulla fattura. Se crei un'istanza di questa classe, rappresenterà la singola fattura attualmente nel contesto.

Creazione di classi

Puoi creare una classe in Apex dalla Console per gli sviluppatori, Force.com Eclipse IDE e anche dalla pagina dei dettagli della classe Apex.

Dalla Developer Console

Segui questi passaggi per creare una classe Apex dalla Console per gli sviluppatori:

Step 1 - Vai su Nome e fai clic su Console per gli sviluppatori.

Step 2 - Fare clic su File ⇒ Nuovo e quindi fare clic sulla classe Apex.

Da Force.com IDE

Segui questi passaggi per creare una classe dall'IDE Force.com:

Step 1 - Apri Force.com Eclipse IDE

Step 2 - Crea un nuovo progetto facendo clic su File ⇒ Nuovo ⇒ Classe Apex.

Step 3 - Fornire il nome per la classe e fare clic su OK.

Fatto ciò, verrà creata la nuova classe.

Dalla pagina dei dettagli della classe Apex

Segui questi passaggi per creare una classe dalla pagina dei dettagli della classe Apex:

Step 1 - Fare clic su Nome ⇒ Impostazioni.

Step 2- Cerca "Classe Apex" e fai clic sul link. Si aprirà la pagina dei dettagli della classe Apex.

Step 3 - Fare clic su "Nuovo", quindi fornire il nome della classe e quindi fare clic su Salva.

Struttura della classe Apex

Di seguito è riportata la struttura di esempio per la definizione della classe Apex.

Syntax

private | public | global
[virtual | abstract | with sharing | without sharing]
class ClassName [implements InterfaceNameList] [extends ClassName] {
   // Classs Body
}

Questa definizione utilizza una combinazione di modificatori di accesso, modalità di condivisione, nome della classe e corpo della classe. Esamineremo ulteriormente tutte queste opzioni.

Example

Di seguito è riportata una struttura di esempio per la definizione della classe Apex:

public class MySampleApexClass {       //Class definition and body
   public static Integer myValue = 0;  //Class Member variable
   public static String myString = ''; //Class Member variable
   
   public static Integer getCalculatedValue () {
   // Method definition and body
   // do some calculation
      myValue = myValue+10;
      return myValue;
   }
}

Modificatori di accesso

Privato

Se dichiari il modificatore di accesso come "Privato", questa classe sarà conosciuta solo localmente e non potrai accedere a questa classe al di fuori di quel particolare pezzo. Per impostazione predefinita, le classi hanno questo modificatore.

Pubblico

Se dichiari la classe come "Pubblica", ciò implica che questa classe è accessibile alla tua organizzazione e al tuo spazio dei nomi definito. Normalmente, la maggior parte delle classi Apex sono definite con questa parola chiave.

Globale

Se dichiari la classe come "globale", questa sarà accessibile da tutti i codici Apex indipendentemente dalla tua organizzazione. Se hai un metodo definito con la parola chiave del servizio web, devi dichiarare la classe contenitore con la parola chiave globale.

Modalità di condivisione

Parliamo ora delle diverse modalità di condivisione.

Con la condivisione

Questa è una caratteristica speciale delle classi Apex in Salesforce. Quando una classe viene specificata con la parola chiave "Con condivisione", ha le seguenti implicazioni: Quando la classe verrà eseguita, rispetterà le impostazioni di accesso dell'utente e l'autorizzazione del profilo. Supponiamo che l'azione dell'utente abbia attivato l'aggiornamento del record per 30 record, ma che l'utente abbia accesso solo a 20 record e 10 record non siano accessibili. Quindi, se la classe sta eseguendo l'azione per aggiornare i record, verranno aggiornati solo 20 record a cui l'utente ha accesso e gli altri 10 record non verranno aggiornati. Questa è anche chiamata modalità utente.

Senza condivisione

Anche se l'Utente non ha accesso a 10 record su 30, tutti i 30 record verranno aggiornati mentre la Classe è in esecuzione in modalità Sistema, cioè è stata definita con la parola chiave Senza Condivisione. Questa è chiamata modalità di sistema.

Virtuale

Se utilizzi la parola chiave "virtuale", indica che questa classe può essere estesa e che sono consentiti gli override. Se i metodi devono essere sovrascritti, le classi devono essere dichiarate con la parola chiave virtual.

Astratto

Se dichiari la classe come "astratta", conterrà solo la firma del metodo e non l'effettiva implementazione.

Variabili di classe

Syntax

[public | private | protected | global] [final] [static] data_type
variable_name [= value]

Nella sintassi sopra -

  • Il tipo di dati variabile e il nome della variabile sono obbligatori
  • I modificatori di accesso e il valore sono facoltativi.

Example

public static final Integer myvalue;

Metodi di classe

Esistono due modificatori per i metodi di classe in Apex: pubblico o protetto. Il tipo restituito è obbligatorio per il metodo e se il metodo non restituisce nulla, è necessario menzionare void come tipo restituito. Inoltre, per il metodo è richiesto anche Body.

Syntax

[public | private | protected | global]
[override]
[static]

return_data_type method_name (input parameters) {
   // Method body goes here
}

Spiegazione della sintassi

Quei parametri menzionati tra parentesi quadre sono facoltativi. Tuttavia, i seguenti componenti sono essenziali:

  • return_data_type
  • method_name

Modificatori di accesso per metodi di classe

Utilizzando i modificatori di accesso, è possibile specificare il livello di accesso per i metodi di classe. Ad esempio, il metodo Public sarà accessibile da qualsiasi punto della classe e al di fuori della classe. Il metodo privato sarà accessibile solo all'interno della classe. Global sarà accessibile da tutte le classi Apex e potrà essere esposto come metodo di servizio web accessibile da altre classi Apex.

Example

//Method definition and body
public static Integer getCalculatedValue () {
   
   //do some calculation
   myValue = myValue+10;
   return myValue;
}

Questo metodo ha un tipo restituito come Integer e non accetta parametri.

Un metodo può avere parametri come mostrato nell'esempio seguente:

// Method definition and body, this method takes parameter price which will then be used 
// in method.

public static Integer getCalculatedValueViaPrice (Decimal price) {
   // do some calculation
   myValue = myValue+price;
   return myValue;
}

Costruttori di classi

Un costruttore è un codice che viene richiamato quando un oggetto viene creato dal blueprint della classe. Ha lo stesso nome del nome della classe.

Non è necessario definire il costruttore per ogni classe, poiché per impostazione predefinita viene chiamato un costruttore senza argomenti. I costruttori sono utili per l'inizializzazione delle variabili o quando un processo deve essere eseguito al momento dell'inizializzazione della classe. Ad esempio, ti piacerebbe assegnare valori a determinate variabili Integer come 0 quando la classe viene chiamata.

Example

// Class definition and body
public class MySampleApexClass2 {
   public static Double myValue;   // Class Member variable
   public static String myString;  // Class Member variable

   public MySampleApexClass2 () {
      myValue = 100; //initialized variable when class is called
   }

   public static Double getCalculatedValue () { // Method definition and body
      // do some calculation
      myValue = myValue+10;
      return myValue;
   }

   public static Double getCalculatedValueViaPrice (Decimal price) {
      // Method definition and body
      // do some calculation
      myValue = myValue+price; // Final Price would be 100+100=200.00
      return myValue;
   }
}

Puoi anche chiamare il metodo della classe tramite il costruttore. Ciò può essere utile quando si programma Apex per visual force controller. Quando viene creato un oggetto classe, il costruttore viene chiamato come mostrato di seguito:

// Class and constructor has been instantiated
MySampleApexClass2 objClass = new MySampleApexClass2();
Double FinalPrice = MySampleApexClass2.getCalculatedValueViaPrice(100);
System.debug('FinalPrice: '+FinalPrice);

Costruttori di sovraccarico

I costruttori possono essere sovraccaricati, ovvero una classe può avere più di un costruttore definito con parametri differenti.

Example

public class MySampleApexClass3 {  // Class definition and body
   public static Double myValue;   // Class Member variable
   public static String myString;  // Class Member variable

   public MySampleApexClass3 () {
      myValue = 100; // initialized variable when class is called
      System.debug('myValue variable with no Overaloading'+myValue);
   }

   public MySampleApexClass3 (Integer newPrice) { // Overloaded constructor
      myValue = newPrice; // initialized variable when class is called
      System.debug('myValue variable with Overaloading'+myValue);
   }

      public static Double getCalculatedValue () { // Method definition and body
      // do some calculation
      myValue = myValue+10;
      return myValue;
   }

   public static Double getCalculatedValueViaPrice (Decimal price) {
      // Method definition and body
      // do some calculation
      myValue = myValue+price;
      return myValue;
   }
}

Puoi eseguire questa classe come l'abbiamo eseguita nell'esempio precedente.

// Developer Console Code
MySampleApexClass3 objClass = new MySampleApexClass3();
Double FinalPrice = MySampleApexClass3.getCalculatedValueViaPrice(100);
System.debug('FinalPrice: '+FinalPrice);

Un'istanza di classe si chiama Object. In termini di Salesforce, l'oggetto può essere di classe oppure è possibile creare anche un oggetto di sObject.

Creazione di oggetti dalla classe

Puoi creare un oggetto di classe come avresti potuto fare in Java o in un altro linguaggio di programmazione orientato agli oggetti.

Di seguito è riportato un esempio di classe chiamato MyClass -

// Sample Class Example
public class MyClass {
   Integer myInteger = 10;
   
   public void myMethod (Integer multiplier) {
      Integer multiplicationResult;
      multiplicationResult = multiplier*myInteger;
      System.debug('Multiplication is '+multiplicationResult);
   }
}

Questa è una classe istanza, cioè, per chiamare o accedere alle variabili o ai metodi di questa classe, è necessario creare un'istanza di questa classe e quindi è possibile eseguire tutte le operazioni.

// Object Creation
// Creating an object of class
MyClass objClass = new MyClass();

// Calling Class method using Class instance
objClass.myMethod(100);

creazione di un oggetto

Gli oggetti sono gli oggetti di Salesforce in cui vengono archiviati i dati. Ad esempio, Account, Contatto e così via sono oggetti personalizzati. È possibile creare istanze di oggetti di questi oggetti.

Di seguito è riportato un esempio di inizializzazione di sObject e mostra come è possibile accedere al campo di quel particolare oggetto utilizzando la notazione a punti e assegnare i valori ai campi.

// Execute the below code in Developer console by simply pasting it
// Standard Object Initialization for Account sObject
Account objAccount = new Account(); // Object initialization
objAccount.Name = 'Testr Account'; // Assigning the value to field Name of Account
objAccount.Description = 'Test Account';
insert objAccount; // Creating record using DML
System.debug('Records Has been created '+objAccount);

// Custom sObject initialization and assignment of values to field
APEX_Customer_c objCustomer = new APEX_Customer_c ();
objCustomer.Name = 'ABC Customer';
objCustomer.APEX_Customer_Decscription_c = 'Test Description';
insert objCustomer;
System.debug('Records Has been created '+objCustomer);

Inizializzazione statica

I metodi e le variabili statici vengono inizializzati solo una volta quando viene caricata una classe. Le variabili statiche non vengono trasmesse come parte dello stato di visualizzazione di una pagina Visualforce.

Di seguito è riportato un esempio di metodo statico e di variabile statica.

// Sample Class Example with Static Method
public class MyStaticClass {
   Static Integer myInteger = 10;
   
   public static void myMethod (Integer multiplier) {
      Integer multiplicationResult;
      multiplicationResult = multiplier * myInteger;
      System.debug('Multiplication is '+multiplicationResult);
   }
}

// Calling the Class Method using Class Name and not using the instance object
MyStaticClass.myMethod(100);

Static Variable Use

Le variabili statiche verranno istanziate solo una volta quando la classe viene caricata e questo fenomeno può essere utilizzato per evitare la ricorsione del trigger. Il valore della variabile statica sarà lo stesso nello stesso contesto di esecuzione e qualsiasi classe, trigger o codice in esecuzione può fare riferimento ad esso e prevenire la ricorsione.

Un'interfaccia è come una classe Apex in cui nessuno dei metodi è stato implementato. Contiene solo le firme del metodo, ma il corpo di ogni metodo è vuoto. Per utilizzare un'interfaccia, un'altra classe deve implementarla fornendo un corpo per tutti i metodi contenuti nell'interfaccia.

Le interfacce vengono utilizzate principalmente per fornire il livello di astrazione per il codice. Separano l'implementazione dalla dichiarazione del metodo.

Facciamo un esempio della nostra azienda chimica. Supponiamo di dover fornire lo sconto ai clienti Premium e Ordinary e gli sconti per entrambi saranno diversi.

Creeremo un'interfaccia chiamata DiscountProcessor.

// Interface
public interface DiscountProcessor {
   Double percentageDiscountTobeApplied(); // method signature only
}

// Premium Customer Class
public class PremiumCustomer implements DiscountProcessor {
   
   //Method Call
   public Double percentageDiscountTobeApplied () {
      
      // For Premium customer, discount should be 30%
      return 0.30;
   }
}

// Normal Customer Class
public class NormalCustomer implements DiscountProcessor {
   
   // Method Call
   public Double percentageDiscountTobeApplied () {
      
      // For Premium customer, discount should be 10%
      return 0.10;
   }
}

Quando si implementa l'interfaccia, è obbligatorio implementare il metodo di tale interfaccia. Se non si implementano i metodi dell'interfaccia, verrà generato un errore. È necessario utilizzare le interfacce quando si desidera rendere l'implementazione del metodo obbligatoria per lo sviluppatore.

Interfaccia Salesforce standard per Batch Apex

SFDC ha interfacce standard come Database.Batchable, Schedulable, ecc. Ad esempio, se si implementa l'interfaccia Database.Batchable, è necessario implementare i tre metodi definiti nell'interfaccia: Start, Execute e Finish.

Di seguito è riportato un esempio dell'interfaccia Database.Batchable fornita da Salesforce che invia messaggi di posta elettronica agli utenti con lo stato batch. Questa interfaccia ha 3 metodi, Start, Execute e Finish. Utilizzando questa interfaccia, possiamo implementare la funzionalità Batchable e fornisce anche la variabile BatchableContext che possiamo usare per ottenere maggiori informazioni sul Batch in esecuzione e per eseguire altre funzionalità.

global class CustomerProessingBatch implements Database.Batchable<sobject7>,
Schedulable {
   // Add here your email address
   global String [] email = new String[] {'[email protected]'};

   // Start Method
   global Database.Querylocator start (Database.BatchableContext BC) {
      
      // This is the Query which will determine the scope of Records and fetching the same
      return Database.getQueryLocator('Select id, Name, APEX_Customer_Status__c,
         APEX_Customer_Decscription__c From APEX_Customer__c WHERE createdDate = today
         && APEX_Active__c = true');
   }

   // Execute method
   global void execute (Database.BatchableContext BC, List<sobject> scope) {
      List<apex_customer__c> customerList = new List<apex_customer__c>();
      List<apex_customer__c> updtaedCustomerList = new List<apex_customer__c>();
      
      for (sObject objScope: scope) {
         // type casting from generic sOject to APEX_Customer__c
         APEX_Customer__c newObjScope = (APEX_Customer__c)objScope ;
         newObjScope.APEX_Customer_Decscription__c = 'Updated Via Batch Job';
         newObjScope.APEX_Customer_Status__c = 'Processed';
         
         // Add records to the List
         updtaedCustomerList.add(newObjScope);
      }

      // Check if List is empty or not
      if (updtaedCustomerList != null && updtaedCustomerList.size()>0) {
         
         // Update the Records
         Database.update(updtaedCustomerList); System.debug('List Size
            '+updtaedCustomerList.size());
      }
   }

   // Finish Method
   global void finish(Database.BatchableContext BC) {
      Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
      
      // get the job Id
      AsyncApexJob a = [Select a.TotalJobItems, a.Status, a.NumberOfErrors,
      a.JobType, a.JobItemsProcessed, a.ExtendedStatus, a.CreatedById,
      a.CompletedDate From AsyncApexJob a WHERE id = :BC.getJobId()];
      System.debug('$$$ Jobid is'+BC.getJobId());
      
      // below code will send an email to User about the status
      mail.setToAddresses(email);
     
      // Add here your email address
      mail.setReplyTo('[email protected]');
      mail.setSenderDisplayName('Apex Batch Processing Module');
      mail.setSubject('Batch Processing '+a.Status);
      mail.setPlainTextBody('The Batch Apex job processed
         '+a.TotalJobItems+'batches with '+a.NumberOfErrors+'failures'+'Job Item
         processed are'+a.JobItemsProcessed);
      Messaging.sendEmail(new Messaging.Singleemailmessage [] {mail});
   }

   // Scheduler Method to scedule the class
   global void execute(SchedulableContext sc) {
      CustomerProessingBatch conInstance = new CustomerProessingBatch();
      database.executebatch(conInstance,100);
   }
}

Per eseguire questa classe, devi eseguire il codice seguente nella Developer Console.

CustomerProessingBatch objBatch = new CustomerProessingBatch ();
Database.executeBatch(objBatch);

In questo capitolo, discuteremo come eseguire le diverse funzionalità di modifica del database in Salesforce. Ci sono due modi con cui possiamo eseguire le funzionalità.

Dichiarazioni DML

DML sono le azioni che vengono eseguite per eseguire operazioni di inserimento, aggiornamento, eliminazione, upsert, ripristino di record, unione di record o conversione di lead.

DML è una delle parti più importanti in Apex poiché quasi tutti i casi aziendali comportano modifiche e modifiche al database.

Metodi di database

Tutte le operazioni che è possibile eseguire utilizzando le istruzioni DML possono essere eseguite anche utilizzando i metodi di database. I metodi di database sono i metodi di sistema che è possibile utilizzare per eseguire operazioni DML. I metodi di database offrono maggiore flessibilità rispetto alle istruzioni DML.

In questo capitolo, esamineremo il primo approccio che utilizza le istruzioni DML. Analizzeremo i metodi del database in un capitolo successivo.

Dichiarazioni DML

Consideriamo ora di nuovo l'istanza dell'azienda fornitrice di prodotti chimici. I nostri record fattura hanno campi come Stato, Importo pagato, Importo rimanente, Prossima data di pagamento e Numero fattura. Le fatture che sono state create oggi e hanno il loro stato "In sospeso", dovrebbero essere aggiornate a "Pagate".

Inserisci operazione

L'operazione di inserimento viene utilizzata per creare nuovi record nel database. È possibile creare record di qualsiasi oggetto standard o personalizzato utilizzando l'istruzione Insert DML.

Example

Possiamo creare nuovi record nell'oggetto APEX_Invoice__c poiché ogni giorno vengono generate nuove fatture per i nuovi ordini dei clienti. Creeremo prima un record cliente, quindi possiamo creare un record fattura per quel nuovo record cliente.

// fetch the invoices created today, Note, you must have at least one invoice 
// created today

List<apex_invoice__c> invoiceList = [SELECT id, Name, APEX_Status__c,
   createdDate FROM APEX_Invoice__c WHERE createdDate = today];

// create List to hold the updated invoice records
List<apex_invoice__c> updatedInvoiceList = new List<apex_invoice__c>();
APEX_Customer__c objCust = new APEX_Customer__C();
objCust.Name = 'Test ABC';

//DML for Inserting the new Customer Records
insert objCust;
for (APEX_Invoice__c objInvoice: invoiceList) {
   if (objInvoice.APEX_Status__c == 'Pending') {
      objInvoice.APEX_Status__c = 'Paid';
      updatedInvoiceList.add(objInvoice);
   }
}

// DML Statement to update the invoice status
update updatedInvoiceList;

// Prints the value of updated invoices
System.debug('List has been updated and updated values are' + updatedInvoiceList);

// Inserting the New Records using insert DML statement
APEX_Invoice__c objNewInvoice = new APEX_Invoice__c();
objNewInvoice.APEX_Status__c = 'Pending';
objNewInvoice.APEX_Amount_Paid__c = 1000;
objNewInvoice.APEX_Customer__c = objCust.id;

// DML which is creating the new Invoice record which will be linked with newly
// created Customer record
insert objNewInvoice;
System.debug('New Invoice Id is '+objNewInvoice.id+' and the Invoice Number is'
   + objNewInvoice.Name);

Operazione di aggiornamento

L'operazione di aggiornamento consiste nell'eseguire gli aggiornamenti sui record esistenti. In questo esempio, aggiorneremo il campo Stato di un record Fattura esistente su "Pagato".

Example

// Update Statement Example for updating the invoice status. You have to create
and Invoice records before executing this code. This program is updating the
record which is at index 0th position of the List.

// First, fetch the invoice created today
List<apex_invoice__c> invoiceList = [SELECT id, Name, APEX_Status__c,
createdDate FROM APEX_Invoice__c];
List<apex_invoice__c> updatedInvoiceList = new List<apex_invoice__c>();

// Update the first record in the List
invoiceList[0].APEX_Status__c = 'Pending';
updatedInvoiceList.add(invoiceList[0]);

// DML Statement to update the invoice status
update updatedInvoiceList;

// Prints the value of updated invoices
System.debug('List has been updated and updated values of records are' 
   + updatedInvoiceList[0]);

Operazione Upsert

L'operazione Upsert viene utilizzata per eseguire un'operazione di aggiornamento e se i record da aggiornare non sono presenti nel database, crea anche nuovi record.

Example

Supponiamo che i record del cliente nell'oggetto Cliente debbano essere aggiornati. Aggiorneremo il record del cliente esistente se è già presente, altrimenti ne creeremo uno nuovo. Questo sarà basato sul valore del campo APEX_External_Id__c. Questo campo sarà il nostro campo per identificare se i record sono già presenti o meno.

Note - Prima di eseguire questo codice, creare un record nell'oggetto Cliente con il valore del campo Id esterno come "12341" e quindi eseguire il codice indicato di seguito -

// Example for upserting the Customer records
List<apex_customer__c> CustomerList = new List<apex_customer__c>();
for (Integer i = 0; i < 10; i++) {
   apex_customer__c objcust=new apex_customer__c(name = 'Test' +i,
   apex_external_id__c='1234' +i);
   customerlist.add(objcust);
} //Upserting the Customer Records

upsert CustomerList;

System.debug('Code iterated for 10 times and created 9 records as one record with 
   External Id 12341 is already present');

for (APEX_Customer_c objCustomer: CustomerList) {
   if (objCustomer.APEX_External_Id_c == '12341') {
      system.debug('The Record which is already present is '+objCustomer);
   }
}

Elimina operazione

È possibile eseguire l'operazione di eliminazione utilizzando Elimina DML.

Example

In questo caso, cancelleremo le fatture che sono state create a scopo di test, cioè quelle che contengono il nome come 'Test'.

Puoi eseguire questo snippet anche dalla Console per gli sviluppatori senza creare la classe.

// fetch the invoice created today
List<apex_invoice__c> invoiceList = [SELECT id, Name, APEX_Status__c,
createdDate FROM APEX_Invoice__c WHERE createdDate = today];
List<apex_invoice__c> updatedInvoiceList = new List<apex_invoice__c>();
APEX_Customer__c objCust = new APEX_Customer__C();
objCust.Name = 'Test';

// Inserting the Customer Records
insert objCust;
for (APEX_Invoice__c objInvoice: invoiceList) {
   if (objInvoice.APEX_Status__c == 'Pending') {
      objInvoice.APEX_Status__c = 'Paid';
      updatedInvoiceList.add(objInvoice);
   }
}

// DML Statement to update the invoice status
update updatedInvoiceList;

// Prints the value of updated invoices
System.debug('List has been updated and updated values are' + updatedInvoiceList);

// Inserting the New Records using insert DML statement
APEX_Invoice__c objNewInvoice = new APEX_Invoice__c();
objNewInvoice.APEX_Status__c = 'Pending';
objNewInvoice.APEX_Amount_Paid__c = 1000;
objNewInvoice.APEX_Customer__c = objCust.id;

// DML which is creating the new record
insert objNewInvoice;
System.debug('New Invoice Id is' + objNewInvoice.id);

// Deleting the Test invoices from Database
// fetch the invoices which are created for Testing, Select name which Customer Name
// is Test.
List<apex_invoice__c> invoiceListToDelete = [SELECT id FROM APEX_Invoice__c
   WHERE APEX_Customer__r.Name = 'Test'];

// DML Statement to delete the Invoices
delete invoiceListToDelete;
System.debug('Success, '+invoiceListToDelete.size()+' Records has been deleted');

Ripristina operazione

È possibile ripristinare il record che è stato eliminato ed è presente nel Cestino. Verranno ripristinate anche tutte le relazioni che ha il record eliminato.

Example

Supponiamo che i record eliminati nell'esempio precedente debbano essere ripristinati. Ciò può essere ottenuto utilizzando il seguente esempio. Il codice nell'esempio precedente è stato modificato per questo esempio.

// fetch the invoice created today
List<apex_invoice__c> invoiceList = [SELECT id, Name, APEX_Status__c,
createdDate FROM APEX_Invoice__c WHERE createdDate = today];
List<apex_invoice__c> updatedInvoiceList = new List<apex_invoice__c>();
APEX_Customer__c objCust = new APEX_Customer__C();
objCust.Name = 'Test';

// Inserting the Customer Records
insert objCust;
for (APEX_Invoice__c objInvoice: invoiceList) {
   if (objInvoice.APEX_Status__c == 'Pending') {
      objInvoice.APEX_Status__c = 'Paid';
      updatedInvoiceList.add(objInvoice);
   }
}

// DML Statement to update the invoice status
update updatedInvoiceList;

// Prints the value of updated invoices
System.debug('List has been updated and updated values are' + updatedInvoiceList);

// Inserting the New Records using insert DML statement
APEX_Invoice__c objNewInvoice = new APEX_Invoice__c();
objNewInvoice.APEX_Status__c = 'Pending';
objNewInvoice.APEX_Amount_Paid__c = 1000;
objNewInvoice.APEX_Customer__c = objCust.id;

// DML which is creating the new record
insert objNewInvoice;
System.debug('New Invoice Id is '+objNewInvoice.id);

// Deleting the Test invoices from Database
// fetch the invoices which are created for Testing, Select name which Customer Name
// is Test.
List<apex_invoice__c> invoiceListToDelete = [SELECT id FROM APEX_Invoice__c
   WHERE APEX_Customer__r.Name = 'Test'];

// DML Statement to delete the Invoices
delete invoiceListToDelete;
system.debug('Deleted Record Count is ' + invoiceListToDelete.size());
System.debug('Success, '+invoiceListToDelete.size() + 'Records has been deleted');

// Restore the deleted records using undelete statement
undelete invoiceListToDelete;
System.debug('Undeleted Record count is '+invoiceListToDelete.size()+'. This should 
   be same as Deleted Record count');

I metodi di classe del database sono un altro modo di lavorare con le istruzioni DML che sono più flessibili delle istruzioni DML come insert, update, ecc.

Differenze tra metodi di database e istruzioni DML

Dichiarazioni DML Metodi di database
L'aggiornamento parziale non è consentito. Ad esempio, se hai 20 record nell'elenco, verranno aggiornati tutti i record o nessuno. È consentito l'aggiornamento parziale. È possibile specificare il metodo Parameter in Database come true o false, true per consentire l'aggiornamento parziale e false per non consentire lo stesso.
Non è possibile ottenere l'elenco dei record riusciti e non riusciti. È possibile ottenere l'elenco dei record riusciti e non riusciti come abbiamo visto nell'esempio.
Example - inserire listName Example - Database.insert (listName, False), dove false indica che l'aggiornamento parziale non è consentito.

Inserisci operazione

Anche l'inserimento di nuovi record tramite metodi di database è abbastanza semplice e flessibile. Consideriamo lo scenario precedente in cui abbiamo inserito nuovi record utilizzando le istruzioni DML. Inseriremo lo stesso utilizzando i metodi del database.

Esempio

// Insert Operation Using Database methods
// Insert Customer Records First using simple DML Statement. This Customer Record will be
// used when we will create Invoice Records
APEX_Customer__c objCust = new APEX_Customer__C();
objCust.Name = 'Test';
insert objCust; // Inserting the Customer Records

// Insert Operation Using Database methods
APEX_Invoice__c objNewInvoice = new APEX_Invoice__c();
List<apex_invoice__c> InvoiceListToInsert = new List<apex_invoice__c>();
objNewInvoice.APEX_Status__c = 'Pending';
objNewInvoice.APEX_Customer__c = objCust.id;
objNewInvoice.APEX_Amount_Paid__c = 1000;
InvoiceListToInsert.add(objNewInvoice);
Database.SaveResult[] srList = Database.insert(InvoiceListToInsert, false);

// Database method to insert the records in List
// Iterate through each returned result by the method

for (Database.SaveResult sr : srList) {
   if (sr.isSuccess()) {
      // This condition will be executed for successful records and will fetch the ids 
      // of successful records
      System.debug('Successfully inserted Invoice. Invoice ID: ' + sr.getId());
      // Get the invoice id of inserted Account
   } else {
      // This condition will be executed for failed records
      for(Database.Error objErr : sr.getErrors()) {
         System.debug('The following error has occurred.');
         
         // Printing error message in Debug log
         System.debug(objErr.getStatusCode() + ': ' + objErr.getMessage());
         System.debug('Invoice oject field which are affected by the error:' 
            + objErr.getFields());
      }
   }
}

Operazione di aggiornamento

Consideriamo ora il nostro esempio di caso aziendale utilizzando i metodi del database. Supponiamo di dover aggiornare il campo di stato dell'oggetto Invoice ma, allo stesso tempo, abbiamo anche bisogno di informazioni come lo stato dei record, gli ID dei record non riusciti, il conteggio delle operazioni riuscite, ecc. Questo non è possibile utilizzando le istruzioni DML, quindi dobbiamo utilizzare i metodi del database per conoscere lo stato della nostra operazione.

Esempio

Aggiorneremo il campo "Stato" della fattura se è nello stato "In sospeso" e la data di creazione è oggi.

Il codice fornito di seguito aiuterà ad aggiornare i record delle fatture utilizzando il metodo Database.update. Inoltre, crea un record Fattura prima di eseguire questo codice.

// Code to update the records using the Database methods
List<apex_invoice__c> invoiceList = [SELECT id, Name, APEX_Status__c,
   createdDate FROM APEX_Invoice__c WHERE createdDate = today];

// fetch the invoice created today
List<apex_invoice__c> updatedInvoiceList = new List<apex_invoice__c>();
for (APEX_Invoice__c objInvoice: invoiceList) {
   if (objInvoice.APEX_Status__c == 'Pending') {
      objInvoice.APEX_Status__c = 'Paid';
      updatedInvoiceList.add(objInvoice);    //Adding records to the list
   }
}

Database.SaveResult[] srList = Database.update(updatedInvoiceList, false);
// Database method to update the records in List

// Iterate through each returned result by the method
for (Database.SaveResult sr : srList) {
   if (sr.isSuccess()) {
      // This condition will be executed for successful records and will fetch
      // the ids of successful records
      System.debug('Successfully updated Invoice. Invoice ID is : ' + sr.getId());
   } else {
      // This condition will be executed for failed records
      for(Database.Error objErr : sr.getErrors()) {
         System.debug('The following error has occurred.');
         
         // Printing error message in Debug log
         System.debug(objErr.getStatusCode() + ': ' + objErr.getMessage());
         System.debug('Invoice oject field which are affected by the error:' 
            + objErr.getFields());
      }
   }
}

In questo tutorial esamineremo solo le operazioni di inserimento e aggiornamento. Le altre operazioni sono abbastanza simili a queste operazioni ea ciò che abbiamo fatto nel capitolo precedente.

Ogni azienda o applicazione ha la funzionalità di ricerca come uno dei requisiti di base. Per questo, Salesforce.com fornisce due approcci principali utilizzando SOSL e SOQL. Discutiamo in dettaglio l'approccio SOSL in questo capitolo.

SOSL

La ricerca della stringa di testo nell'oggetto e nel campo verrà eseguita utilizzando SOSL. Questo è il linguaggio di ricerca degli oggetti di Salesforce. Ha la capacità di cercare una particolare stringa su più oggetti.

Le istruzioni SOSL restituiscono un elenco di oggetti, in cui ogni elenco contiene i risultati della ricerca per un particolare tipo di oggetto. Gli elenchi dei risultati vengono sempre restituiti nello stesso ordine in cui sono stati specificati nella query SOSL.

Esempio di query SOSL

Consideriamo un caso aziendale in cui dobbiamo sviluppare un programma in grado di cercare una stringa specificata. Supponiamo di dover cercare la stringa "ABC" nel campo Nome cliente dell'oggetto Fattura. Il codice è il seguente:

Innanzitutto, devi creare un singolo record nell'oggetto Fattura con il nome del cliente come "ABC" in modo che possiamo ottenere risultati validi durante la ricerca.

// Program To Search the given string in all Object
// List to hold the returned results of sObject generic type
List<list<SObject>> invoiceSearchList = new List<List<SObject>>();

// SOSL query which will search for 'ABC' string in Customer Name field of Invoice Object
invoiceSearchList = [FIND 'ABC*' IN ALL FIELDS RETURNING APEX_Invoice_c
   (Id,APEX_Customer_r.Name)];

// Returned result will be printed
System.debug('Search Result '+invoiceSearchList);

// Now suppose, you would like to search string 'ABC' in two objects,
// that is Invoice and Account. Then for this query goes like this:

// Program To Search the given string in Invoice and Account object,
// you could specify more objects if you want, create an Account with Name as ABC.

// List to hold the returned results of sObject generic type
List<List<SObject>> invoiceAndSearchList = new List<List<SObject>>();

// SOSL query which will search for 'ABC' string in Invoice and in Account object's fields
invoiceAndSearchList = [FIND 'ABC*' IN ALL FIELDS RETURNING APEX_Invoice__c
   (Id,APEX_Customer__r.Name), Account];

// Returned result will be printed
System.debug('Search Result '+invoiceAndSearchList);

// This list will hold the returned results for Invoice Object
APEX_Invoice__c [] searchedInvoice = ((List<APEX_Invoice_c>)invoiceAndSearchList[0]);

// This list will hold the returned results for Account Object
Account [] searchedAccount = ((List<Account>)invoiceAndSearchList[1]);
System.debug('Value of searchedInvoice'+searchedInvoice+'Value of searchedAccount'
   + searchedAccount);

SOQL

Questo è quasi lo stesso di SOQL. È possibile utilizzarlo per recuperare i record dell'oggetto da un oggetto solo alla volta. Puoi scrivere query annidate e anche recuperare i record dall'oggetto padre o figlio su cui stai interrogando ora.

Esploreremo SOQL nel prossimo capitolo.

Si tratta di Salesforce Object Query Language progettato per funzionare con SFDC Database. Può cercare un record su un dato criterio solo in un singolo oggetto.

Come SOSL, non può eseguire ricerche su più oggetti ma supporta query annidate.

Esempio SOQL

Considera il nostro esempio continuo di Chemical Company. Supponiamo di aver bisogno di un elenco di record che vengono creati oggi e il cui nome cliente non è "test". In questo caso, dovremo utilizzare la query SOQL come indicato di seguito:

// fetching the Records via SOQL
List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
InvoiceList = [SELECT Id, Name, APEX_Customer__r.Name, APEX_Status__c FROM
   APEX_Invoice__c WHERE createdDate = today AND APEX_Customer__r.Name != 'Test'];
// SOQL query for given criteria

// Printing the fetched records
System.debug('We have total '+InvoiceList.size()+' Records in List');

for (APEX_Invoice__c objInvoice: InvoiceList) {
   System.debug('Record Value is '+objInvoice); 
   // Printing the Record fetched
}

È possibile eseguire la query SOQL tramite l'Editor di query nella Console per gli sviluppatori come mostrato di seguito.

Esegui la query indicata di seguito nella Developer Console. Cerca i record delle fatture creati oggi.

SELECT Id, Name, APEX_Customer__r.Name, APEX_Status__c FROM APEX_Invoice__c
   WHERE createdDate = today

È necessario selezionare i campi per i quali sono necessari i valori, altrimenti può generare errori in fase di esecuzione.

Attraversare i campi di relazione

Questa è una delle parti più importanti in SFDC poiché molte volte abbiamo bisogno di attraversare la relazione dell'oggetto padre figlio

Inoltre, potrebbero verificarsi casi in cui è necessario inserire due record di oggetti associati nel database. Ad esempio, l'oggetto Fattura ha una relazione con l'oggetto Cliente e quindi un cliente può avere molte fatture.

Supponiamo che tu stia creando la fattura e quindi sia necessario correlare questa fattura al cliente. È possibile utilizzare il codice seguente per questa funzionalità:

// Now create the invoice record and relate it with the Customer object
// Before executing this, please create a Customer Records with Name 'Customer
// Creation Test'
APEX_Invoice__c objInvoice = new APEX_Invoice__c();

// Relating Invoice to customer via id field of Customer object
objInvoice.APEX_Customer__c = [SELECT id FROM APEX_Customer__c WHERE Name =
   'Customer Creation Test' LIMIT 1].id;
objInvoice.APEX_Status__c = 'Pending';
insert objInvoice;  //Creating Invoice
System.debug('Newly Created Invoice'+objInvoice);  //Newly created invoice

Esegui questo snippet di codice nella Developer Console. Una volta eseguito, copia l'ID della fattura dalla Console per gli sviluppatori e quindi apri lo stesso in SFDC come mostrato di seguito. Puoi vedere che il record genitore è già stato assegnato al record fattura come mostrato di seguito.

Recupero di record figlio

Consideriamo ora un esempio in cui tutte le fatture relative a un particolare record cliente devono essere in un unico posto. Per questo, devi conoscere il nome della relazione figlio. Per vedere il nome della relazione figlio, vai alla pagina dei dettagli del campo sull'oggetto figlio e controlla il valore "Relazione figlio". Nel nostro esempio, sono le fatture aggiunte da __r alla fine.

Esempio

In questo esempio, dovremo impostare i dati, creare un cliente con il nome come record "Cliente ABC" e quindi aggiungere 3 fatture a quel cliente.

A questo punto, recupereremo le fatture del cliente "Cliente ABC". Di seguito è riportata la query per lo stesso:

// Fetching Child Records using SOQL
List<apex_customer__c> ListCustomers = [SELECT Name, Id, 
   (SELECT id, Name FROM Invoices__r) FROM APEX_Customer__c WHERE Name = 'ABC Customer'];

// Query for fetching the Child records along with Parent
System.debug('ListCustomers '+ListCustomers); // Parent Record

List<apex_invoice__c> ListOfInvoices = ListCustomers[0].Invoices__r;
// By this notation, you could fetch the child records and save it in List
System.debug('ListOfInvoices values of Child '+ListOfInvoices);
// Child records

Puoi vedere i valori dei record nei registri di debug.

Recupero del record genitore

Supponiamo che sia necessario recuperare il nome cliente della fattura la cui data di creazione è oggi, quindi è possibile utilizzare la query fornita di seguito per lo stesso:

Esempio

Recupera il valore del record padre insieme all'oggetto figlio.

// Fetching Parent Record Field value using SOQL
List<apex_invoice__c> ListOfInvoicesWithCustomerName = new List<apex_invoice__c>();
ListOfInvoicesWithCustomerName = [SELECT Name, id, APEX_Customer__r.Name 
   FROM APEX_Invoice__c LIMIT 10];

// Fetching the Parent record's values
for (APEX_Invoice__c objInv: ListOfInvoicesWithCustomerName) {
   System.debug('Invoice Customer Name is '+objInv.APEX_Customer__r.Name);
   // Will print the values, all the Customer Records will be printed
}

Qui abbiamo usato la notazione APEX_Customer__r.Name, dove APEX_Customer__r è il nome della relazione genitore, qui devi aggiungere __r alla fine del campo Parent e poi puoi recuperare il valore del campo genitore.

Funzioni aggregate

SOQL ha una funzione aggregata come in SQL. Le funzioni aggregate ci consentono di raggruppare e riepilogare i dati. Vediamo ora di capire la funzione in dettaglio.

Supponi di voler sapere qual è il ricavo medio che otteniamo dal cliente "Cliente ABC", quindi puoi utilizzare questa funzione per calcolare la media.

Esempio

// Getting Average of all the invoices for a Perticular Customer
AggregateResult[] groupedResults = [SELECT
   AVG(APEX_Amount_Paid__c)averageAmount FROM APEX_Invoice__c WHERE
   APEX_Customer__r.Name = 'ABC Customer'];
Object avgPaidAmount = groupedResults[0].get('averageAmount');
System.debug('Total Average Amount Received From Customer ABC is '+avgPaidAmount);

Controlla l'output nei registri di debug. Tieni presente che qualsiasi query che include una funzione di aggregazione restituisce i risultati in una matrice diAggregateResultoggetti. AggregateResult è un oggetto di sola lettura e viene utilizzato solo per i risultati della query. È utile quando è necessario generare il report sui dati di grandi dimensioni.

Esistono anche altre funzioni aggregate che è possibile utilizzare per eseguire il riepilogo dei dati.

MIN() - Può essere utilizzato per trovare il valore minimo

MAX() - Questo può essere utilizzato per trovare il valore massimo.

Variabili Apex vincolanti

È possibile utilizzare la variabile Apex nella query SOQL per recuperare i risultati desiderati. Le variabili Apex possono essere referenziate dalla notazione due punti (:).

Esempio

// Apex Variable Reference
String CustomerName = 'ABC Customer';
List<apex_customer__c> ListCustomer = [SELECT Id, Name FROM APEX_Customer__c
   WHERE Name = :CustomerName];

// Query Using Apex variable
System.debug('ListCustomer Name'+ListCustomer); // Customer Name

La sicurezza Apex si riferisce al processo di applicazione delle impostazioni di sicurezza e di applicazione delle regole di condivisione sull'esecuzione del codice. Le classi Apex hanno impostazioni di sicurezza che possono essere controllate tramite due parole chiave.

Sicurezza dei dati e regole di condivisione

Apex viene generalmente eseguito nel contesto del sistema, ovvero le autorizzazioni dell'utente corrente. La sicurezza a livello di campo e le regole di condivisione non vengono prese in considerazione durante l'esecuzione del codice. Solo il codice del blocco anonimo viene eseguito con il permesso dell'utente che sta eseguendo il codice.

Il nostro codice Apex non deve esporre i dati sensibili all'utente che sono nascosti tramite le impostazioni di sicurezza e condivisione. Pertanto, la sicurezza di Apex e l'applicazione della regola di condivisione sono molto importanti.

Con la condivisione delle parole chiave

Se si utilizza questa parola chiave, il codice Apex applicherà le impostazioni di condivisione dell'utente corrente ad Apex code. Ciò non applica l'autorizzazione del profilo, ma solo le impostazioni di condivisione a livello di dati.

Consideriamo un esempio in cui, il nostro utente ha accesso a 5 record, ma il numero totale di record è 10. Quindi quando la classe Apex verrà dichiarata con la parola chiave "With Sharing", restituirà solo 5 record su cui l'utente ha accesso a.

Example

Innanzitutto, assicurati di aver creato almeno 10 record nell'oggetto Cliente con "Nome" di 5 record come "Cliente ABC" e riposa 5 record come "Cliente XYZ". Quindi, crea una regola di condivisione che condividerà il "Cliente ABC" con tutti gli utenti. Dobbiamo anche assicurarci di aver impostato l'OWD dell'oggetto Cliente come Privato.

Incolla il codice fornito di seguito nel blocco Anonimo nella Console per gli sviluppatori.

// Class With Sharing
public with sharing class MyClassWithSharing {
   // Query To fetch 10 records
   List<apex_customer__c> CustomerList = [SELECT id, Name FROM APEX_Customer__c LIMIT 10];
   
   public Integer executeQuery () {
      System.debug('List will have only 5 records and the actual records are' 
         + CustomerList.size()+' as user has access to'+CustomerList);
      Integer ListSize = CustomerList.size();
      return ListSize;
   }
}

// Save the above class and then execute as below
// Execute class using the object of class
MyClassWithSharing obj = new MyClassWithSharing();
Integer ListSize = obj.executeQuery();

Senza condividere la parola chiave

Come suggerisce il nome, la classe dichiarata con questa parola chiave viene eseguita in modalità System, ovvero, indipendentemente dall'accesso dell'utente al record, la query recupererà tutti i record.

// Class Without Sharing
public without sharing class MyClassWithoutSharing {
   List<apex_customer__c> CustomerList = [SELECT id, Name FROM APEX_Customer__c LIMIT 10];
   
   // Query To fetch 10 records, this will return all the records
   public Integer executeQuery () {
      System.debug('List will have only 5 records and the actula records are'
         + CustomerList.size()+' as user has access to'+CustomerList);
      Integer ListSize = CustomerList.size();
      return ListSize;
   }
}
// Output will be 10 records.

Impostazione della sicurezza per la classe Apex

È possibile abilitare o disabilitare una classe Apex per un profilo particolare. I passaggi per lo stesso sono riportati di seguito. È possibile determinare quale profilo deve avere accesso a quale classe.

Impostazione della sicurezza della classe Apex dalla pagina dell'elenco delle classi

Step 1 - Da Imposta, fai clic su Sviluppo → Classi Apex.

Step 2- Fare clic sul nome della classe che si desidera limitare. Abbiamo cliccato su CustomerOperationClass.

Step 3 - Fare clic su Sicurezza.

Step 4 - Selezionare i profili che si desidera abilitare dall'elenco Profili disponibili e fare clic su Aggiungi oppure selezionare i profili che si desidera disabilitare dall'elenco Profili abilitati e fare clic su Rimuovi.

Step 5 - Fare clic su Salva.

Impostazione della protezione Apex dal set di autorizzazioni

Step 1 - Da Imposta, fare clic su Gestisci utenti → Set di autorizzazioni.

Step 2 - Seleziona un insieme di autorizzazioni.

Step 3 - Fare clic su Apex Class Access.

Step 4 - Fare clic su Modifica.

Step 5 - Selezionare le classi Apex che si desidera abilitare dall'elenco Classi Apex disponibili e fare clic su Aggiungi oppure selezionare le classi Apex che si desidera disabilitare dall'elenco Classi Apex abilitate e fare clic su Rimuovi.

Step 6 - Fare clic sul pulsante Salva.

Il richiamo di Apex si riferisce al processo di esecuzione della classe Apex. La classe Apex può essere eseguita solo quando viene invocata tramite uno dei modi elencati di seguito:

  • Trigger e blocco anonimo

  • Un trigger richiamato per eventi specificati

  • Apex asincrono

  • Pianificazione di una classe Apex da eseguire a intervalli specificati o esecuzione di un lavoro batch

  • Classe di servizi Web

  • Classe del servizio di posta elettronica Apex

  • Servizi Web Apex, che consentono di esporre i metodi tramite i servizi Web SOAP e REST

  • Controller Visualforce

  • Servizio di posta elettronica Apex per elaborare la posta in arrivo

  • Invocare Apex utilizzando JavaScript

  • Il toolkit Ajax per richiamare i metodi del servizio Web implementati in Apex

Ora capiremo alcuni modi comuni per invocare Apex.

Da Esegui blocco anonimo

Puoi invocare la classe Apex tramite l'esecuzione anonima nella Console per gli sviluppatori come mostrato di seguito:

Step 1 - Apri la Console per gli sviluppatori.

Step 2 - Fare clic su Debug.

Step 3- La finestra Esegui anonimo si aprirà come mostrato di seguito. Ora, fai clic sul pulsante Esegui -

Step 4 - Apri il registro di debug quando apparirà nel pannello Registri.

Da Trigger

Puoi anche chiamare una classe Apex da Trigger. I trigger vengono chiamati quando si verifica un evento specificato e possono chiamare la classe Apex durante l'esecuzione.

Di seguito è riportato il codice di esempio che mostra come viene eseguita una classe quando viene chiamato un trigger.

Esempio

// Class which will gets called from trigger
public without sharing class MyClassWithSharingTrigger {

   public static Integer executeQuery (List<apex_customer__c> CustomerList) {
      // perform some logic and operations here
      Integer ListSize = CustomerList.size();
      return ListSize;
   }
}

// Trigger Code
trigger Customer_After_Insert_Example on APEX_Customer__c (after insert) {
   System.debug('Trigger is Called and it will call Apex Class');
   MyClassWithSharingTrigger.executeQuery(Trigger.new);  // Calling Apex class and 
                                                         // method of an Apex class
}

// This example is for reference, no need to execute and will have detail look on 
// triggers later chapters.

Dal codice del controller della pagina Visualforce

La classe Apex può essere chiamata anche dalla pagina Visualforce. Possiamo specificare il controller o l'estensione del controller e la classe Apex specificata viene chiamata.

Esempio

VF Page Code

Apex Class Code (Controller Extension)

I trigger Apex sono come procedure memorizzate che vengono eseguite quando si verifica un particolare evento. Un trigger viene eseguito prima e dopo che un evento si verifica nel record.

Sintassi

trigger triggerName on ObjectName (trigger_events) { Trigger_code_block }

Esecuzione del trigger

Di seguito sono riportati gli eventi su cui possiamo attivare il grilletto:

  • insert
  • update
  • delete
  • merge
  • upsert
  • undelete

Esempio di trigger 1

Si supponga di aver ricevuto un requisito aziendale per la creazione di un record fattura quando il campo "Stato cliente" del cliente cambia in Attivo da Inattivo. Per questo, creeremo un trigger sull'oggetto APEX_Customer__c seguendo questi passaggi:

Step 1 - Vai a sObject

Step 2 - Fare clic su Cliente

Step 3 - Fare clic sul pulsante "Nuovo" nell'elenco correlato Trigger e aggiungere il codice trigger come indicato di seguito.

// Trigger Code
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   List InvoiceList = new List();
   
   for (APEX_Customer__c objCustomer: Trigger.new) {
      
      if (objCustomer.APEX_Customer_Status__c == 'Active') {
         APEX_Invoice__c objInvoice = new APEX_Invoice__c();
         objInvoice.APEX_Status__c = 'Pending';
         InvoiceList.add(objInvoice);
      }
   }
   
   // DML to insert the Invoice List in SFDC
   insert InvoiceList;
}

Spiegazione

Trigger.new- Questa è la variabile di contesto che memorizza i record attualmente nel contesto di trigger, inseriti o aggiornati. In questo caso, questa variabile ha i record dell'oggetto Cliente che sono stati aggiornati.

Ci sono altre variabili di contesto disponibili nel contesto: trigger.old, trigger.newMap, trigger.OldMap.

Esempio di trigger 2

Il trigger di cui sopra verrà eseguito quando è presente un'operazione di aggiornamento sui record del cliente. Supponiamo che il record della fattura debba essere inserito solo quando lo Stato del cliente cambia da Inattivo ad Attivo e non ogni volta; per questo, possiamo usare un'altra variabile di contestotrigger.oldMap che memorizzerà la chiave come ID record e il valore come vecchi valori record.

// Modified Trigger Code
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
   
   for (APEX_Customer__c objCustomer: Trigger.new) {
      
      // condition to check the old value and new value
      if (objCustomer.APEX_Customer_Status__c == 'Active' &&
      
      trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
         APEX_Invoice__c objInvoice = new APEX_Invoice__c();
         objInvoice.APEX_Status__c = 'Pending';
         InvoiceList.add(objInvoice);
      }
   }
   
   // DML to insert the Invoice List in SFDC
   insert InvoiceList;
}

Spiegazione

Abbiamo utilizzato la variabile Trigger.oldMap che, come spiegato in precedenza, è una variabile di contesto che memorizza l'ID e il vecchio valore dei record che vengono aggiornati.

I modelli di progettazione vengono utilizzati per rendere il nostro codice più efficiente e per evitare di raggiungere i limiti del governor. Spesso gli sviluppatori possono scrivere codice inefficiente che può causare ripetute istanze di oggetti. Ciò può comportare un codice inefficiente, con prestazioni scarse e potenzialmente la violazione dei limiti del governatore. Ciò si verifica più comunemente nei trigger, poiché possono operare su un insieme di record.

In questo capitolo vedremo alcune importanti strategie di design pattern.

Modelli di progettazione di trigger in blocco

Nel caso aziendale reale, potrebbe essere necessario elaborare migliaia di record in una volta sola. Se il trigger non è progettato per gestire tali situazioni, potrebbe non riuscire durante l'elaborazione dei record. Esistono alcune best practice che è necessario seguire durante l'implementazione dei trigger. Tutti i trigger sono trigger in blocco per impostazione predefinita e possono elaborare più record alla volta. Dovresti sempre pianificare l'elaborazione di più di un record alla volta.

Considera un caso aziendale, in cui è necessario elaborare un gran numero di record e aver scritto il trigger come indicato di seguito. Questo è lo stesso esempio che avevamo preso per inserire il record della fattura quando lo Stato del cliente cambia da Inattivo ad Attivo.

// Bad Trigger Example
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   
   for (APEX_Customer__c objCustomer: Trigger.new) {
      
      if (objCustomer.APEX_Customer_Status__c == 'Active' && 
         trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
         
         // condition to check the old value and new value
         APEX_Invoice__c objInvoice = new APEX_Invoice__c();
         objInvoice.APEX_Status__c = 'Pending';
         insert objInvoice;   //DML to insert the Invoice List in SFDC
      }
   }
}

Ora puoi vedere che l'istruzione DML è stata scritta per il blocco loop che funzionerà quando si elaborano solo pochi record ma quando si elaborano alcune centinaia di record, raggiungerà il limite dell'istruzione DML per transazione che è il governor limit. Avremo uno sguardo dettagliato sui limiti del governatore in un capitolo successivo.

Per evitare ciò, dobbiamo rendere il trigger efficiente per l'elaborazione di più record alla volta.

Il seguente esempio ti aiuterà a capire lo stesso:

// Modified Trigger Code-Bulk Trigger
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
   
   for (APEX_Customer__c objCustomer: Trigger.new) {
      
      if (objCustomer.APEX_Customer_Status__c == 'Active' &&
         trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
         
         //condition to check the old value and new value
         APEX_Invoice__c objInvoice = new APEX_Invoice__c();
         objInvoice.APEX_Status__c = 'Pending';
         InvoiceList.add(objInvoice);//Adding records to List
      }
   }
   
   insert InvoiceList;
   // DML to insert the Invoice List in SFDC, this list contains the all records 
   // which need to be modified and will fire only one DML
}

Questo trigger attiverà solo 1 istruzione DML poiché funzionerà su una lista e la lista ha tutti i record che devono essere modificati.

In questo modo, puoi evitare i limiti del governor dell'istruzione DML.

Classe assistente trigger

Anche scrivere l'intero codice in trigger non è una buona pratica. Quindi è necessario chiamare la classe Apex e delegare l'elaborazione da Trigger alla classe Apex come mostrato di seguito. La classe Trigger Helper è la classe che esegue tutte le elaborazioni per il trigger.

Consideriamo nuovamente il nostro esempio di creazione di record di fattura.

// Below is the Trigger without Helper class
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
   
   for (APEX_Customer__c objCustomer: Trigger.new) {
      
      if (objCustomer.APEX_Customer_Status__c == 'Active' &&
         trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
         
         // condition to check the old value and new value
         APEX_Invoice__c objInvoice = new APEX_Invoice__c();
         objInvoice.APEX_Status__c = 'Pending';
         InvoiceList.add(objInvoice);
      }
   }
   
   insert InvoiceList; // DML to insert the Invoice List in SFDC
}

// Below is the trigger with helper class
// Trigger with Helper Class
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   CustomerTriggerHelper.createInvoiceRecords(Trigger.new, trigger.oldMap);
   // Trigger calls the helper class and does not have any code in Trigger
}

Classe di aiuto

public class CustomerTriggerHelper {
   public static void createInvoiceRecords (List<apex_customer__c>
   
   customerList, Map<id, apex_customer__c> oldMapCustomer) {
      List<apex_invoice__c> InvoiceList = new Listvapex_invoice__c>();
      
      for (APEX_Customer__c objCustomer: customerList) {
         
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            oldMapCustomer.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            
            // condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            
            // objInvoice.APEX_Status__c = 'Pending';
            InvoiceList.add(objInvoice);
         }
      }
      
      insert InvoiceList;  // DML to insert the Invoice List in SFDC
   }
}

In questo, tutta l'elaborazione è stata delegata alla classe helper e quando abbiamo bisogno di una nuova funzionalità possiamo semplicemente aggiungere il codice alla classe helper senza modificare il trigger.

Trigger singolo su ogni oggetto

Crea sempre un singolo trigger su ogni oggetto. Più trigger sullo stesso oggetto possono causare il conflitto e gli errori se raggiunge i limiti del governor.

È possibile utilizzare la variabile di contesto per chiamare i diversi metodi dalla classe helper secondo il requisito. Considera il nostro esempio precedente. Supponiamo che il nostro metodo createInvoice debba essere chiamato solo quando il record viene aggiornato e su più eventi. Quindi possiamo controllare l'esecuzione come di seguito -

// Trigger with Context variable for controlling the calling flow
trigger Customer_After_Insert on APEX_Customer__c (after update, after insert) {
   
   if (trigger.isAfter && trigger.isUpdate) {
      // This condition will check for trigger events using isAfter and isUpdate
      // context variable
      CustomerTriggerHelper.createInvoiceRecords(Trigger.new);
      
      // Trigger calls the helper class and does not have any code in Trigger
      // and this will be called only when trigger ids after update
   }
}

// Helper Class
public class CustomerTriggerHelper {
   
   //Method To Create Invoice Records
   public static void createInvoiceRecords (List<apex_customer__c> customerList) {
      
      for (APEX_Customer__c objCustomer: customerList) {
         
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            
            // condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            objInvoice.APEX_Status__c = 'Pending';
            InvoiceList.add(objInvoice);
         }
      }
      
      insert InvoiceList; // DML to insert the Invoice List in SFDC
   }
}

I limiti di esecuzione del governor assicurano l'uso efficiente delle risorse sulla piattaforma multi-tenant Force.com. È il limite specificato da Salesforce.com all'esecuzione del codice per un'elaborazione efficiente.

Cosa sono i limiti del governatore?

Come sappiamo, Apex funziona in ambiente multi-tenant, ovvero una singola risorsa è condivisa da tutti i clienti e le organizzazioni. Quindi, è necessario assicurarsi che nessuno monopolizzi le risorse e quindi Salesforce.com ha creato l'insieme di limiti che regola e limita l'esecuzione del codice. Ogni volta che uno qualsiasi dei limiti del governatore viene superato, genererà un errore e interromperà l'esecuzione del programma.

Dal punto di vista di uno sviluppatore, è importante garantire che il nostro codice sia scalabile e non raggiunga i limiti.

Tutti questi limiti vengono applicati per transazione. Un'esecuzione di un singolo trigger è una transazione.

Come abbiamo visto, il modello di progettazione del trigger aiuta a evitare l'errore di limite. Vedremo ora altri importanti limiti.

Evitare il limite di query SOQL

Puoi emettere solo 100 query per transazione, ovvero, quando il tuo codice emetterà più di 100 query SOQL, genererà un errore.

Esempio

Questo esempio mostra come è possibile raggiungere il limite di query SOQL:

Il trigger seguente esegue un'iterazione su un elenco di clienti e aggiorna la descrizione del record figlio (Fattura) con la stringa "OK per il pagamento".

// Helper class:Below code needs o be checked.
public class CustomerTriggerHelper {
  
  public static void isAfterUpdateCall(Trigger.new) {
      createInvoiceRecords(trigger.new);//Method call
      updateCustomerDescription(trigger.new);
   }
   
   // Method To Create Invoice Records
   public static void createInvoiceRecords (List<apex_customer__c> customerList) {
      for (APEX_Customer__c objCustomer: customerList) {
         
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            
            // condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            objInvoice.APEX_Status__c = 'Pending';
            InvoiceList.add(objInvoice);
         }
      }
      insert InvoiceList; // DML to insert the Invoice List in SFDC
   }
   
   // Method to update the invoice records
   public static updateCustomerDescription (List<apex_customer__c> customerList) {
      for (APEX_Customer__c objCust: customerList) {
         List<apex_customer__c> invList = [SELECT Id, Name,
            APEX_Description__c FROM APEX_Invoice__c WHERE APEX_Customer__c = :objCust.id];
         
         // This query will fire for the number of records customer list has and will
         // hit the governor limit when records are more than 100
         for (APEX_Invoice__c objInv: invList) {
            objInv.APEX_Description__c = 'OK To Pay';
            update objInv;
            // Update invoice, this will also hit the governor limit for DML if large
            // number(150) of records are there
         }
      }
   }
}

Quando viene chiamato il metodo "updateCustomerDescription" e il numero di record del cliente è superiore a 100, raggiungerà il limite SOQL. Per evitare ciò, non scrivere mai la query SOQL nel ciclo For. In questo caso, la query SOQL è stata scritta nel ciclo For.

Di seguito è riportato un esempio che mostrerà come evitare il limite DML e SOQL. Abbiamo utilizzato la query di relazione nidificata per recuperare i record della fattura e abbiamo utilizzato la variabile di contestotrigger.newMap per ottenere la mappa dell'ID e dei record dei clienti.

// SOQL-Good Way to Write Query and avoid limit exception
// Helper Class
public class CustomerTriggerHelper {
   public static void isAfterUpdateCall(Trigger.new) {
      createInvoiceRecords(trigger.new);  //Method call
      updateCustomerDescription(trigger.new, trigger.newMap);
   }
   
   // Method To Create Invoice Records
   public static void createInvoiceRecords (List<apex_customer__c> customerList) {
      for (APEX_Customer__c objCustomer: customerList) {
         
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            trigger.oldMap.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            
            // condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            objInvoice.APEX_Status__c = 'Pending';
            InvoiceList.add(objInvoice);
         }
      }
      insert InvoiceList; // DML to insert the Invoice List in SFDC
   }
   
   // Method to update the invoice records
   public static updateCustomerDescription (List<apex_customer__c>
      customerList, Map<id, apex_customer__c> newMapVariable) {
      List<apex_customer__c> customerListWithInvoice = [SELECT id,
         Name,(SELECT Id, Name, APEX_Description__c FROM APEX_Invoice__r) FROM
         APEX_Customer__c WHERE Id IN :newMapVariable.keySet()];
      
      // Query will be for only one time and fetches all the records
      List<apex_invoice__c> invoiceToUpdate = new
      List<apex_invoice__c>();
      
      for (APEX_Customer__c objCust: customerList) {
         for (APEX_Invoice__c objInv: invList) {
            objInv.APEX_Description__c = 'OK To Pay';
            invoiceToUpdate.add(objInv);
            // Add the modified records to List
         }
      }
      update invoiceToUpdate;
   }
}

Chiamate in blocco DML

Questo esempio mostra il trigger Bulk insieme al modello di classe di supporto del trigger. È necessario salvare prima la classe helper e quindi salvare il trigger.

Note - Incolla il codice seguente nella classe "CustomerTriggerHelper" che abbiamo creato in precedenza.

// Helper Class
public class CustomerTriggerHelper {
   public static void isAfterUpdateCall(List<apex_customer__c> customerList,
      Map<id, apex_customer__c> mapIdToCustomers, Map<id, apex_customer__c>
      mapOldItToCustomers) {
      createInvoiceRecords(customerList, mapOldItToCustomers);   //Method call
      updateCustomerDescription(customerList,mapIdToCustomers,
      mapOldItToCustomers);
   }
   
   // Method To Create Invoice Records
   public static void createInvoiceRecords (List<apex_customer__c>
      customerList, Map<id, apex_customer__c> mapOldItToCustomers) {
      List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
      List<apex_customer__c> customerToInvoice = [SELECT id, Name FROM
         APEX_Customer__c LIMIT 1];
      
      for (APEX_Customer__c objCustomer: customerList) {
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            mapOldItToCustomers.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            //condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            objInvoice.APEX_Status__c = 'Pending';
            objInvoice.APEX_Customer__c = objCustomer.id;
            InvoiceList.add(objInvoice);
         }
      }
      system.debug('InvoiceList&&&'+InvoiceList);
      insert InvoiceList;
      // DML to insert the Invoice List in SFDC. This also follows the Bulk pattern
   }
   
   // Method to update the invoice records
   public static void updateCustomerDescription (List<apex_customer__c>
      customerList, Map<id, apex_customer__c> newMapVariable, Map<id,
      apex_customer__c> oldCustomerMap) {
      List<apex_customer__c> customerListWithInvoice = [SELECT id,
      Name,(SELECT Id, Name, APEX_Description__c FROM Invoices__r) FROM
         APEX_Customer__c WHERE Id IN :newMapVariable.keySet()];
   
      // Query will be for only one time and fetches all the records
      List<apex_invoice__c> invoiceToUpdate = new List<apex_invoice__c>();
      List<apex_invoice__c> invoiceFetched = new List<apex_invoice__c>();
      invoiceFetched = customerListWithInvoice[0].Invoices__r;
      system.debug('invoiceFetched'+invoiceFetched);
      system.debug('customerListWithInvoice****'+customerListWithInvoice);
   
      for (APEX_Customer__c objCust: customerList) {
         system.debug('objCust.Invoices__r'+objCust.Invoices__r);
         if (objCust.APEX_Active__c == true &&
            oldCustomerMap.get(objCust.id).APEX_Active__c == false) {
            for (APEX_Invoice__c objInv: invoiceFetched) {
               system.debug('I am in For Loop'+objInv);
               objInv.APEX_Description__c = 'OK To Pay';
               invoiceToUpdate.add(objInv);
               // Add the modified records to List
            }
         }
      }
     system.debug('Value of List ***'+invoiceToUpdate);
     update invoiceToUpdate;
      // This statement is Bulk DML which performs the DML on List and avoids
      // the DML Governor limit
   }
}

// Trigger Code for this class: Paste this code in 'Customer_After_Insert'
// trigger on Customer Object
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   CustomerTriggerHelper.isAfterUpdateCall(Trigger.new, trigger.newMap,
      trigger.oldMap);
   // Trigger calls the helper class and does not have any code in Trigger
}

Altri limiti del governatore di Salesforce

La tabella seguente elenca i limiti importanti del governatore.

Descrizione Limite
Dimensione totale dell'heap 6 MB / 12 MB
Numero totale di dichiarazioni DML emesse 150
Numero totale di record recuperati da una singola query SOSL 2000
Numero totale di query SOSL emesse 20
Numero totale di record recuperati da Database.getQueryLocator 10000
Numero totale di record recuperati dalle query SOQL 50000

In questo capitolo capiremo l'elaborazione in batch in Apex. Considera uno scenario in cui elaboreremo un gran numero di record su base giornaliera, probabilmente la pulizia dei dati o forse l'eliminazione di alcuni dati inutilizzati.

Cos'è Batch Apex?

Batch Apex è l'esecuzione asincrona del codice Apex, appositamente progettato per l'elaborazione di un gran numero di record e ha una maggiore flessibilità nei limiti del governor rispetto al codice sincrono.

Quando utilizzare Batch Apex?

  • Quando si desidera elaborare un numero elevato di record su base giornaliera o anche in un intervallo di tempo specifico, è possibile utilizzare Batch Apex.

  • Inoltre, quando si desidera che un'operazione sia asincrona, è possibile implementare Batch Apex. Batch Apex è esposto come un'interfaccia che deve essere implementata dallo sviluppatore. I processi batch possono essere richiamati a livello di codice in fase di esecuzione utilizzando Apex. Batch Apex opera su piccoli batch di record, coprendo l'intero set di record e suddividendo l'elaborazione in blocchi di dati gestibili.

Utilizzo di Batch Apex

Quando si utilizza Batch Apex, è necessario implementare l'interfaccia Database.Batchable fornita da Salesforce, quindi richiamare la classe a livello di codice.

Puoi monitorare la classe seguendo questi passaggi:

Per monitorare o interrompere l'esecuzione del lavoro batch Apex batch, andare a Configurazione → Monitoraggio → Lavori Apex o Lavori → Lavori Apex.

L'interfaccia Database.Batchable ha i seguenti tre metodi che devono essere implementati:

  • Start
  • Execute
  • Finish

Vediamo ora di capire in dettaglio ogni metodo.

Inizio

Il metodo Start è uno dei tre metodi dell'interfaccia Database.Batchable.

Syntax

global void execute(Database.BatchableContext BC, list<sobject<) {}

Questo metodo verrà richiamato all'avvio del lavoro batch e raccoglie i dati su cui opererà il lavoro batch.

Considera i seguenti punti per comprendere il metodo:

  • Utilizzare il Database.QueryLocatoroggetto quando si utilizza una query semplice per generare l'ambito degli oggetti utilizzati nel lavoro batch. In questo caso, il limite di righe di dati SOQL verrà ignorato.

  • Utilizzare l'oggetto iterabile quando si dispone di criteri complessi per elaborare i record. Database.QueryLocator determina l'ambito dei record che devono essere elaborati.

Eseguire

Vediamo ora di comprendere il metodo Execute dell'interfaccia Database.Batchable.

Syntax

global void execute(Database.BatchableContext BC, list<sobject<) {}

dove, list <sObject <viene restituito dal metodo Database.QueryLocator.

Questo metodo viene chiamato dopo il metodo Start ed esegue tutta l'elaborazione richiesta per il lavoro batch.

finire

Discuteremo ora il metodo Finish dell'interfaccia Database.Batchable.

Syntax

global void finish(Database.BatchableContext BC) {}

Questo metodo viene chiamato alla fine e puoi completare alcune attività come l'invio di un'e-mail con le informazioni sui record del lavoro batch elaborati e lo stato.

Esempio di apice in batch

Consideriamo un esempio della nostra azienda chimica esistente e supponiamo di avere l'obbligo di aggiornare il campo Stato cliente e Descrizione cliente dei record cliente che sono stati contrassegnati come attivi e che hanno creato la data come oggi. Questa operazione dovrebbe essere eseguita quotidianamente e un'e-mail dovrebbe essere inviata a un utente sullo stato dell'elaborazione batch. Aggiorna lo stato del cliente come "Elaborato" e la descrizione del cliente come "Aggiornato tramite lavoro batch".

// Batch Job for Processing the Records
global class CustomerProessingBatch implements Database.Batchable<sobject> {
   global String [] email = new String[] {'[email protected]'};
   // Add here your email address here
  
   // Start Method
   global Database.Querylocator start (Database.BatchableContext BC) {
      return Database.getQueryLocator('Select id, Name, APEX_Customer_Status__c,
      APEX_Customer_Decscription__c From APEX_Customer__c WHERE createdDate = today
      AND APEX_Active__c = true');
      // Query which will be determine the scope of Records fetching the same
   }
   
   // Execute method
   global void execute (Database.BatchableContext BC, List<sobject> scope) {
      List<apex_customer__c> customerList = new List<apex_customer__c>();
      List<apex_customer__c> updtaedCustomerList = new List<apex_customer__c>();
      
      // List to hold updated customer
      for (sObject objScope: scope) {
         APEX_Customer__c newObjScope = (APEX_Customer__c)objScope ;
         
         // type casting from generic sOject to APEX_Customer__c
         newObjScope.APEX_Customer_Decscription__c = 'Updated Via Batch Job';
         newObjScope.APEX_Customer_Status__c = 'Processed';
         updtaedCustomerList.add(newObjScope); // Add records to the List
         System.debug('Value of UpdatedCustomerList '+updtaedCustomerList);
      }
      
      if (updtaedCustomerList != null && updtaedCustomerList.size()>0) {
         // Check if List is empty or not
         Database.update(updtaedCustomerList); System.debug('List Size '
          + updtaedCustomerList.size());
         // Update the Records
      }
   }
   
   // Finish Method
   global void finish(Database.BatchableContext BC) {
      Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
      
      // Below code will fetch the job Id
      AsyncApexJob a = [Select a.TotalJobItems, a.Status, a.NumberOfErrors,
      a.JobType, a.JobItemsProcessed, a.ExtendedStatus, a.CreatedById,
      a.CompletedDate From AsyncApexJob a WHERE id = :BC.getJobId()];
      
      // get the job Id
      System.debug('$$$ Jobid is'+BC.getJobId());
      
      // below code will send an email to User about the status
      mail.setToAddresses(email);
      mail.setReplyTo('[email protected]'); // Add here your email address
      mail.setSenderDisplayName('Apex Batch Processing Module');
      mail.setSubject('Batch Processing '+a.Status);
      mail.setPlainTextBody('The Batch Apex job processed'
         + a.TotalJobItems+'batches with '+a.NumberOfErrors+'failures'+'Job Item
      processed are'+a.JobItemsProcessed);
      Messaging.sendEmail(new Messaging.Singleemailmessage [] {mail});
   }
}

Per eseguire questo codice, salvarlo prima e poi incollare il codice seguente in Esegui anonimo. Questo creerà l'oggetto della classe e il metodo Database.execute eseguirà il lavoro Batch. Una volta completato il lavoro, verrà inviata un'e-mail all'indirizzo e-mail specificato. Assicurati di avere un record del cliente che haActive come controllato.

// Paste in Developer Console
CustomerProessingBatch objClass = new CustomerProessingBatch();
Database.executeBatch (objClass);

Una volta eseguita questa classe, controlla l'indirizzo email che hai fornito dove riceverai l'email con le informazioni. Inoltre, è possibile controllare lo stato del lavoro batch tramite la pagina Monitoraggio e i passaggi forniti sopra.

Se controlli i registri di debug, puoi trovare la dimensione dell'elenco che indica quanti record sono stati elaborati.

Limitations

Possiamo avere solo 5 elaborazioni batch alla volta. Questo è uno dei limiti di Batch Apex.

Pianificazione del lavoro batch Apex utilizzando la pagina dettagli Apex

Puoi programmare la lezione Apex tramite la pagina dei dettagli Apex come indicato di seguito:

Step 1 - Vai a Configurazione ⇒ Classi Apex, fai clic su Classi Apex.

Step 2 - Fare clic sul pulsante Schedule Apex.

Step 3 - Fornire dettagli.

Pianificazione del lavoro batch Apex utilizzando l'interfaccia pianificabile

È possibile pianificare il lavoro batch Apex utilizzando l'interfaccia pianificabile come indicato di seguito:

// Batch Job for Processing the Records
global class CustomerProessingBatch implements Database.Batchable<sobject> {
   global String [] email = new String[] {'[email protected]'};
   // Add here your email address here
   
   // Start Method
   global Database.Querylocator start (Database.BatchableContext BC) {
      return Database.getQueryLocator('Select id, Name, APEX_Customer_Status__c,
      APEX_Customer_Decscription__c From APEX_Customer__c WHERE createdDate = today
      AND APEX_Active__c = true');
      // Query which will be determine the scope of Records fetching the same
   }
   
   // Execute method
   global void execute (Database.BatchableContext BC, List<sobject> scope) {
      List<apex_customer__c> customerList = new List<apex_customer__c>();
      List<apex_customer__c> updtaedCustomerList = new
      List<apex_customer__c>();//List to hold updated customer
      
      for (sObject objScope: scope) {
         APEX_Customer__c newObjScope = (APEX_Customer__c)objScope ;//type
         casting from generic sOject to APEX_Customer__c
         newObjScope.APEX_Customer_Decscription__c = 'Updated Via Batch Job';
         newObjScope.APEX_Customer_Status__c = 'Processed';
         updtaedCustomerList.add(newObjScope);//Add records to the List
         System.debug('Value of UpdatedCustomerList '+updtaedCustomerList);
      }
      
      if (updtaedCustomerList != null && updtaedCustomerList.size()>0) {
         // Check if List is empty or not
         Database.update(updtaedCustomerList); System.debug('List Size'
            + updtaedCustomerList.size());
         // Update the Records
      }
   }
 
   // Finish Method
   global void finish(Database.BatchableContext BC) {
      Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
      
      // Below code will fetch the job Id
      AsyncApexJob a = [Select a.TotalJobItems, a.Status, a.NumberOfErrors,
      a.JobType, a.JobItemsProcessed, a.ExtendedStatus, a.CreatedById,
      a.CompletedDate From AsyncApexJob a WHERE id = :BC.getJobId()];//get the job Id
      System.debug('$$$ Jobid is'+BC.getJobId());
      
      // below code will send an email to User about the status
      mail.setToAddresses(email);
      mail.setReplyTo('[email protected]');//Add here your email address
      mail.setSenderDisplayName('Apex Batch Processing Module');
      mail.setSubject('Batch Processing '+a.Status);
      mail.setPlainTextBody('The Batch Apex job processed' 
         + a.TotalJobItems+'batches with '+a.NumberOfErrors+'failures'+'Job Item
      processed are'+a.JobItemsProcessed);
      Messaging.sendEmail(new Messaging.Singleemailmessage [] {mail});
   }
   
   // Scheduler Method to scedule the class
   global void execute(SchedulableContext sc) {
      CustomerProessingBatch conInstance = new CustomerProessingBatch();
      database.executebatch(conInstance,100);
   }
}

// Paste in Developer Console
CustomerProessingBatch objClass = new CustomerProcessingBatch();
Database.executeBatch (objClass);

Il debug è una parte importante in qualsiasi sviluppo di programmazione. In Apex, abbiamo alcuni strumenti che possono essere utilizzati per il debug. Uno di questi è il metodo system.debug () che stampa il valore e l'output della variabile nei log di debug.

Possiamo usare i seguenti due strumenti per il debug:

  • Console per gli sviluppatori
  • Log di debug

Debug tramite Developer Console

È possibile utilizzare la console per sviluppatori ed eseguire funzionalità anonime per il debug di Apex come di seguito:

Example

Considera il nostro esempio esistente di recupero dei record dei clienti che sono stati creati oggi. Vogliamo solo sapere se la query restituisce o meno i risultati e, in caso affermativo, controlleremo il valore di List.

Incolla il codice fornito di seguito nella finestra di esecuzione anonima e segui i passaggi che abbiamo fatto per aprire la finestra di esecuzione anonima.

Step 1 - Apri la Console per gli sviluppatori

Step 2 - Apri Execute anonymous da "Debug" come mostrato di seguito.

Step 3 - Apri la finestra Esegui anonimo e incolla il codice seguente e fai clic su Esegui.

// Debugging The Apex
List<apex_customer__c> customerList = new List<apex_customer__c>();
customerList = [SELECT Id, Name FROM APEX_Customer__c WHERE CreatedDate =
today];
// Our Query
System.debug('Records on List are '+customerList+' And Records are '+customerList);
// Debug statement to check the value of List and Size

Step 4 - Apri i registri come mostrato di seguito.

Step 5 - Immettere "USER" nella condizione di filtro come mostrato di seguito.

Step 6 - Apri l'istruzione USER DEBUG come mostrato di seguito.

Debug tramite log di debug

Puoi anche eseguire il debug della stessa classe tramite i log di debug. Supponiamo di avere un trigger nell'oggetto Cliente e deve essere sottoposto a debug per alcuni valori variabili, quindi puoi farlo tramite i log di debug come mostrato di seguito -

Questo è il codice trigger che aggiorna il campo Descrizione se il cliente modificato è attivo e si desidera controllare i valori delle variabili e dei record attualmente nell'ambito -

trigger CustomerTrigger on APEX_Customer__c (before update) {
   List<apex_customer__c> customerList = new List<apex_customer__c>();
   for (APEX_Customer__c objCust: Trigger.new) {
      System.debug('objCust current value is'+objCust);
      
      if (objCust.APEX_Active__c == true) {
         objCust.APEX_Customer_Description__c = 'updated';
         System.debug('The record which has satisfied the condition '+objCust);
      }
   }
}

Seguire i passaggi indicati di seguito per generare i registri di debug.

Step 1- Imposta i log di debug per il tuo utente. Vai a Configurazione e digita "Registro di debug" nella finestra di configurazione della ricerca, quindi fai clic su Collegamento.

Step 2 - Imposta i log di debug come segue.

Step 3- Immettere il nome dell'utente che richiede l'installazione. Inserisci il tuo nome qui.

Step 4 - Modificare i record del cliente quando l'evento dovrebbe verificarsi per generare il registro di debug.

Step 5- Ora vai di nuovo alla sezione dei log di debug. Apri i registri di debug e fai clic su Ripristina.

Step 6 - Fare clic sul collegamento di visualizzazione del primo registro di debug.

Step 7 - Cerca la stringa "USER" utilizzando la ricerca del browser come mostrato di seguito.

L'istruzione di debug mostrerà il valore del campo in cui abbiamo impostato il punto.

Il test è la parte integrante di Apex o di qualsiasi altro sviluppo di applicazioni. In Apex, abbiamo classi di test separate da sviluppare per tutti i test unitari.

Classi di prova

In SFDC, il codice deve avere una copertura di codice del 75% per essere distribuito in produzione. Questa copertura del codice viene eseguita dalle classi di test. Le classi di test sono frammenti di codice che testano la funzionalità di altre classi Apex.

Scriviamo una classe di test per uno dei nostri codici che abbiamo scritto in precedenza. Scriveremo una classe di test per coprire il codice della nostra classe Trigger e Helper. Di seguito è riportato il trigger e la classe di supporto che devono essere coperti.

// Trigger with Helper Class
trigger Customer_After_Insert on APEX_Customer__c (after update) {
   CustomerTriggerHelper.createInvoiceRecords(Trigger.new, trigger.oldMap);
      //Trigger calls the helper class and does not have any code in Trigger
}

// Helper Class:
public class CustomerTriggerHelper {
   public static void createInvoiceRecords (List<apex_customer__c>
      
      customerList, Map<id, apex_customer__c> oldMapCustomer) {
      List<apex_invoice__c> InvoiceList = new List<apex_invoice__c>();
      
      for (APEX_Customer__c objCustomer: customerList) {
         if (objCustomer.APEX_Customer_Status__c == 'Active' &&
            oldMapCustomer.get(objCustomer.id).APEX_Customer_Status__c == 'Inactive') {
            
            // condition to check the old value and new value
            APEX_Invoice__c objInvoice = new APEX_Invoice__c();
            objInvoice.APEX_Status__c = 'Pending';
            objInvoice.APEX_Customer__c = objCustomer.id;
            InvoiceList.add(objInvoice);
         }
      }
      insert InvoiceList;  // DML to insert the Invoice List in SFDC
   }
}

Creazione della classe di test

In questa sezione capiremo come creare una classe di test.

Creazione dei dati

Abbiamo bisogno di creare dati per la classe di test nella nostra stessa classe di test. La classe di test per impostazione predefinita non ha accesso ai dati dell'organizzazione, ma se imposti @isTest (seeAllData = true), avrà accesso anche ai dati dell'organizzazione.

Annotazione @isTest

Utilizzando questa annotazione, hai dichiarato che questa è una classe di test e non verrà conteggiata nel limite di codice totale dell'organizzazione.

parola chiave testMethod

I metodi di unit test sono metodi che non accettano argomenti, non inviano dati al database, non inviano messaggi di posta elettronica e sono dichiarati con la parola chiave testMethod o l'annotazione isTest nella definizione del metodo. Inoltre, i metodi di test devono essere definiti nelle classi di test, ovvero le classi annotate con isTest.

Abbiamo utilizzato il metodo di test "myUnitTest" nei nostri esempi.

Test.startTest () e Test.stopTest ()

Questi sono i metodi di test standard disponibili per le classi di test. Questi metodi contengono l'evento o l'azione per cui simuleremo il nostro test. Come in questo esempio, testeremo la nostra classe di trigger e helper per simulare l'attivazione del fuoco aggiornando i record come abbiamo fatto per avviare e interrompere il blocco. Questo fornisce anche un limite governor separato al codice che si trova nel blocco di avvio e arresto.

System.assert ()

Questo metodo controlla l'output desiderato con l'effettivo. In questo caso, ci aspettiamo che venga inserito un record di fattura, quindi abbiamo aggiunto assert per controllare lo stesso.

Example

/**
* This class contains unit tests for validating the behavior of Apex classes
* and triggers.
*
* Unit tests are class methods that verify whether a particular piece
* of code is working properly. Unit test methods take no arguments,
* commit no data to the database, and are flagged with the testMethod
* keyword in the method definition.
*
* All test methods in an organization are executed whenever Apex code is deployed
* to a production organization to confirm correctness, ensure code
* coverage, and prevent regressions. All Apex classes are
* required to have at least 75% code coverage in order to be deployed
* to a production organization. In addition, all triggers must have some code coverage.
*
* The @isTest class annotation indicates this class only contains test
* methods. Classes defined with the @isTest annotation do not count against
* the organization size limit for all Apex scripts.
*
* See the Apex Language Reference for more information about Testing and Code Coverage.
*/

@isTest
private class CustomerTriggerTestClass {
   static testMethod void myUnitTest() {
      //Create Data for Customer Objet
      APEX_Customer__c objCust = new APEX_Customer__c();
      objCust.Name = 'Test Customer';
      objCust.APEX_Customer_Status__c = 'Inactive';
      insert objCust;
      
      // Now, our trigger will fire on After update event so update the Records
      Test.startTest();    // Starts the scope of test
      objCust.APEX_Customer_Status__c = 'Active';
      update objCust;
      Test.stopTest();     // Ends the scope of test
      
      // Now check if it is giving desired results using system.assert
      // Statement.New invoice should be created
      List<apex_invoice__c> invList = [SELECT Id, APEX_Customer__c FROM
         APEX_Invoice__c WHERE APEX_Customer__c = :objCust.id];
      system.assertEquals(1,invList.size());
      // Check if one record is created in Invoivce sObject
   }
}

Esecuzione della classe di prova

Seguire i passaggi indicati di seguito per eseguire la classe di test:

Step 1 - Vai alle classi Apex ⇒ fai clic sul nome della classe "CustomerTriggerTestClass".

Step 2 - Fare clic sul pulsante Esegui test come mostrato.

Step 3 - Controlla lo stato

Step 4 - Ora controlla la classe e il trigger per cui abbiamo scritto il test

Classe

Trigger

Il nostro test è riuscito e completato.

Che cos'è la distribuzione in SFDC?

Fino ad ora abbiamo sviluppato codice in Developer Edition, ma nello scenario di vita reale, è necessario eseguire questo sviluppo in Sandbox e quindi potrebbe essere necessario distribuirlo a un altro sandbox o ambiente di produzione e questo è chiamato distribuzione. In breve, questo è il movimento dei metadati da un'organizzazione all'altra. Il motivo è che non puoi sviluppare Apex nella tua organizzazione di produzione Salesforce. Gli utenti in tempo reale che accedono al sistema durante lo sviluppo possono destabilizzare i dati o danneggiare l'applicazione.

Strumenti disponibili per la distribuzione -

  • Force.com IDE
  • Set di modifiche
  • API SOAP
  • Strumento di migrazione Force.com

Poiché utilizziamo l'edizione per sviluppatori per i nostri scopi di sviluppo e apprendimento, non possiamo utilizzare il set di modifiche o altri strumenti che richiedono l'edizione aziendale SFDC o un'altra edizione a pagamento. Pertanto, in questo tutorial elaboreremo il metodo di distribuzione IDE Force.com.

Force.com Eclipse IDE

Step 1 - Apri Eclipse e apri il trigger di classe che deve essere distribuito.

Step 2 - Dopo aver fatto clic su "Distribuisci sul server", quindi immettere il nome utente e la password dell'organizzazione in cui è necessario distribuire il componente.

Eseguendo i passaggi sopra menzionati, i componenti Apex verranno distribuiti nell'organizzazione di destinazione.

Distribuzione tramite Change Set

È possibile distribuire regole di convalida, regole del flusso di lavoro, classi Apex e trigger da un'organizzazione all'altra collegandoli tramite le impostazioni di distribuzione. In questo caso, le organizzazioni devono essere collegate.

Per aprire la configurazione della distribuzione, seguire i passaggi indicati di seguito. Ricorda che questa funzione non è disponibile nella Developer Edition -

Step 1 - Vai su Setup e cerca "Deploy".

Step 2 - Fare clic su "Serie di modifiche in uscita" per creare una serie di modifiche da distribuire.

Step 3 - Aggiungi componenti al set di modifiche utilizzando il pulsante "Aggiungi", quindi Salva e fai clic su Carica.

Step 4 - Vai all'organizzazione di destinazione e fai clic sul set di modifiche in entrata e infine fai clic su distribuisci.

Chiamate API SOAP da distribuire

Avremo solo una piccola panoramica di questo metodo poiché non è un metodo comunemente usato.

È possibile utilizzare le chiamate al metodo fornite di seguito per distribuire i metadati.

  • compileAndTest()
  • compileClasses()
  • compileTriggers()

Strumento di migrazione Force.com

Questo strumento viene utilizzato per la distribuzione tramite script. È necessario scaricare lo strumento di migrazione Force.com e quindi eseguire la distribuzione basata su file. È possibile scaricare lo strumento di migrazione Force.com e quindi eseguire la distribuzione tramite script.