Apex Code

오픈소스 비즈니스 컨설팅
Pnuskgh (토론 | 기여)님의 2018년 2월 12일 (월) 10:54 판
(차이) ← 이전 판 | 최신판 (차이) | 다음 판 → (차이)
둘러보기로 가기 검색하러 가기

Force.com중 Apex Code를 정리 합니다.

Apex Code 문법

변수 타입

String
  • 문자열
  • 선언
  • String item = new String();
  • String item = '~';
  • 제공 함수
  • Integer length()
  • Boolean equals(String), Boolean equalsIgnoreCase(String), Integer compareTo(String)
  • Boolean startsWith(String), Boolean contains(String), Boolean endsWith(String)
  • Integer indexOf(String), Integer indexOf(String, Integer), Integer lastIndexOf(String)
  • String trim()
  • String replace(String, String), String replaceAll(String, String), String replaceFirst(String, String)
  • String substring(Integer), String substring(Integer, Integer)
  • List<String> split(String), List<String> split(String, Integer)
  • String toLowerCase(), String toLowerCase(String)
  • String toUpperCase(), String toUpperCase(String)
  • void addError(APEX_OBJECT 또는 String)

  • 변환
  • Integer
  • Integer tmpInteger = Integer.valueOf(tmpStr);
  • String tmpStr = String.valufOf(tmpInteger);
  • Boolean
  • Boolean tmpBoolean = (tmpStr == 'true') ? true:false;
  • String tmpStr = (tmpBoolean) ? 'true':'false';
  • Date
  • Date tmpDate = Date.valufOf(tmpStr + ' 00:00:00');
  • tmpStr : yyyy-MM-dd
  • String tmpStr = tmpDate.year() + '-' + tmpDate.month() + '-' + tmpDate.day();
  • Datetime
  • Datetime tmpDatetime = Date.valufOf(tmpStr);
  • tmpStr : yyyy-MM-dd HH:mm:ss
  • String tmpStr = tmpDatetime.year() + '-' + tmpDatetime.month() + '-' + tmpDatetime.day() + ' ' + tmpDatetime.hour() + ':' + tmpDatetime.minute() + ':' + tmpDatetime.second();
  • Blob
  • Blob tmpBlob = Blob.valueOf(tmpStr);
  • String tmpStr = tmpBlob.toString();
배열
  • 선언
  • String[] data = new String[3];
  • String[] data = new String[3] {val1, val2, val3};
  • String[] data = new List<String>();
  • String[] data = new List<String>(다른_List);
  • 제공 함수
  • Integer size()
  • 사용법
  • data[0], data[1], data[2], ...
  • 변환
  • String[] = List<String>;
Integer, Long
  • Integer : 32-bits 정수, Long : 64-bits 정수
  • Integer = Integer.valueOf(String)
  • Long long = ~L;
Decimal, Double
  • Decimal : 32-bits 실수, Double : 64-bits 실수
Boolean
  • Boolean : true, false, null
Date, Datetime
  • Date : 날자, Datetime : 날자 + 시간
  • Date baseDate = Date.parse('2011. 12. 5');
  • Date var20111101 = baseDate.addMonths(-1).toStartOfMonth();
  • Date var20111130 = baseDate.toStartOfMonth().addDays(-1);
ID
  • ID : 18 문자의 레코드 아이디
Object
sObject
  • 개체
  • 선언
  • Account item = new Account();
  • Account item = new Account(name1 = 'value1', name2 = 'value2');
  • Account[] data = [Query_문];
  • Account[] data = Database.query('Query_문');
  • 사용
  • item.~ : Field 값
  • item.getSObjectType() == Account.sObjectType : 'Account'라는 object type을 반환
Blob
this
List
  • 선언
  • List<type> data = new List<type>();
  • List<type> data = new List<type> {val1, val2, val3};
  • List<type> data = new type[0];
  • List<type> data = new type[] {val1, val2, val3};
  • List<type> data = new List<type>(다른_List);
  • 제공 함수
  • get(0), set(0, ~), clear();
  • add(~), remove(0), size(), isEmpty()
Set
  • 선언
  • Set<type> data = new Set<type>();
  • Set<type> data = new Set<type> {val1, val2, val3};
  • Set<type> data = new Set<type>(다른_Set);
  • 제공 함수
  • clear(), isEmpty(), size()
  • add(data), contains(data), remove(data)
Map
  • 선언
  • Map<keyType, valueType> name = new Set<keyType, valueType>();
  • Map<keyType, valueType> name = new Set<keyType, valueType> {key1 => val1, key2 => val2};
  • Map<ID, Contact> m = new Map<ID, Contact>([select id, lastname from contact]);
  • 제공 함수
  • containsKey(key), keySet(), values(), clear(), isEmpty()
  • get(key), put(key, value), remove(key)
Enums
  • 선언
  • public enum Season {WINTER, SPRING, SUMMER, FALL}
  • 사용법
  • Season e = Season.WINTER;
  • 제공 함수
  • name(), ordinal(), values()
  • System-defined enums
  • System.StatusCode, System.XmlTag, System.LoggingLevel, System.RoundingMode
  • System.SoapType, System.DisplayType, ApexPages.Severity, Dom.XmlNodeType
  • Primitive Data Types
Boolean     : true, false
Date
Datetime
Double
ID          : 18 Character Apex record identifier
Integer
String
배열        : [] 로 표시
  • SObject Type, SObject Fields
  • Lists
List<String> zzStr = new List<String>();
zzStr.set(0, "tmpStr");
zzStr.get(0);
zzStr.clear();
  • Sets
Set<String> zzStr = new Set<String>();
zzStr.add("tmpStr");
zzStr.remove(1);
  • Maps
Map<String, String> zzStr = new Map<String, String>();
zzStr.put("zzName", "zzValue");
zzStr.get("zzName");
  • Not Support DML Statements
User, Profile, Territory, RecordType, Transaction,
WebLink, BusinessHours, BusinessProcess, CategoryNode, Process
  • UserInfo
  • Currency
  • Integer, Double, Boolean, String, Datetime, Date, Math
  • List, Set, Map, SObject, Exception

Data 지정 방법

  • POJO (Plan Old Java Object)
  • obj.name
  • obj['name']
  • obj.getName(), obj.setName(value)
  • obj.get('name'), obj.set('name', value)
  • obj.name[0]

제어문

if (~) {
} else {
}

Loops

  • continue, break
do {
    statement;
    break;
    continue;
} while (Boolean_condition);

while (Boolean_condition) {
    statement;
}

for (initialization; Boolean_exit_condition; increment) {
    statement;
}

for (variable : array_or_set) {
    statement;
}

for (variable : [inline_soql_query]) {
    statement;
}

Exception

   try {
       throw ~;
   } catch (Exception ex) {
       //---   System.ArrayException, DmlException, MathException, NullPointerException
       //---   QueryException, StringException, TypeException
   } finally {
   }


