https://trailhead.salesforce.com/ko/content/learn/modules/apex_database/apex_database_dml
Manipulate Records with DML
과제
YOUR CHALLENGE
Create a method for inserting accounts.
To pass this challenge, create an Apex class that inserts a new account named after an incoming parameter. If the account is successfully inserted, the method should return the account record. If a DML exception occurs, the method should return null.
- The Apex class must be called AccountHandler and be in the public scope
- The Apex class must have a public static method called insertNewAccount
public class AccountHandler { //called AccountHandler and be in the public scope
// public static method called insertNewAccount
//string as a parameter, which will be used to create the Account name
public static Account insertNewAccount(String AccountName){
//insert the account into the system and then return the record
try {
Account acct = new Account(Name=AccountName);
insert acct;
return acct;
} catch (DmlException e) { //catch the failed DML and then return null
System.debug('A DML exception has occurred: ' + e.getMessage());
return null;
}
}
}
AccountHandler.insertNewAccount('TestAccount');
---
Data Manipulation Language (DML)
DML로 레코드조작하기
DML문
- insert
- update
- upsert
- delete
- undelete
- merge
ID Field Auto-Assigned to New Records
// 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
Bulk DML
여러 개 만들어놓고 그냥 한번의 DML문으로 한번에 다 가능
//conList 생성
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')};
insert conList; //한번의 Insert로 대량 레코드 삽입이 가능
// 업데이트할 새연락처를 보유할 listToUpdate
List<Contact> listToUpdate = new List<Contact>();
//conList 목록을 반복하고
for(Contact con : conList) {
if (con.Department == 'Finance') { //만약 부서이름이 '재무'라면?
con.Title = 'Financial analyst'; //'Financial analyst'로 제목 바꿔주기
listToUpdate.add(con);
}
}
update listToUpdate; //마찬가지로 한번으로 업데이트 가능
Upsert Records
Upsert helps avoid the creation of duplicate records and can save you time as you don’t have to determine which records exist first.
-> 필드의 값을 비교해 기존 sObject를 기존 레코드와 일치시킴.
Upsert Syntax
upsert sObject | sObject[]
upsert sObject | sObject[] field
For example, to specify the MyExternalID field, the statement is:
upsert sObjectList Account.Fields.MyExternalId;
upsert는 레코드 기본키(ID), idLookup필드 또는 외부 ID필드를 사용해 새 레코드를 생성해야하는지 아니면 기존 레코드를 업데이트 해야하는지 결정
- If the key is not matched, a new object record is created.
- If the key is matched once, the existing object record is updated.
- If the key is matched multiple times, an error is generated and the object record is neither inserted or updated.
how upsert updates an existing contact record and inserts a new contact in one call
// Josh의 Contact 삽입
Contact josh = new Contact(FirstName='Josh',LastName='Kaplan',Department='Finance');
insert josh;
//변수 josh는 이제 upsert에 의해 레코드를 일치시키는 데 사용될 ID를 갖습니다.
josh.Description = 'Josh\'s record has been updated by the upsert operation.';
// Kathy contact 생성
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 };
//여기서 upsert 호출해주면
upsert contacts;
// Result: Josh 는 업데이트! Kathy는 생성!
결국 조직에는 Josh연락처는 한 개만 존재! 마찬가지로 케이시 연락처 레코드 한개있다
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.');
// 일치를 위해 idLookup 필드를 사용하여 연락처를 Upsert합니다.
// 이메일이 같으니 이걸로 연결해서 upsert!
// 여기서 Insert를 하면 중복된 계정이 2개가 생겨버림!
upsert jane2 Contact.fields.Email;
System.assertEquals('Prefers to be contacted by email.',
[SELECT Description FROM Contact WHERE Id=:jane.Id].Description);
Jane Smith 연락처가 하나만 있습니다
질문!
그러면 Jane2 계정은 사라지고 Jane 레코드만 업데이트 되는건지
만약 이름이 다르면 어느계정 것이 더 우선이 되는지?
먼저 Insert한 순???
-> 이거 그냥 새로운 정보만 추가 업데이트 하는 것임!!!
Delete Records
바로 삭제되는건 아니고 15일동안 휴지통에서 보관!
Delete all contacts whose last name is Smith.
Contact[] contactsDel = [SELECT Id FROM Contact WHERE LastName='Smith'];
delete contactsDel;
DML Statement Exceptions
예외처리는 언제나 중요하다!
DmlException 방지
try {
Account acct = new Account();
insert acct;
} catch (DmlException e) {
System.debug('A DML exception has occurred: ' +
e.getMessage());
}
Database Methods
Database methods are static and are called on the class name.
- Database.insert()
- Database.update()
- Database.upsert()
- Database.delete()
- Database.undelete()
- Database.merge()
Unlike DML statements, Database methods have an optional allOrNone parameter
디폴트값이 ture
Database.insert(recordList);
Database.insert(recordList, true);
false일때만 insert 메서드 호출!
Database.insert(recordList, false);
삽입하기
Database.SaveResult[] results = Database.insert(recordList, false);
Example: Insert Records with Partial Success
의도적으로 필드가 없고, LastName 필드 없이 연락처를 저장할 수 없음@@
// 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()};
// Bulk insert all contacts with one DML call
Database.SaveResult[] srList = Database.insert(conList, false);
// Iterate through each returned result
for (Database.SaveResult sr : srList) {
if (sr.isSuccess()) { //성공이면 ID값 반환
System.debug('Successfully inserted contact. Contact ID: ' + sr.getId());
} else {
// 아니면 에러 가져오기
for(Database.Error err : sr.getErrors()) {
System.debug('The following error has occurred.');
System.debug(err.getStatusCode() + ': ' + err.getMessage());
System.debug('Contact fields that affected this error: ' + err.getFields());
}
}
}
Debug 결과
3개는 insert가 되었지만 하나는 Last Name 없다고 오류가 뜸!!
DML VS Database Method
DML : Apex 예외처리 원할 때
Database Method : 부분적인 성공을 허용하고 싶을 때,
Work with Related Records
Insert Related Records
You can insert records related to existing records if a relationship has already been defined between the two objects, such as a lookup or master-detail relationship.
AccountId 필드를 설정하여 계정(관련 레코드)에 연락처를 추가하는 방법
//새 계정 SFDC Account 생성
Account acct = new Account(Name='SFDC Account');
insert acct;
ID acctID = acct.ID;
// Add a contact to this account.
Contact mario = new Contact(
FirstName='Mario',
LastName='Ruiz',
Phone='415.555.1212',
AccountId=acctID);
insert mario;
è 새 계정(SFDC 계정)을 만들었으며 계정의 연락처 관련 목록에 Mario Ruiz 연락처가 있습니다
Update Related Records
관련 레코드의 필드는 DML 작업에 대한 동일한 호출로 업데이트 할 수 없으며 별도의 DML 호출이 필요함!!
// 거래처와 연결된 연락처를 쿼리로
Contact queriedContact = [SELECT Account.Name
FROM Contact
WHERE FirstName = 'Mario' AND LastName='Ruiz'
LIMIT 1]; // Limit 숫자1만큼 행출력
// Update the contact's phone number
queriedContact.Phone = '(415)555-1213';
// Update the related account industry
queriedContact.Account.Industry = 'Technologys';
// Make two separate call
// 1. This call is to update the contact's phone.
update queriedContact;
// 2. This call is to update the related account's Industry field.
update queriedContact.Account;
즉 계정 자체를 업데이트하지 않고는 계정 이름 변경 불가!
연락처를 업데이트 ->연락처의 관련된 계정도 업데이트 -> DML 호출 두 번!
LIMIT 숫자 : 출력할 행의 수
OFFSET 숫자 : 몇번째 row부터 출력할 지. (1번째 row면 0)
Delete Related Records
Account[] queriedAccounts = [SELECT Id FROM Account WHERE Name='SFDC Account'];
delete queriedAccounts;
상위 개체를 삭제하면 자동으로 하위개체도 다 삭제된다.
---