【Apex】関連オブジェクトのupdate。別にselectし直さなくても良い。
分かりづらいタイトルですが・
Apex処理であるオブジェクトを更新して、そのオブジェクトに関連している(参照関係 or 主従関係)オブジェクトもついでに更新するという場面はけっこうあると思います。
具体的に以下、取引先責任者と取引先の例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
/** Apexクラス */ public class SampleClass { public static void updateSample() { // 更新対象の取引先責任者を取得 List<Contact> conList = [ SELECT Id ,Description //説明 ,AccountId //取引先Id FROM Contact WHERE Email != null ]; // 取引先責任者の説明を更新 for (Contact con : conList) { con.Description = Date.today().format() + '時点 メール入力済み'; } // 取引先責任者update update conList; // 上記取引先責任者に関連する取引先を取得 // ①取引先責任者に関連する取引先Idセットを作成 Set<Id> accIdSet = new Set<Id>(); for (Contact con : conList) { accIdSet.add(con.AccountId); } // ②作成した取引先Idセットを条件に取引先を取得 List<Account> accList = [ SELECT Id ,Description //説明 FROM Account WHERE Id = :accIdSet ]; // 取引先の説明を更新 for (Account acc : accList) { acc.Description = Date.today().format() + '時点 処理済み'; } //取引先update update accList; } } |
上記例だと取引先責任者を更新した後、関連する取引先をselectしています(ハイライトの部分)。これを、別にselectしなくてもいけるよというのがタイトルで言いたかったことになります。
まあ自分メモなので・・
具体的にどのように書けば良いかというと
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
/** Apexクラス */ public class SampleClass { public static void updateSample() { // 更新対象の取引先責任者を取得 List<Contact> conList = [ SELECT Id ,Description //説明 ,AccountId //取引先Id FROM Contact WHERE Email != null ]; // 取引先責任者の説明を更新 for (Contact con : conList) { con.Description = Date.today().format() + '時点 メール入力済み'; } // 取引先責任者update update conList; // 取引先の説明を更新 Map<Id, Account> accUpdateMap = new Map<Id, Account>(); for (Contact con : conList) { Account acc = accUpdateMap.get(con.AccountId); if (acc == null) { acc = new Account(); acc.Id = con.AccountId; accUpdateMap.put(acc.Id, acc); } acc.Description = Date.today().format() + '時点 処理済み'; } // 取引先をupdate update accUpdateMap.values(); } } |
後半ゴチャっとしてしまいました。取引先責任者と取引先の例はよくなかったですね・・
とりあえずハイライトした部分、取引先のインスタンスを生成してIdを設定してあげれば、updateできます。更新したい項目のみ値を設定してあげることで、設定していない項目は更新されません。
最大のメリットはSOQLの発行回数を減らせるということですね。煩雑な処理になってくるとSOQL発行回数(ガバナ制限)にも気を付けないといけないので。
ちなみになんで後半ゴチャっとしてしまったかというと、例えば書きのようにシンプルに書くと
1 2 3 4 5 6 7 8 9 10 11 |
// 取引先の説明を更新 List<Account> accUpdateList = new List<Account>(); for (Contact con : conList) { Account acc = new Account(); acc.Id = con.AccountId; acc.Description = Date.today().format() + '時点 処理済み'; accUpdateList.add(acc); } // 取引先をupdate update accUpdateList; |
こんなエラーで落ちる可能性があります。
System.ListException: Duplicate id in list: XXXXXXXXXXXXXXXXXX |
Listクラスにオブジェクトを格納する際、おなじIdのレコードは入れられないみたいです。
そのためMapで重複がないようにしたのでした。
何気に分かっていなかったので、副産物的な発見でした。