Control - Class

Class 정의

  • "설정 -> App 설정 -> 개발 -> Apex 클래스" 메뉴
public | private | global
    [virtual | abstract | with sharing | without sharing]  class | interface  ClassName
    [implements InterfaceNameList]  [extends ClassName] {
    [public | private | protected | global]   [static]   [final]   String   var = value;
    [public | private | protected | global]   [override]   [static]   String   func()  { }
}
  • with sharing
  • <- user’s permissions, field-level security, sharing rules
  • 소유자 (사용자)
  • 역할
  • 공유 설정
  • 프로필
  • Field Level Security
  • Transient String name; //--- view state에 저장되지 않음

Class001.png

Class 상속

  • virtual -> extend or override, abstract -> override
  • this, super
public virtual class Parent {
    public virtual String getStrParent() {
        return ‘Parent String’; 
    } 
}

public class Child extends Parent {
    public Child() {
        super();
    }

    public override String getStrParent() {
        return super.getStrParent() + ‘ : Child String’;
    } 
}
public virtual class Parent {
    public String strParent = null;

    public Parent() {
    }

    public void Func01() {
    }

    public String getStrParent() {
        return strParent;
    }
}

public class Child extends Parent {
    public Child() {
         super();     //--- Parent의 생성자를 호출 합니다.
         //--- TODO : 여기에 코딩
    }

    //--- Parent의 Method를 재설정 합니다.
    public override void Func01() {
        getStrParent();
    }
}
  • Interface 상속
public virtual interface Parent {
}

public interface Child extends Parent {
}
  • 상속 확인
  • A instanceof B

Apex Properties

  • Apex Properties 정의
[public | private | protected | global]   [static, virtual, abstract, overrid]   
    String   var { [public | private | protected] get; [~] set;}
  • Apex Properties
  • set 함수에서 value는 System이 생성하여 전달하는 인수값 입니다.
public class BasicClass {
    public  String  varName {
        get {
            return varName;
        }
        set {
            name = value;
        }
    }
}

Parameterized Interface

public virtual interface Pair<T, U> {
    public T getFirest();
    public void setFirst(T val);
}

public StringPair implements Pair<String, String> {
}

Annotations

  • @deprecated :
  • @future : 비동기적으로 실행되는 Method, 200 호출 / user, 24시간
  • @isTest : 테스트 클래스 표시
  • @ReadOnly : in Web services, Schedulable interface
  • @RemoteAction : JavaScript에서 함수 호출

내장 변수

  • {!$ObjectType.Account} === Schema.SObjectType.Account.getKeyPrefix()
  • {!$ObjectType.Account.fields.Name.label}
  • Object, sObject
  • NS__Object__c, NS__Field__c / NS.Class.Method()
  • Iterable, Iterators -> Database.batchable

Control - Testing Apex

Apex Code로 프로그램을 작성하면 이를 배포하기 위해서는 전체 코딩된 라인중 75% 이상이 테스트 되어야 합니다. (Code Coverage Result가 75% 이상) Force.com에서 제안하는 테스트 방식을 살펴보면 해당 코드가 한번 이상 수행이 되면 테스트가 된 것으로 처리를 하고 있습니다. 따라서 Code Coverage Result를 높이기만을 원한다면 다양한 테스트 코드를 작성할 필요는 없고 각각의 라인이 한번 이상 실행이 되도록 테스트 코드를 작성하면 됩니다.

  • Code Coverage Result를 높이는 방법
  1. 분기문, 제어문 등에서 각각의 코드 블럭이 실행될 수 있도록 데이터를 구성 합니다. (추천)
  2. 테스트가 완료된 코드 블럭에 의미없는 코드를 추가하여 라인수를 늘입니다. (비추천)

Test Class 사례

  • ClassName 클래스를 테스트하기 위한 Test 클래스 샘플
  • ClassName의 모든 라인이 수행될 수 있도록 Test 클래스를 작성하여야 함
  • 배포 등을 위해서는 전체 라인중 75%가 테스트(Code Coverage Result)가 되어야 함
@IsTest
private class ClassNameTest {
   private static testMethod void testMain() {
       ClassName test = null;
       
       //--- Test를 위한 사용자 설정
       User user = [select id from User where alias='auser'];
       System.RunAs(u1) {
           //--- Test를 위한 데이터 설정
           manage = new Manage();
   
           //--- Test 코드 작성
           test = new ClassName();
           test.setManage(manage);
           
           System.assert(actual==expected, 'Character.isAscii(\ + charactr + '\') returned ' + actual);
           System.assertEquals(singletotalMiles,  totalMiles);

           Test.startTest();     //--- Limits를 초기화하고 테스트 시작
           ~
           Test.stopTest();
       }
   }
}
  • Apex Batch 테스트 프로그램
@IsTest
private class BatEvaluationTest {
   private static testmethod void testMain() {
       BatEvaluation test = null;
       List<Evaluation__c> scope = null;
       
       Test.StartTest();
       //--- Apex Batch에 전달할 scope 데이터 생성
       scope = new List<Evaluation__c>();
       scope.add(new Evaluation__c());
       
       //--- Apex Batch의 각 Method를 별도로 실행
       test = new BatEvaluation();
       test.start(null);
       test.execute(null, scope);
       test.finish(null);
       Test.stopTest();
   }
}

System.assert

  • System.assert(boolean) : boolean 값이 true이면 OK
  • System.assert(boolean, e.getMessage()) : boolean 값이 true이면 OK, boolean 값이 false이면 두번째 인자를 메시지로 표시
  • System.assertEquals(dataA, dataB [, msg]) : dataA와 dataB의 값이 동일하면 OK
  • System.assertNotEquals(dataA, dataB [, msg]) : dataA와 dataB의 값이 다르면 OK
  • System.assert(Boolean[, ExceptionMessage]);
System.assert(false);
System.assert('a' == 'A');
  • System.assertEquals(expectedValue, actualValue[, ExceptionMessage]);
System.assertEquals('Hello to you!', sayHelloWorld('to you!'));
  • System.assertNotEquals(expectedValue, actualValue[, ExceptionMessage]);

Test 실행 방법

  • "설정 -> App 설정 -> 개발 -> Apex 클래스 -> 모든 테스트 실행"에서 테스트
  • "설정 -> App 설정 -> 개발 -> Apex 테스트 실행"에서 테스트
  • Eclipse에서 Class에서 오른쪽 마우스를 눌러 "Force.com -> Run Tests" 메뉴를 실행 합니다.

Control - Trigger

