2023. 12. 29. 18:40ㆍ카테고리 없음
특징
- 서버인 Lightning Platform에서 저장, 컴파일 및 실행
- 클래스, 인터페이스 및 상속을 지원
- 컴파일 타임에 개체에 대한 참조의 유효성을 검사
- 다중 테넌트 플랫폼에서 실행되므로 코드가 공유 리소스를 독점하는 것을
방지하는 제한을 적용하여 런어웨이 코드를 철저히 보호
* 다중 테넌트 : 여러 고객이 클라우드에서 동일한 애플리케이션과 컴퓨팅 리소스를 공유하는 아키텍처
* 런어웨이 코드 : 제어가 불가능한 상태로 진행되는 프로그램 코드를 의미.
이는 종종 무한 루프, 무한 재귀, 메모리 누수 등으로 인해 발생하며,
프로그램의 제어를 잃어버리게 되어 예상치 못한 동작을 하거나, 시스템 자원을 과도하게 소모하게 됨.
- 레코드 및 해당 필드에 대한 직접 액세스를 제공하고
해당 레코드를 조작하기 위한 문 및 쿼리 언어를 제공 - 데이터베이스에 대한 트랜잭션 액세스를 제공하여 작업을 롤백할 수 있도록 함
- Java 관용구 기반
- 유닛 테스트 생성, 실행 및 코드 검사에 대한 기본 제공 지원을 제공.
Salesforce는 플랫폼 업그레이드 전에 모든 유닛 테스트를 실행하여
모든 사용자 정의 Apex 코드가 예상대로 작동하는지 확인 가능 - 사용자 정의 Apex 코드는 API의 다른 버전에 대해 저장할 수 있습니다.
다른 객체 지향 프로그래밍 언어와 달리 Apex는 다음을 지원합니다.
- Apex로서의 클라우드 개발은 클라우드에서 저장, 컴파일 및 실행됨.
- 데이터베이스 시스템의 트리거와 유사한 트리거.
- 데이터를 쿼리하고 검색하기 위해 직접 데이터베이스 호출 및 쿼리 언어를 만들 수 있는 Database 문.
- 트랜잭션 및 롤백.
- public 수정자보다 권한이 더 있는 global 액세스 수정자로,
네임스페이스와 애플리케이션 전반에 걸쳐 액세스를 허용함. - 사용자 정의 코드의 버전 관리.
- 또한 Apex는 대소문자를 구분하지 않는 언어
Apex의 목록은 배열과 동의어이며 두 가지를 서로 바꿔서 사용할 수 있습니다.
다음 두 선언은 동일합니다.
List<String> colors = new List<String>();
String[] colors = new List<String>();
두 가지 방식으로 요소 추가 가능
// Create a list and add elements to it in one step
List<String> colors = new List<String> { 'red', 'green', 'blue' };
// Add elements to a list after it has been created
List<String> moreColors = new List<String>();
moreColors.add('orange');
moreColors.add('purple');
두 가지 방식으로 요소 가져오기 가능
String color1 = moreColors.get(0);
String color2 = moreColors[0];
sObject 사용하기
Salesforce의 모든 레코드는 기본적으로 Apex에서 sObject로 표시됩니다
예를 들어 Acme 계정 레코드는 Apex의 계정 sObject에 해당합니다. 사용자 인터페이스에서 보고 수정할 수 있는 Acme 레코드의 필드는 sObject에서도 직접 읽고 수정할 수 있습니다.
테이블 1. 검색된 레코드에 대한 계정 sObject계정 필드값
| Id | 001D000000JlfXe |
| 이름 | Acme |
| 전화 | (415)555-1212 |
| 직원 수 | 100 |
각 Salesforce 레코드는 Salesforce에 삽입되기 전에 sObject로 표시됩니다.
다음은 표준 개체에 사용되는 Apex의 몇 가지 일반적인 sObject 유형 이름입니다.
- 계정
- 연락처
- 리드
- 기회
1. sObject 변수 생성
Acme라는 이름의 계정 유형 sObject를 만들고 이를 acct 변수에 할당합니다.
Account acct = new Account(Name='Acme');
2. sObject 및 필드 이름
Apex는 고유한 API 이름을 사용하여 표준 또는 사용자 정의 sObject와 해당 필드를 참조합니다.
개체 및 필드의 API 이름은 레이블과 다를 수 있습니다
예를 들어 직원 필드에는 직원이라는 레이블이 있고 계정 레코드 페이지에 직원으로 표시되지만
해당 API 이름은 NumberOfEmployees입니다.
Apex에서 이 필드에 액세스 하려면 필드의 API 이름인 NumberOfEmployees를 사용해야 합니다.
맞춤형 객체 및 사용자 정의 필드의 API 이름에 사용되는 규칙
- 맞춤형 객체 및 사용자 정의 필드의 경우 API 이름은 항상 __c 접미사로 끝납니다.
- 사용자 정의 관계 필드의 경우 API 이름은 __r 접미사로 끝납니다.
- Merchandise라는 레이블이 있는 맞춤형 객체의 API 이름은 Merchandise__c입니다.
- 레이블이 설명인 사용자 정의 필드에는 API 이름이 Description__c입니다.
- 항목 레이블이 있는 사용자 정의 관계 필드의 API 이름은 Items__r입니다.
3. 개체 및 필드 이름 찾기
etup(설정)에서 Home(홈) 탭의 오른쪽에 있는 Object Manager(개체 관리자) 탭을 클릭한 후
개체 이름을 클릭합니다.
4. sObject 생성 및 필드 추가
Salesforce 레코드를 삽입하기 전에 먼저 메모리에 sObject로 생성해야 합니다. 다른 개체와 마찬가지로 sObject는 new 연산자와 함께 생성됩니다.
Account acct = new Account();
아직 필드를 채우지 않았으므로 acct 변수에서 참조한 계정이 비어 있습니다.
필드를 추가하는 방법에는 생성자를 통하거나 점 표기법을 사용하는 두 가지 방법이 있습니다.
필드를 추가하는 가장 빠른 방법은 생성자 내에서 이름-값 쌍으로 필드를 지정하는 것입니다
Account acct = new Account(Name='Acme');
이름 필드는 계정의 유일한 필수 필드이므로 새 레코드를 삽입하려면 먼저 채워야 합니다. 그러나 새 레코드에 대해 다른 필드도 채울 수 있습니다
Account acct = new Account(Name='Acme', Phone='(415)555-1212', NumberOfEmployees=100);
또는 점 표기법을 사용하여 sObject에 필드를 추가할 수 있습니다.
Account acct = new Account();
acct.Name = 'Acme';
acct.Phone = '(415)555-1212';
acct.NumberOfEmployees = 100;
일반 sObject 데이터 유형 작업하기
일반적으로 sObject로 작업할 때 표준 개체의 계정 또는
Book이라는 맞춤형 객체의 Book__c와 같은 특정 sObject 데이터 유형을 사용합니다.
그러나 메서드가 처리하는 sObject의 유형을 모르는 경우
일반 sObject 데이터 유형을 사용할 수 있습니다.
일반 sObject 데이터 유형으로 선언된 변수는 표준 또는 맞춤형 객체 레코드에 관계없이
모든 Salesforce 레코드를 참조할 수 있습니다.

