MIXED_DML_OPERATION, 非設定オブジェクトを更新した後の設定オブジェクト上のDML操作(またはその逆)は、許可されていませんという、Salesforce特有のエラーに対し、どのように対処していけばいいか、今回は3つの対処法を紹介していきたいと思います。
そもそもこのエラーの原因は?
https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_dml_non_mix_sobjects.htm
上記ページに詳細は記してありますが、同じトランザクション内でDML操作を実行する場合、設定オブジェクトと非設定オブジェクトの両方を含めることができません。
例えば下記のsObjectは他のsObjectと一緒のトランザクション内で使用できません。
FieldPermissions
Group
以下のsObjectは他のsObjectを含む1つのトランザクションでは、グループの挿入と更新のみを行うことができます。その他のDML操作は使用できません。
GroupMember
API
ObjectPermissions
PermissionSet
PermissionSetAssignment
QueueSObject
ObjectTerritory2AssignmentRule
ObjectTerritory2AssignmentRuleItem
RuleTerritory2Association
SetupEntityAccess
Territory2
Territory2Model
UserTerritory2Association
User
それではこのエラーの3つの解決方法を紹介いたします。
解決方法① トランザクションを分ける
これができてしまえば一番簡単なのですが、可能であれば設定オブジェクトと日設定王ジェクトはどうしても同じトランザクションで処理をしなければいけないという場合を除いて、別々のものにわけて処理をするというのが一番簡単な解決法になります。
解決方法② プロセスビルダーを使用する
個人的にはこの方法が一番おすすめかもしれません。
プロセスビルダーとは、Salesforceに標準搭載されている、様々なプロセスを設定して自動的に実行できるアプリケーションになります。詳しくは下記の公式HPを参照ください。
これを利用することで、あるオブジェクトの項目を更新することをトリガとして、他の項目を変更することができます。これを用いることで、同時に行おうとしていた日設定オブジェクトと設定オブジェクトの操作を、一方はApexのコード上で、もう一方はプロセスビルダー上でという風に切り分けることが可能になります。
プロセスビルダーはGUI上で設定を行えるため、直感的に使えるため、色々なコード上の処理を書き換えることも可能です。
これを使えばトランザクションを分けることができるので、MIXED_DML_OPERATIONエラーは解消されます。
解決方法③ futureをつけて非同期処理を行う
@futureをつけることでDMLを実行することができます。
しかし、返り値を返すことや、同じ@futureのついたfunctionから呼び出せないことなど、Apexの非同期処理は制約が多いのも現実です。
例えば下記のように行います。
public static void sampleFunc(){
updateFormOwner(aid, bid);
}
@future
private static void updateFormOwner(Id formId, Id groupId){
Form__c form = [SELECT OwnerId FROM Form__c WHERE Id = :formId];
system.debug(form);
form.OwnerId = groupId;
update form;
}
以上がApexでMIXED_DML_OPERATIONエラーに出会った際の解決法になります。
もし他にもより良いものがありましたら、コメントなどで教えてください。