Trigger 개요

  • Trigger 종류
  • insert : before/after insert
  • update : before/after update
  • delete : before/after delete
  • upsert : before/after insert/update
  • merge : before/after delete, before update
  • undelete : after undelete (Account, Asset, Campaign, Case, Contract, Custom objects, Event, Lead, Opportunity, Product, Solution, Task)
  • Trigger 적용 예외
  • Cascading delete, Mass ~, …
  • Opportunity : amoutn, ForecastCategory, isWon, …
  • 트리거 메뉴
  • "설정 -> App 설정 -> 사용자 정의 -> '개체' -> 트리거" 메뉴
  • "설정 -> App 설정 -> 작성 -> 개체 -> 트리거 '새로 만들기'"
  • Trigger 변수
  • Trigger.old, Trigger.new, Trigger.oldMap, Trigger.newMap, Trigger.size
  • Trigger
  • isBefore, isAfter, isInsert, isUpdate, isDelete, isUndelete
public Integer size = Trigger.size;
public PaymentType__c[] oldData = Trigger.old;	
public PaymentType__c[] newData = Trigger.new;	
Trigger.old[idx], Trigger.new[idx]
  • Trigger 사례
trigger StandardTrigger on Account (before insert, before update, before delete,
                                                after insert,   after update,    after delete) {
   //--- @future, 비동기 WebService
   //--- sObject.addError('~');
   //--- Trigger.size, oldMap, newMap, old (ReadOnly), new
if (Trigger.isInsert && Trigger.isBefore) {
       for (Account item : Trigger.old) {
       }
       for (Account item : Trigger.new) {
           //--- 수정 가능
       }
   }

   if (Trigger.isInsert && Trigger.isAfter) {
       for (Account item : Trigger.old) {
       }
       for (Account item : Trigger.new) {
       }
   }
}

Triggers and Bulk Triggers

   -   Bulk Triggers
       Data import, Bulk Apex API calls, Mass actions
       Recursive Apex Code methods and triggers that invoke bulk DML statements

   trigger <triggerName> on <ObjectName> bulk (<trigger_event>) {
       //---   trigger_event   : before insert, before update, before delete, after ~

       //---   isInsert, isUpdate, isDelete, isUndelete, isBefore, isAfter

       //---   Trigger.new, Trigger.newMap, Trigger.old, Trigger.oldMap, Trigger.size

       //---   Trigger.oldMap.get(q.opportunity__c).addError('Cannot delete opportunity with a quote');
       //---   Trigger.new[i].Primary__c.addError('Primary quote cannot be marked non-primary');

       try {
           Dictionary__c obj = new Dictionary__c(Name='Dictionary deploy test');
           insert obj;
       } catch(DmlException e) {
           System.assert(e.getMessage().contains('first error: FIELD_CUSTOM_VALIDATION_EXCEPTION,'), e.getMessage());
       }
   }   //---   최대 32,000 characters

   trigger helloWorldAccountTrigger on Account (before insert) 
   {
       //---   before insert, before update, after insert, after update, after delete
       //---   Trigger.isBefore

       Account[] accs = Trigger.new;
       MyHelloWorld.addHelloWorld(accs);
       
       Contact c = new Contact(lastName = 'Weissman');
       c.accountId = a.Id;
       insert c;

       List<Account> aa = [select id, name from account where name = 'Acme'];
       c = [select account.name from contact where id = :c.id];
       c.account.name = 'salesforce.com';
       c.lastName = 'Roth';
       update c;
       update c.account;

       upsert <SObject> <opt_external_id>

       delete <SObject>
       delete <SObject[]>
        
       System.assertEquals('xxx', a.accountNumber);
   }
   
   Savepoint sp = Database.setSavepoint();
   Database.rollback(sp);
   throw <exceptionObject>;

   try {
       <code_block>
   } catch (<exceptionType>) {
       <code_block>
   }

Trigger Sample 1

/**
 *      프로그램 명     : DictionaryTrigger.trigger Trigger
 *      프로그램 설명   : Dictionary 개체용 Trigger 샘플
 *      작성자          : 산사랑
 *      작성일          : 2008.06.19 ~ 2008.06.19
 *
 *      Copyright (c) 2000-2008 pnuskgh, All rights reserved.
 */
trigger DictionaryTrigger on Dictionary__c (before insert, before update, before delete)
{
    Double tmpNum = 0.0;

	if (Trigger.isBefore) {
        if (Trigger.isInsert) {
            for (Dictionary__c obj:Trigger.new) {
                obj.num__c = 1;
            }
        }

        if (Trigger.isUpdate) {
            for (Dictionary__c obj:Trigger.new) {
                if (obj.num__c == 11) {
                    obj.num__c = obj.num__c + 100;
                } else {
                    obj.num__c = obj.num__c + 10;
                }
                if (150 < obj.num__c) {
                    obj.addError('Error : You can\'t update this record.');
                    obj.num__c.addError('Error : You can\'t update this record.');
                }
            }
        }

        if (Trigger.isDelete) {
            for (Dictionary__c obj:Trigger.old) {
                tmpNum = obj.num__c;
            }
        }
	}
}

Trigger Test Class Sample 1

/**
 *      프로그램 명     : DictionaryDeployClass Class
 *      프로그램 설명   : DictionaryTrigger Trigger를 테스트하는 클래스
 *      작성자          : 산사랑
 *      작성일          : 2008.06.19 ~ 2008.06.19
 *
 *      Copyright (c) 2000-2008 pnuskgh, All rights reserved.
 */
public class DictionaryDeployClass {
	public static testmethod void DictionaryDeployTest()
	{
	    Double tmpNum = 0.0;
		
		System.debug('Start insert trigger test.');
		Dictionary__c obj = new Dictionary__c(Name='Dictionary deploy test');
		insert obj;

		obj = [select Id, Name, num__c
		         from Dictionary__c
		        where Id = :obj.Id]; 
		System.assertEquals(1, obj.num__c);


		System.debug('Start update trigger test.');
		tmpNum = obj.num__c + 10;
		update obj;

		obj = [select Id, Name, num__c
		         from Dictionary__c
		        where Id = :obj.Id];
		System.assertEquals(tmpNum, obj.num__c);

		
		try {
            System.debug('Start delete trigger test.'); 
	    	delete obj;
 
    		obj = [select Id, Name, num__c
					from Dictionary__c
					where Id = :obj.Id];
		} catch(QueryException e) {
			System.debug(e.getMessage());
			System.assert(e.getMessage().contains('List has no rows for assignment to SObject'), e.getMessage());
		}
	}
}

Trigger Sample 2

/**
 *      프로그램 명     : OpportunityTrigger.trigger Trigger
 *      프로그램 설명   : Forecast 데이터만 영업기회에서 분리하여 관리
 *      작성자          : 산사랑
 *      작성일          : 2008.06.20 ~ 2008.06.20
 *
 *      Copyright (c) 2000-2008 pnuskgh, All rights reserved.
 */