sObject sobj1 = new Account(Name='Trailhead');
sObject sobj2 = new Book__c(Name='Workbook 1');
특정 sObject 데이터 유형으로 선언된 변수는
동일한 유형의 Salesforce 레코드만 참조할 수 있습니다.

1. 일반 sObject를 특정 sObject 유형으로 캐스트
이렇게 하는 이점 중 하나는 점 표기법을 사용하여 필드에 액세스 할 수 있다는 것입니다
sObject는 모든 특정 sObject 유형의 상위 유형이므로
일반 sObject를 특정 sObject로 캐스트할 수 있습니다.
// Cast a generic sObject to an Account
Account acct = (Account)myGenericSObject;
// Now, you can use the dot notation to access fields on Account
String name = acct.Name;
String phone = acct.Phone;
일반 sObject의 필드는 put() 및 get() 메서드를 통해서만 액세스할 수 있습니다.
DML로 레코드 조작하기
Data Manipulation Language(약칭 DML)를 사용하여
Salesforce에서 레코드를 만들고 수정합니다.
DML은 레코드를 삽입, 업데이트, 병합, 삭제 및 복원하는 간단한 명령문을 제공하여
레코드를 관리하는 간단한 방법을 제공합니다.
Apex는 데이터 중심 언어이고 Lightning Platform에 저장되기 때문에
Salesforce의 데이터에 직접 액세스 할 수 있습니다.
데이터 소스에 연결하기 위해 추가 설정이 필요한 다른 프로그래밍 언어와 달리
Apex DML을 사용하면 레코드 관리가 간편해집니다.
// Create the account sObject
Account acct = new Account(Name='Acme', Phone='(415)555-1212', NumberOfEmployees=100);
// Insert the account by using DML
insert acct;
1. DML 문
각 DML 문은 단일 sObject 또는 sObject 목록(또는 배열)을 허용합니다
몇 가지를 제외한 모든 문은 친숙한 데이터베이스 작업입니다.
upsert 및 merge 문은 Salesforce에만 해당되며 매우 편리할 수 있습니다.
- upsert DML 작업 은 단일 문 내에서 새 레코드를 만들고 지정된 필드를 사용하여
기존 개체의 존재 여부를 확인하거나 필드가 지정되지 않은 경우 ID 필드를 사용하여
sObject 레코드를 업데이트합니다. - merge 문은 동일한 sObject 유형의 레코드를 최대 3개까지 레코드 중 하나로 병합하고
다른 레코드를 삭제하고 관련 레코드를 다시 상위 항목으로 지정합니다.
2. 새 레코드에 자동 할당된 ID 필드
레코드를 삽입할 때 시스템은 각 레코드에 ID를 할당합니다.
데이터베이스에서 ID 값을 유지하는 것 외에도
ID 값은 DML 호출에서 인수로 사용한 sObject 변수에도 자동으로 채워집니다.
sObject에서 ID를 가져오는 방법
// Create the account sObject
Account acct = new Account(Name='Acme', Phone='(415)555-1212', NumberOfEmployees=100);
// Insert the account by using DML
insert acct;
// Get the new ID on the inserted sObject argument
ID acctID = acct.Id;
// Display this ID in the debug log
System.debug('ID = ' + acctID);
// Debug log result (the ID will be different in your case)
// DEBUG|ID = 001D000000JmKkeIAF
3. 대량 DML
단일 sObject 또는 sObject 목록에서 대량으로 DML 작업을 수행할 수 있습니다.
대량 DML 작업을 수행하는 것은 Apex 트랜잭당 150개의 문으로 된
DML 제한과 같은 거버너 제한에 도달하는 것을 방지하는 데 도움이 되므로 권장되는 방법입니다.
sObject 목록에서 DML 작업을 수행하는 것은
각 sObject에 대한 단일 문이 아니라 하나의 DML 문으로 계산됩니다.
하나의 호출에 연락처 목록을 삽입하여 연락처를 대량으로 삽입합니다. 그런 다음 샘플은 해당 연락처도 대량으로 업데이트합니다.
// Create a list of contacts
List<Contact> conList = new List<Contact> {
new Contact(FirstName='Joe',LastName='Smith',Department='Finance'),
new Contact(FirstName='Kathy',LastName='Smith',Department='Technology'),
new Contact(FirstName='Caroline',LastName='Roth',Department='Finance'),
new Contact(FirstName='Kim',LastName='Shain',Department='Education')};
// Bulk insert all contacts with one DML call
insert conList;
// List to hold the new contacts to update
List<Contact> listToUpdate = new List<Contact>();
// Iterate through the list and add a title only
// if the department is Finance
for(Contact con : conList) {
if (con.Department == 'Finance') {
con.Title = 'Financial analyst';
// Add updated contact sObject to the list.
listToUpdate.add(con);
}
}
// Bulk update all contacts with one DML call
update listToUpdate;
4. 레코드 Upsert
새 레코드와 기존 레코드가 혼합된 목록이 있는 경우 upsert 문을 사용하여
목록의 모든 레코드에 대한 삽입 및 업데이트를 처리할 수 있습니다.
Upsert는 중복 레코드 생성을 방지하고
어떤 레코드가 먼저 존재하는지 결정할 필요가 없으므로 시간을 절약할 수 있습니다.
upsert 문은 한 필드의 값을 비교하여 sObject를 기존 레코드와 일치시킵니다.
이 문을 호출할 때 필드를 지정하지 않을 경우
upsert 문은 sObject의 ID를 사용하여 sObject를 Salesforce의 기존 레코드와 일치시킵니다.
또는 일치에 사용할 필드를 지정할 수 있습니다.
사용자 정의 개체의 경우 외부 ID로 표시된 사용자 정의 필드를 지정합니다.
표준 개체의 경우 idLookup 속성이 true로 설정된 모든 필드를 지정할 수 있습니다.
예를 들어 연락처 또는 사용자의 이메일 필드에는 idLookup 속성 집합이 있습니다.
upsert sObject | sObject[]
upsert sObject | sObject[] field //field는 선택적
MyExternalID 필드를 지정하는 문은 다음과 같습니다.
upsert sObjectList Account.Fields.MyExternalId;
upsert는 sObject 레코드의 기본 키(ID), idLookup 필드 또는 외부 ID 필드를 사용하여
새 레코드를 생성해야 하는지 아니면 기존 레코드를 업데이트해야 하는지를 결정합니다.
- 키가 일치하지 않으면 새 개체 레코드가 생성됩니다.
- 키가 한 번 일치하면 기존 개체 레코드가 업데이트됩니다.
- 키가 여러 번 일치하면 오류가 발생되고 개체 레코드가 삽입되거나 업데이트되지 않습니다.
이 예에서는 upsert가 기존 연락처 레코드를 업데이트하고 한 통화에 새 연락처를 삽입하는 방법을 보여줍니다. 이 upsert 호출은 기존 Josh 연락처를 업데이트하고 새 연락처 Kathy를 삽입합니다.
// Insert the Josh contact
Contact josh = new Contact(FirstName='Josh',LastName='Kaplan',Department='Finance');
insert josh;
// Josh's record has been inserted
// so the variable josh has now an ID
// which will be used to match the records by upsert
josh.Description = 'Josh\'s record has been updated by the upsert operation.';
// Create the Kathy contact, but don't persist it in the database
Contact kathy = new Contact(FirstName='Kathy',LastName='Brown',Department='Technology');
// List to hold the new contacts to upsert
List<Contact> contacts = new List<Contact> { josh, kathy };
// Call upsert
upsert contacts;
// Result: Josh is updated and Kathy is created.
upsert 작업이 새 연락처 레코드를 만드는 대신 기존 레코드를 찾아 업데이트했으므로
조직에는 두 개가 아닌 하나의 Josh Kaplan 레코드만 있습니다.
Kathy Brown 연락처 레코드 한 개도 있을 것입니다.

또는 일치하는 레코드에 사용할 필드를 지정할 수 있습니다.
이 예에서는 idLookup 속성 집합을 가지므로 연락처의 이메일 필드를 사용합니다.
이 예에서는 Jane Smith 연락처를 삽입하고
두 번째 연락처 sObject를 만들고 동일한 이메일로 채운 다음
upsert를 호출하여 일치를 위해 이메일 필드를 사용하여 연락처를 업데이트합니다.
Contact jane = new Contact(FirstName='Jane',
LastName='Smith',
Email='jane.smith@example.com',
Description='Contact of the day');
insert jane;
// 1. Upsert using an idLookup field
// Create a second sObject variable.
// This variable doesn’t have any ID set.
Contact jane2 = new Contact(FirstName='Jane',
LastName='Smith',
Email='jane.smith@example.com',
Description='Prefers to be contacted by email.');
// Upsert the contact by using the idLookup field for matching.
upsert jane2 Contact.fields.Email;
// Verify that the contact has been updated
System.assertEquals('Prefers to be contacted by email.',
[SELECT Description FROM Contact WHERE Id=:jane.Id].Description);
조직에는 업데이트된 설명이 포함된 Jane Smith 연락처가 하나만 있습니다.

