배치 개발을 많이 하다보니까 요즘 계속 exception 내용만 남기네 ^^...
[정의]
단일 트랜잭션 내에서 설정(Setup) 객체와 비설정(Non-setup) 객체에 대해 동시에 데이터 조작 언어(DML) 작업을 수행할 때 발생하는 Exception
예를들어서
설정 개체는 아래와 같다
- User
- Group
- GroupMember
- Profile
- PermissionSet
- PermissionSetAssignment
- ObjectPermissions
- FieldPermissions
- Queue
- Role
- UserRole
그외 custom object , standard obj 는 비설정 객체에 보함이 된다
이 DML 이 한 배치에 동시에 일어나면 , 저 에러가 어김없이 나온다...
해결방안
Batch 외 일반 class에서는 @future을 사용하면되지만,,
Batch 안에서는 @future 을 사용할 수 없기에..
queable 로 트랜잭션을 분리해서 처리를 해야한다.
예를들어 batch 안에 excute 안에서
A__c 라는 custom object 를 delete 하면서 GroupMember 를 삭제해야하는 로직을 예를들면
아래와 같이 코드를 작성했다
public void execute(Database.BatchableContext BC, List<User> userList) {
try{
Set<Id> userIdSet = (new Map<Id,User>(userList)).keySet();
List<A__c> aList = [
SELECT Id
FROM A__c
WHERE b__c IN :userIdSet
];
if(aList.Size()>0){
delete aList;
}
// 트랜잭션 분리!
System.enqueueJob(new delMember(userIdSet));
}catch(Exception e){
}
}
이렇게 짜고
finish 아래 quealbe class를 추가하던가 .. 별도 클래스를 새로 만들어 사용하는방법이 있다.
public class delMember implements Queueable {
// 삭제 로직
}
이렇게 분리를 해주면 한 배치가 돌때 해당 Exception이 뜨지 않고 잘 돌아가는걸 확인할 수 있다.