trigger OpportunityTrigger on Opportunity (before insert, after insert, before update, before delete)
{
	if (Trigger.isAfter) {
        if (Trigger.isInsert) {
            for (Opportunity opp:Trigger.new) {
                Forecast__c obj = new Forecast__c(OwnerId = opp.OwnerId, Name = opp.Name, 
                    Amount__c = opp.Amount__c, GP__c = opp.GP__c, 
                    Probability__c = opp.Probability, opportunity__c = opp.Id);
                insert obj;
            }
        }
    }
    
	if (Trigger.isBefore) {
        if (Trigger.isUpdate) {
            for (Opportunity opp:Trigger.new) {
                Forecast__c obj = [select Id, OwnerId, Name, Amount__c, GP__c, Probability__c, opportunity__c
                                     from Forecast__c
		                            where opportunity__c = :opp.Id];
                obj.OwnerId = opp.OwnerId;
                obj.Name = opp.Name;
                obj.Amount__c = opp.Amount__c;
                obj.GP__c = opp.GP__c;
                obj.Probability__c = opp.Probability;
                update obj;
            }
        }

        if (Trigger.isDelete) {
            for (Opportunity opp:Trigger.old) {
                Forecast__c obj = [select Id, OwnerId, Name, Amount__c, GP__c, Probability__c, opportunity__c
                                     from Forecast__c
		                            where opportunity__c = :opp.Id];
                delete obj;
            }
        }
	}
}

Trigger Test Class Sample 2

/**
 *      프로그램 명     : OpportunityDeployClass Class
 *      프로그램 설명   : OpportunityTrigger Trigger를 테스트하는 클래스
 *      작성자          : 산사랑
 *      작성일          : 2008.06.20 ~ 2008.06.20
 *
 *      Copyright (c) 2000-2008 pnuskgh, All rights reserved.
 */
public class OpportunityDeployClass {
	public static testmethod void OpportunityDeployTest()
	{
	    Boolean flagError = false;
        Forecast__c obj = Null;
		
		System.debug('Start insert trigger test.');
		Opportunity opp = new Opportunity(Name = 'Deploy test', Amount__c = 100, GP__c = 20,
            StageName = '수주확신(90%)', CloseDate = System.today());
		insert opp;

        opp = [select Id, OwnerId, Name, Amount__c, GP__c, Probability
                 from Opportunity
                where Id = :opp.Id];

        obj = [select Id, OwnerId, Name, Amount__c, GP__c, Probability__c, opportunity__c
                 from Forecast__c
                where opportunity__c = :opp.Id];

        System.assertEquals(opp.OwnerId, obj.OwnerId);
        System.assertEquals(opp.Name, obj.Name);
        System.assertEquals(opp.Amount__c, obj.Amount__c);
        System.assertEquals(opp.GP__c, obj.GP__c);
        System.assertEquals(opp.Probability, obj.Probability__c);
        System.assertEquals(opp.Id, obj.opportunity__c);

		System.debug('Start update trigger test.');
        opp.GP__c = 30;
        update opp;

        obj = [select Id, OwnerId, Name, Amount__c, GP__c, Probability__c, opportunity__c
                 from Forecast__c
                where opportunity__c = :opp.Id];

        System.assertEquals(opp.OwnerId, obj.OwnerId);
        System.assertEquals(opp.Name, obj.Name);
        System.assertEquals(opp.Amount__c, obj.Amount__c);
        System.assertEquals(opp.GP__c, obj.GP__c);
        System.assertEquals(30, obj.GP__c);
        System.assertEquals(opp.Probability, obj.Probability__c);
        System.assertEquals(opp.Id, obj.opportunity__c);
        
		try {
            System.debug('Start delete trigger test.');
	    	delete opp;

    		obj = [select Id, OwnerId, Name, Amount__c, GP__c, Probability__c, opportunity__c
					from Forecast__c
					where opportunity__c = :opp.Id];
		} catch(QueryException e) {
            if (e.getMessage().contains('List has no rows for assignment to SObject')) {
                flagError = true;
            } else {
    			throw e;
            }
		}
        System.assert(flagError);
	}
}

Control - Scheduler

  • "설정 -> App 설정 -> 개발 -> Apex 클래스 -> Apex 예약" 메뉴

Schedular001.png


  • "설정 -> 관리 설정 -> 모니터링 -> 예약된 작업" 메뉴에서 모니터링
  • Scheduler 생성
global class StandardScheduler implements Schedulable {
    global void execute (SchedulableContext sc) {
        Batchable batch = null; 

        //--- sc.getTriggerId()  CronTrigger 개체
        batch = new Batchable();
        Database.executebatch(batch);
    }
}
  • Scheduler 사용법
  • 초(0-59) 분(0-59) 시(0-23) 일(1-31) � 월(1-12) 주(1-7, 1.일요일) 년(1970-2099)
String sch = ‘20 30 8 10 2 ? * ‘;
String id = system.schedule(‘name’, sch, StadnardScheduler);

Control - Batch Apex

Database.Batchable Interface

Apex Code에서 Batch 프로그램을 작성하려면 Database.Batchable Interface를 구현 하여야 합니다.

  • global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {}
  • execute Method에서 처리할 레코드를 수집하여 반환 합니다.
  • global void execute(Database.BatchableContext BC, list<P>) {}
  • 실제로 Batch 처리가 이루어지는 method 입니다.
  • Default로 200개의 records씩 전달되어 실행이 되며 각 execute은 별개의 Transaction으로 처리가 됩니다.
  • global void finish(Database.BatchableContext BC) {}
  • Batch 처리가 모두 완료된 후에 호출되는 method 입니다.

Database.AllowsCallouts Interface

Apex Batch에서 HTTP request를 호출하는 프로그램을 작성하려면 Database.AllowsCallouts Interface를 implement 하여야 합니다.

Database.Stateful Interface

Apex Batch 처리를 위한 Class에서 선언한 변수의 값을 계속 유지하려면 Database.Stateful Interface를 implement 하여야 합니다.

Database.BatchableContext

  • getJobId() : 해당 Apex Batch Job의 ID를 반환 합니다.

Database

  • executeBatch Method : Apex Batch를 실행 합니다.
ID batchId = null;
BatSession batch = null;
       
batch = new BatSession();
batchId = Database.executeBatch(batch);
//batchId = Database.executeBatch(batch, 200);     //--- 200. 한번에 처리하는 레코드 갯수

Batch Apex 사례

  • Batch Apex 선언
  • Database.AllowsCallouts Interface : HTTP 호출시 implement
  • Database.Stateful : Class에서 선언한 변수 값을 유지하려면 implement
global class BatAccount implements Database.Batchable<Account>, Database.Stateful {
    global Database.QueryLocator start(Database.BatchableContext ctx) {
       return Database.getQueryLocator([SELECT Id, Name FROM Account]);
    }
   
    global void execute(Database.BatchableContext ctx, List<Account> scope) {
        for (Account item : scope) {
        }
    }
   
    global void finish(Database.BatchableContext ctx) {
        ID id = ctx.getJobID();	//--- AsyncApexJob 개체
    }
}
  • Batch Apex 사례
global class BatSession implements Database.Batchable<sObject>, Database.Stateful {
   global Database.QueryLocator start(Database.BatchableContext ctx) {
       Datetime tmpDate = null;
       
       tmpDate = Datetime.now();
       tmpDate.addDays(-3);
       return Database.getQueryLocator([SELECT Id
                                          FROM Session__c
                                         WHERE CreatedDate < :tmpDate]);
   }
   
   global void execute(Database.BatchableContext ctx, List<sObject> scope) {
       delete scope;
   }
   
   global void finish(Database.BatchableContext ctx) {
       AsyncApexJob job = null;

       AsyncApexJob job = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email
                             FROM AsyncApexJob
                            WHERE Id = :ctx.getJobId()];
   }
}

Batch Job 모니터링

  • AsyncApexJob : Batch 진행 사항을 저장
  • "설정 -> 관리 설정 -> 모니터링 -> Apex 작업" 메뉴에서 모니터링
  • Apex 작업

Batch 제약 사항

  • start method에서 QueryLocator를 사용할 경우 최대 5000만 레코드만 처리가 가능 합니다.
  • start method에서 Iterable을 사용할 경우 최대 레코드 제약은 그대로 적용이 됩니다.
  • Apex governor limits are reset for each execution of execute
  • 동시에 최대 5개의 Batch Job만 처리가 가능 합니다.
  • A user can have up to 5 query cursors open at a time
  • Apex query cursors, Batch cursors, Visualforce cursors는 각각 최대 5개까지 동시에 사용이 가능 합니다.
  • Aggregate Query는 Batch Apex에서 start 함수의 결과로써 사용할 수 없습니다.

Control - Web Service

  • Web Services 생성 in Apex Code
global class StandardWebServices {
    webService static String getTitle(String title, Account argAccount) {
        return '[' + title + ']';
    }
}
  • Web Services 호출 in Visualforce Page
<script type="text/javascript">
 var __sfdcSessionId = "{!GETSESSIONID()}";
 </script>
 <script type="text/javascript" src="/soap/ajax/22.0/connection.js"></script>
 <script type="text/javascript" src="/soap/ajax/22.0/apex.js"></script>

var account = sforce.sObject("Account");	//--- id, type, name
var title = sforce.apex.execute(“StandardWebServices”, “getTitle”, 
              {title:”~”, argAccount:account});
  • sforce.debug.trace = true;

Control - HTTP

Http http       = null; 
HttpRequest req = null; 
HttpResponse res = null;
String strHeader = null;
String contentType = null, response = null;

try {
    req = new HttpRequest();
    req.setEndpoint('http://www.apexdevnet.com/'); 
    req.setMethod('GET');
    req.setHeader(‘Content-Type’, ‘application/soap+xml’);
    req.setTimeout(60000);
    req.setBody(‘name1=value1&name2=value2’);
    req.setCompressed(false);

    //--- Basic Authencation
    strHeader = EncodingUtil.base64Endoce(Blob.valueOf(userid + ‘:’ + pwd))
    req.setHeader(‘Authorization’, ‘BASIC ‘ + strHeader);

    http = new Http();
    res = http.send(req); 
    if (res.getStatusCode() == 404) {
    } else {
        contentType = resp.getHeader('Content-Type');
        response = resp.getHeader('Content-Length');
        this.theXMLDom = new xmldom(res.getBody());

        dom.document doc = res.getBodyDocument();  
        dom.XmlNode [] node = doc.getRootElement().getChildElements();  

        //--- Atachement로 저장
        Attachment attach = new Attachment();
        attach.Name = “~’;
        attach.ContentType = “~”;
        attach.body = Blob.valueOf(res.getBody());
        attach.ParenetId = ~;
        insert attach;
    }
} catch (System.CalloutException e) {
    this.theXMLDom = null;
}

Control - RemoteAction

RemoteAction은 Visualforce Page에서 JavaScript를 사용하여 Controller의 Method를 호출하는 방법 입니다.

  • Apex Code
global class MyJSController {
    public String accountName { get; set; } 
    public static Account account { get; set; } 

    @RemoteAction
    global static Account getAccount(String accountName) { 
        account = [
            SELECT id, name, phone 
             FROM Account 
            WHERE name =  :accountName ];
        return account;
    } 
}
  • Visualforce Page
<apex:page controller="MyJSController“>
<script type="text/javascript"> 
    var accountNameJS = null; 

    accountNameJS = "오픈소스 비즈니스 컨설팅"; 
    MyJSController.getAccount(
        accountNameJS,            //--- 전달되는 인자 
        function(result, event) {   //--- result : 반환 값 
            if (event.status) { 
                //--- 정상 처리 
                //--- 반환된 값은 result.name
                //--- 반환된 배열 result[2].name
            } else if (event.type === 'exception') {
                //--- Exception 오류 처리 
            } else { 
                //--- 오류 처리 
            }
        }, 
       {escape:true} 
); 
</script> 
</apex:page>
  • 참고 문헌

Control - Email Service

  • Single Mail 발송
Messaging.SingleEmailMessage email = null;
Messaging.EmailFileAttachment file = null;
Messaging.SendEmailResult[] result = null;

email = new Messaging.SingleEmailMessage();
email.setSubject(String);
email.setToAddress(String[]);
email.setPlainTextBody(String);

file = new Messaging.EmailFileAttatchment();
file.setFileName(‘~’);
file.setBody(Blob);

email.setFileAttachments(new Messaging.EmailFileAttachment[] {file});
result = Messaging.sendEmail(new Messaging.SingleEmailMessag[] {email});

Custom Setting

  • Setting__c.getValues(Name).Value__c
  • Setting__c : Custom Setting 개체명
  • Name : 레코드의 Name
  • Value__c : 레코드의 Value__c라는 필드의 필드값

Sandbox

  • Sandbox 명이 de일 경우, Sandbox의 로그인 아이디는 userid.de 입니다.

Deploy

  • Eclipse에서 deploy
  • 클래스를 선택한 후 오른쪽 마우스를 누릅니다.
  • "Force.com -> Deploy to Server..." 메뉴를 선택하여 deploy 합니다.
  • Setup에서 deploy
  • 운영의 "설정 -> App 설정 -> 배치 -> 연결 배포"에서 "인바운드 변경 허용"을 선택 합니다.
  • Sandbox의 "설정 -> App 설정 -> 배치 -> 아웃바운드 변경 세트"에서 변경세트를 작성하고 업로드 합니다.
  • 운영의 "설정 -> App 설정 -> 배치 -> 인바운드 변경 세트"에서 업로드된 변경 세트를 배포 합니다.
  • Deploy의 제약 사항
  • Class와 Trigger를 75% 이상 테스트 되어야 합니다.
  • 하나의 class가 deploy 되더라도 모든 class에서 검증이 들어 갑니다. (Source Coverage의 평균이 75% 이상이 되어야 합니다.)
  • Test Class는 실제 운영 서비스에 있는 테스트 클래스가 실행 되므로 먼저 테스트 클래스부터 deploy 해야 합니다.

Force.com 내장 개체

System

  • Debug
  • System.debug(Message);
  • System.debug(logLevel, Message);
ERROR, WARN, INFO, DEBUG, FINE, FINER, FINEST
  • Date and Time
  • System.today() : 오늘 날자를 반환한다.
  • System.now() : 오늘 날자와 시간을 반환한다.

암호화

  • 암호화 key 생성
  • Blob key = Crypto.generateAesKey(256)
  • 암호화
  • String 암호문 = EncodingUtil.base64Encode(Crypto.encryptWithManagedIV('AES256', key, Blob.valueOf('평문')));
  • 복호화
  • String 평문 = Crypto.decryptWithManagedIV('AES256', key, EncodingUtil.base64Decode('암호문')).toString();
  • 해시키 생성
  • '[MD5]' + 해시키 = Crypto.generateDigest('MD5', '해시키로 변환할 문자열');
  • String과 Blob간 변환
  • Blob에 문자열이 저장되어 있을 경우
  • String strBlob = dataBlob.toString();
  • Blob dataBlob = Blob.valufOf(strBlob);
  • Blob에 바이너리가 저장되어 있을 경우
  • String strBlob = EncodingUtil.base64Encode(dataBlob);
  • Blob dataBlob = EncodingUtil.base64Decode(strBlob);

인코딩

  • 인코딩 : EncodingUtil.base64Encode(~)
  • 디코딩 : EncodingUtil.base64Decode(~)
  • URL 인코딩 : EncodingUtil.urlEncode(~, “UTF-8”)
  • URL 디코딩 : EncodingUtil.urlDecode(~, “UTF-8”)

Logging

  • System Logging Levels (System.LoggingLevel enum)
  • ERROR
  • WARN
  • INFO
  • DEBUG
  • FINE
  • FINER
  • FINEST
  • 로그 남기기
System.debug('MsgTxt'); //--- Default Loggin Level인 Logginglevel.DEBUG 가 적용됨)
System.debug(Logginglevel.INFO, 'MsgTxt');
  • Apex Code별 로그 레벨 설정
  • Apex 클래스 : "설정 -> App 설정 -> 개발 -> Apex 클래스" 메뉴에서 원하는 클래스를 선택한 후 "로그 필터" 탭에서 설정
ApexLog01.png
  • Apex 트리거 : "설정 -> App 설정 -> 개발 -> Apex 트리거" 메뉴에서 원하는 트리거를 선택한 후 "로그 필터" 탭에서 설정
ApexLog02.png
  • 로그 확인
  • "시스템 로그" 메뉴에서 확인
  • "설정 -> 관리 설정 -> 모니터링 -> 디버그 로그"에서 확인

Dynamic Apex

sObject 정보 획득

sObject
  • sObject obj = new Custom__c();
  • Map<String, Schema.SObjectType> objAll = Schema.getGlobalDescribe();
  • 표준 개체는 key에 namespace가 붙지 않습니다.
  • 사용자 정의 개체는 namespace가 다를 경우, key에 "NS__" 와 같은 형태의 namespace가 앞에 붙습니다.

  • Object value = obj.get('name');
  • obj.put('name', 'value');
  • obj.put(field, 'value');
  • sObject objParent = obj.getSObject('ParentCustom__c');
  • SELECT Id, ParentCustom__c FROM Custom__c LIMIT 1
  • sObject[] objChild = obj.getSObjects('ChildCustom__c');
  • SELECT Id, (SELECT Name FROM ChildCustom__c LIMIT 1) FROM Custom__c
Schema.SObjectType
  • Schema.SObjectType objType = obj.getSObjectType();
  • Schema.SObjectType objType = Custom__c.sObjectType;
  • Schema.SObjectType objType = objDesc.getSObjectType();

  • Custom__c obj = (Custom__c)objType.newSObject();
Schema.DescribeSObjectResult
  • Schema.DescribeSObjectResult objDesc = objType.getDescribe();
  • Schema.DescribeSObjectResult objDesc = Custom__c.sObjectType.getDescribe();
  • Schema.DescribeSObjectResult objDesc = Schema.SObjectType.Custom__c;

  • String objDesc.getName()
  • String objDesc.getLabel()
  • String objDesc.getKeyPrefix()
  • List<Schema.ChildRelationship> objDesc.getChildRelationships()
Schema.SObjectField
  • Schema.SObjectField field = fieldDesc.getSObjectField();
  • Schema.SObjectField field = Custom__c.Field__c;
  • Map<String, Schema.SObjectField> fieldAll = Schema.SObjectType.Custom__c.fields.getMap();
  • 표준 필드는 key에 namespace가 붙지 않습니다.
  • 사용자 정의 필드는 namespace가 다를 경우, key에 "NS__" 와 같은 형태의 namespace가 앞에 붙습니다.
  • 참고 문헌
Schema.DescribeFieldResult
  • Schema.DescribeFieldResult fieldDesc = field.getDescribe();
  • Schema.DescribeFieldResult fieldDesc = Custom__c.Field__c.getDescribe();
  • Schema.DescribeFieldResult fieldDesc = Schema.sObjectType.Custom__c.fields.Field__c;

  • String fieldDesc.getLabel();
  • String fieldDesc.getName();
  • Schema.DisplayType fieldDesc.getType();
  • List <Schema.PicklistEntry> fieldDesc.getPicklistValues();
  • Object fieldDesc.getDefaultValue();
  • Schema.SOAPType Enum
  • String, Integer, Double, Boolean, Date, Datetime, Time
  • ID, anytype, base64binary
  • 제공 함수
  • Integer getByteLength()
  • String getCalculatedFormula()
  • Schema.SObjectField getController()
  • Object getDefaultValue()
  • String getDefaultValueFormula()
  • Integer getDigits()
  • String getInlineHelpText()
  • String getLable()
  • Integer getLength
  • String getLocalName()
  • String getName()
  • List<Schema.PicklistEntry> getPicklistValues()
  • Integer getPrecision()
  • List<Schema.SObjectType> getReferenctTo()
  • String getRelationshipName()
  • Integer getRelationShipOrder()
  • Integer getScale()
  • Schema.SoapType getSoapType()
  • Schema.SObjectField getSobjectField()
  • Schema.DisplayType getType()
  • Boolean isAccessible()
  • Boolean isAutoNumber()
  • Boolean isCalculated()
  • Boolean isCaseSEnsitive()
  • Boolean isCreateable()
  • Boolean isCustom()
  • Boolean isDefaultedOnCreate()
  • Boolean isDependentPicklist()
  • Boolean isDeprecatedAndHidden()
  • Boolean isExternalId()
  • Boolean isFilterable()
  • Boolean isHtmlFormatted()
  • Boolean isIdLookup()
  • Boolean isNameField()
  • Boolean isNamePointing()
  • Boolean isNillable()
  • Boolean isRestrictedPicklist()
  • Boolean isSortable()
  • Boolean isUnique()
  • Boolean isUpdateable()
  • Boolean isWriteRequiresMasterRead()
  • picklist entry
  • 제약 사항
  • 최대 100개의 fields 멤버를 사용할 수 있습니다.

Dynamic SOQL

  • 동적으로 데이터 읽기
sObject item = Database.query(string_limit_1);
List<sObject> data = Database.query(string);
  • 동적으로 데이터 처리하는 샘플
List<sObject> data = null;
Map<String, Schema.SObjectField> columns = null;

data = Database.query(strQuery);
columns = data.getSObjectType().getDescribe().fields.getMap();
for (sObject item : data) {
    for (String name : columns.keySet()) {
        string value = null;

        value = String.valueOf(item.get(name));
    }
}
  • 참고 문헌

Dynamic Visualforce

  • 변수 : ~.~, ~[‘~’]
  • Map<String, Schema.SobjectField> = Schema.SobjectType.Account.fields.getMap();
  • Schema.SobjectField
  • getDescribe().isAccessible(), isCustom()
  • Component.NameSpace.~
  • Component.Apex.OutputText
  • {!$ObjectType.Account.FieldSets.~}
  • Field : Label, Type, Required, FieldPath, DBRequired
  • sObject.put(~, ~), get(~)
  • StandardController
  • StandardSetController
  • reset(), addFields(List<String>)
  • Include
  • <apex:include pageName=“~” />
  • <apex:includeScript value=“{$Resource.~}” />
  • <apex:stylesheet value=“{$Resource.~}” />�
  • <apex:iframe src=“~” height=“~” width=“~” scrolling=“true” frameborder=“false” />

Managed Sharing

  • 공유 권한 : 소유자 -> 역할 -> 공유 설정 / 필드 접근성
  • User Managed Sharing
  • Access Level : None. Private, Read. Read Only, Edit. Read/Write, All. Full Access
  • 개체명__Share
  • Modify All Data" 권한이 있어야 사용 가능
public class JobSharing {
    public Boolean manualShare(ID recordId, ID userOrGroup) {
        Job__Share share = new Job__Share();

        share.ParentId = recordId;
        share.UserOrGroup = userOrGroup;        //--- Job.Recruiter__c
        share.AccessLevel = ‘Read’;
        share.RowCause = Schema.Job__Share.RowCause.Manual;
        //--- 공유 이유가 Recruite일 경우 (사용자 정의 공유 이유)
        //--- share.RowCause = Schema.Job__Share.RowCause.Recruite__c;
        Database.insert(share);
    }
}

JSONObject

apex-library의 JSONObject를 사용하여 JSON 데이터를 처리할 수 있습니다.

  • JSONObject Class
  • 생성자 : JSONObject(String source)
  • Key 확인
Boolean has(String key)
SET keys()
  • 데이터를 저장하는 함수
JSONObject putOpt(String key, JSONObject.value value)
  • 데이터 읽어 오는 함수
JSONObject.value  getValue(String key)
Object  get(String key)
Object  opt(String key)   //--- Default는 null을 반환

String   getString(String key)
//--- Integer.valueOf(string), Date.valueOf(string) 등을 사용하여 다른 type으로 변환 가능

Boolean  getBoolean(String key)
Boolean  optBoolean(String key) //--- Default는 false
Boolean  optBoolean(String key, Boolean defaultValue)
String valueToString()
  • 데이터 읽어 오는 함수의 응용
JSONObject snbJson = new JSONObject(strJson);
for (JSONObject.value jsonItem : snbJson.getValue('data').values) {
    JSONObject item = null;

    item = new JSONObject(jsonItem.valueToString()); 
}
  • JSONObject.value Class의 속성값
JSONObject obj
String str
Integer num
Double dnum
Boolean bool
List<value> values
  • 참고 문헌

Apex Code 개발

Request

  • Apex Code에서
ApexPages.currentPage().getParameters().get('id');
  • VisualForce Page에서
{!$CurrentPage.parameters.cid}

Cookie

Cookie는 일반적으로 도메인을 기준으로 설정이 됩니다. 세일즈포스닷컴은 CRM 서비스를 제공하는 URL과 Visualforce의 URL이 다르므로 서로 다른 도메인의 URL을 가지게 됩니다.

  • 세일즈포스닷컴의 URL 종류
  • Apex Code에서 Cookie 사용 방법
  • Apex Code에서 저장한 Cookie는 이름의 앞에 "apex__"가 자동으로 붙어서 처리가 됩니다.
public class UtilCookie {
   public static String getCookie(String name) {
       Cookie cookie = null;
       
       cookie = ApexPages.currentPage().getCookies().get(name);
       if (cookie == null) {
           return null;
       } else {
           return cookie.getValue();
       }
   }
   
   //--- 저장되는 Cookie명은 "apex__" + name 입니다.
   public static void setCookie(String name, String value) {
       Cookie cookie = null;
       
       cookie = new Cookie(name, value, null, -1, false);
       ApexPages.currentPage().setCookies(new Cookie[]{ cookie });
   }
}
  • JavaScript에서 Cookie 사용 방법
<script type="text/javascript">
var APEX_PREFIX = "apex__";

//---   Cookie를 저장한다.
function setCookieTime(name, value, mSecond)
{
   var today  = new Date();
   var expire = new Date(today.getTime() + mSecond);

   window.document.cookie = name + "=" + escape(value)
       + ((expire) ? "; expires=" + expire.toGMTString() : "");
}

function setCookie(name, value, days)
{
    setCookieTime(name, value, days * 24 * 60 * 60 * 1000);
}

//---   Cookie를 가져온다.
function getCookie(uName)
{
   var strCookie = " " + window.document.cookie;
   var ptrFr = strCookie.indexOf(" " + uName + '=');

   if (ptrFr != -1) {
       ptrFr = ptrFr + uName.length + 2;
       ptrTo = strCookie.indexOf(';', ptrFr);

       if (ptrTo == -1) {
           ptrTo = strCookie.length;
       }
       return unescape(strCookie.substring(ptrFr, ptrTo));
   } else {
       return "";
   }
}
</script>

Session

사용자 세션을 활용하여 세션 정보를 관리하는 모듈을 작성 합니다.

  • Session의 종류
  • 사용자 세션 (Apex Code 세션)
UserInfo.getSessionID();
  • API용 세션 (AJAX Toolkit 세션)
{!$Api.Session_ID}
var __sfdcSessionId = "{!GETSESSIONID()}";
//--- sforce.connection.sessionId 에 저장되어 사용됨
  • Salesforce 서비스의 세션
  • Session__c 개체

Session.png

  • DaoSession
public class DaoSession {
   public String sessionId {get; set;}
   
   public DaoSession(String argSessionId) {
       sessionId = argSessionId;
   }

   public String findData(String argName) {
       Session__c session = null;
   
       session = [SELECT Id, Name, SessionId__c, Name__c, Value__c, LastModifiedDate
                    FROM Session__c
                   WHERE SessionId__c = :sessionId
                     AND Name__c = :argName
                   LIMIT 1];
       return session.Value__c;
   }
   
   public void insertData(String argName, String argValue) {
       Session__c session = null;
   
       session = new Session__c();
       session.SessionId__c = sessionId;
       session.Name__c= argName;
       session.Value__c = argValue;
       insert session;
   }
   
   public void updateData(String argName, String argValue) {
       Session__c session = null;
   
       session = [SELECT Id, Name, SessionId__c, Name__c, Value__c, LastModifiedDate
                    FROM Session__c
                   WHERE SessionId__c = :sessionId
                     AND Name__c = :argName
                   LIMIT 1];
       session.Value__c = argValue;
       update session;
   }
   
   public Void upsertData(String argName, String argValue) {
       Session__c session = null;
   
       try {
           session = [SELECT Id, Name, SessionId__c, Name__c, Value__c, LastModifiedDate
                        FROM Session__c
                       WHERE SessionId__c = :sessionId
                         AND Name__c = :argName
                       LIMIT 1];
       } catch (Exception ex) {
       }
       
       if (session == null) {
           session = new Session__c();
           session.SessionId__c = sessionId;
           session.Name__c= argName;
           session.Value__c = argValue;
           insert session;
       } else {
           session.Value__c = argValue;
           update session;
       }
   }

   public Void deleteData(String argName) {
       Session__c session = null;
   
       session = [SELECT Id, Name, SessionId__c, Name__c, Value__c, LastModifiedDate
                    FROM Session__c
                   WHERE SessionId__c = :sessionId
                     AND Name__c = :argName
                   LIMIT 1];
       delete session;
   }
}
  • MgrSession
public class MgrSession {
   public DaoSession dao = null;
   
   public MgrSession() {
       dao = new DaoSession(UserInfo.getSessionId());
   }
   
   public String getSession(String argName) {
       return dao.findData(argName);
   }
   
   public Void setSession(String argName, String argValue) {
       dao.upsertData(argName, argValue);
   }
}
  • SchSession
  • "App 설정 -> 개발 -> Apex 클래스" 메뉴에서 "Apex 예약"에서 등록
  • "관리 설정 -> 모니터링 -> 예약된 작업"에서 등록된 작업을 조회
global class SchSession implements Schedulable {
   global void execute(SchedulableContext sc) {
       BatSession batch = null;
       
       batch = new BatSession();
       Database.executeBatch(batch);
   }
}
  • BatSession
global class BatSession implements Database.Batchable<sObject> {
   global Database.QueryLocator start(Database.BatchableContext ctx) {
       Datetime tmpDate = null;
       
       tmpDate = Datetime.now();
       tmpDate.addDays(-3);
       return Database.getQueryLocator([SELECT Id
                                          FROM Session__c
                                         WHERE CreatedDate < :tmpDate]);
   }
   
   global void execute(Database.BatchableContext ctx, List<sObject> scope) {
       delete scope;
   }
   
   global void finish(Database.BatchableContext ctx) {
   }
}

Config

  • ConfigSetting__c Custom Settings

Forcecom config new.png

  • MgrConfig
public class MgrConfig {
   public MgrConfig() {
   }
   
   public String getConfig(String argName) {
       ConfigSetting__c config = null;
       
       config = ConfigSetting__c.getValues(argName);
       return config.Value__c;
   }
}
  • Config__c 개체

Forcecom config.png

  • DaoConfig
public  class DaoConfig {
   public static String CATEGORY = 'global';
   
   public DaoConfig() {
   }

   public String findData(String argCategory, String argName) {
       Config__c config = null;
   
       config = [SELECT Id, Name, Category__c, Name__c, Value__c
                   FROM Config__c
                  WHERE Category__c = :argCategory
                    AND Name__c = :argName
                  LIMIT 1];
       return config.Value__c;
   }
   
   public String findData(String argName) {
       return findData(CATEGORY, argName);
   }
   
   public void insertData(String argCategory, String argName, String argValue) {
       Config__c config = null;
   
       config = new Config__c();
       config.Category__c = argCategory;
       config.Name__c = argName;
       config.Value__c = argValue;
       insert config;
   }
   
   public void insertData(String argName, String argValue) {
       insertData(CATEGORY, argName, argValue);
   }
   
   public void updateData(String argCategory, String argName, String argValue) {
       Config__c config = null;
   
       config = [SELECT Id, Name, Category__c, Name__c, Value__c
                   FROM Config__c
                  WHERE Category__c = :argCategory
                    AND Name__c = :argName
                  LIMIT 1];
       config.Value__c = argValue;
       update config;
   }
   
   public void updateData(String argName, String argValue) {
       updateData(CATEGORY, argName, argValue);
   }
   
   public Void upsertData(String argCategory, String argName, String argValue) {
       Config__c config = null;
   
       try {
           config = [SELECT Id, Name, Category__c, Name__c, Value__c
                       FROM Config__c
                      WHERE Category__c = :argCategory
                        AND Name__c = :argName
                      LIMIT 1];
       } catch (Exception ex) {
       }
       
       if (config == null) {
           config = new Config__c();
           config.Category__c= argCategory;
           config.Name__c= argName;
           config.Value__c = argValue;
           insert config;
       } else {
           config.Value__c = argValue;
           update config;
       }
   }

   public Void upsertData(String argName, String argValue) {
       upsertData(CATEGORY, argName, argValue);
   }

   public Void deleteData(String argCategory, String argName) {
       Config__c config = null;
   
       config = [SELECT Id, Name, Category__c, Name__c, Value__c
                   FROM Config__c
                  WHERE Category__c = :argCategory
                    AND Name__c = :argName
                  LIMIT 1];
       delete config;
   }
   
   public Void deleteData(String argName) {
       deleteData(CATEGORY, argName);
   }
}
  • MgrConfig
public class MgrConfig {
   public DaoConfig dao = null;
   
   public MgrConfig() {
       dao = new DaoConfig();
   }
   
   public String getConfig(String argCategory, String argName) {
       return dao.findData(argCategory, argName);
   }
   
   public String getConfig(String argName) {
       return dao.findData(argName);
   }
   
   public Void setConfig(String argCategory, String argName, String argValue) {
       dao.upsertData(argCategory, argName, argValue);
   }
   
   public Void setConfig(String argName, String argValue) {
       dao.upsertData(argName, argValue);
   }
}

참고 문헌

지원 업체

SuiteCRM을 사용한 영업관리, 고객관리는 아래 담당자에게 연락하여 주시면, 빠르고 친절하게 전문적인 답변을 드리겠습니다.

영업 문의 sales@obcon.biz 010-4667-1106 영업 대표
기술 문의 tech@obcon.biz 구축/컨설팅 담당
고객 지원 support@obcon.biz 고객 지원 담당

OBCon 홈페이지 바로가기