Apex のデータについて知っておくべきこと
- Null 以外の必須項目値と Null 項目
- 新規レコードの挿入または既存のレコードの必須項目の更新を行う場合、すべての必須項目に null 以外の値を指定する必要があります。
- SOAP API とは異なり、Apex では、sObject レコードの fieldsToNull 配列を更新せずに、項目値を null に変更できます。多くの SOAP プロバイダで null 値の処理が統一されていないため、API ではこの配列に更新する必要があります。Apex は Lightning プラットフォーム上のみで実行されるため、この回避策は不要です。
- DML は一部の sObject でサポートされていない
- DML 操作は、特定の sObject ではサポートされていません。「DML 操作をサポートしない sObject」を参照してください。
- 文字列項目の切り捨てと API バージョン
- 項目に割り当てた文字列値が長すぎる場合、API バージョン 15.0 以降を使用して保存 (コンパイル) した Apex クラスとトリガにはランタイムエラーが発生します。
- DML 操作を有効にする sObject プロパティ
- sObject レコードを挿入、更新、削除、復元できるようにするには、sObject の対応するプロパティ (createable、updateable、deletable、undeletable) を true に設定する必要があります。
- ID 値
- insert ステートメントは、すべての新規 sObject レコードの ID 値を自動的に設定します。すでに ID がある (つまり、すでに組織のデータに存在している) レコードを挿入すると、エラーが発生します。詳細は、「Lists」 を参照してください。
- insert および update ステートメントは、レコードの各バッチに重複 ID 値がないかどうか確認します。重複がある場合、最初の 5 つが処理されます。6 番目とその他すべての重複 ID については、これらのエントリの SaveResult が、次のようなエラーでマークされます。Maximum number of duplicate updates in one batch (5 allowed).Attempt to update Id more than once in this API call: number_of_attempts.
- 更新された sObject レコードの ID は update ステートメントで変更できませんが、関連レコード ID は変更できます。
- 一意制約のある項目
- 一意制約のある項目を含む一部の sObject では、重複する sObject レコードを挿入するとエラーになります。たとえば、同じ名前の複数の CollaborationGroup sObject を挿入すると、CollaborationGroup レコードには一意の名前が必要なためエラーになります。
- 自動的に設定されるシステム項目
- 新規レコードを挿入すると、CreatedDate、CreatedById、SystemModstamp などのシステム項目が自動的に更新されます。これらの値を Apex で明示的に指定することはできません。同様に、レコードを更新すると、LastModifiedDate、LastModifiedById、SystemModstamp などのシステム項目が自動的に更新されます。
- DML ステートメントで処理される最大レコード数
- 1 つの insert、update、delete、undelete メソッドには、最大 10,000 個の sObject レコードを渡すことができます。
各 upsert ステートメントは、レコードの挿入とレコードの更新という 2 つの操作で構成されます。これらの各操作は、insert と update のランタイム制限でそれぞれ制限されます。たとえば、10,000 を超えるレコードを更新/挿入し、すべてが更新中の場合、エラーが発生します(「実行ガバナと制限」を参���してください)。
- 更新/挿入と外部キー
- sObject レコードが参照項目として設定されている場合、sObject レコードを更新/挿入するために外部キーを使用できます。詳細は、『Salesforce のオブジェクトリファレンス』の「データ型」を参照してください。
- 複数のオブジェクト種別のレコードの作成
-
SOAP API と同様に、API バージョン 20.0 以降では、1 回の DML コールで、カスタムオブジェクトを含む複数のオブジェクト種別のレコードを Apex で作成できます。たとえば、取引先責任者と取引先を 1 回のコールで作成できます。1 回のコールで、最大 10 個の種別のオブジェクトのレコードを作成できます。
レコードは、sObject 入力配列に入力された順序で保存されます。親子リレーションのある新規レコードを入力する場合は、配列内で親レコードを子レコードよりも前にする必要があります。たとえば、取引先責任者と取引先を同じコールで作成し、取引先責任者が取引先を参照する場合は、配列内の取引先のインデックスが取引先責任者のインデックスよりも小さくなるようにします。取引先責任者は、[外部 ID] 項目を使用して取引先を参照します。
同じコールの中で、同じオブジェクト種別の別のレコードを参照するレコードは追加できません。たとえば、取引先責任者オブジェクトに、別の取引先責任者への参照である [上司] 項目があるとします。一方の取引先責任者が [上司] 項目を使用して、入力配列の別の取引先責任者を参照する場合、1 回のコールでこの両方の取引先責任者を作成することはできません。作成済みの別の取引先責任者を参照する取引先責任者を作成することは可能です。
Salesforce では、複数のオブジェクト種別のレコードが複数のチャンクに分割されます。チャンクとは入力配列のサブセットで、レコードがオブジェクト種別ごとにまとめられます。データは、チャンク単位でコミットされます。チャンク内のレコードに関連する Apex トリガは、チャンクごとに 1 回起動されます。次の一連のレコードを含む sObject 入力配列があるとします。
1account1, account2, contact1, contact2, contact3, case1, account3, account4, contact4Salesforce は、レコードを次の 5 つのチャンクに分割します。
- account1, account2
- contact1, contact2, contact3
- case1
- account3, account4
- contact4
コールごとに最大 10 個のチャンクを処理できます。sObject 配列に含まれるチャンクが 10 個よりも多い場合、レコードを複数のコールに分けて処理する必要があります。この機能についての詳細は、『SOAP API 開発者ガイド』の「オブジェクト種別が異なるレコードの作成」を参照してください。
- DML およびナレッジのオブジェクト
- ナレッジ記事 (カスタムの FAQ__kav 記事タイプなどの KnowledgeArticleVersion タイプ) に対して DML コードを実行する場合は、実行ユーザにナレッジユーザ機能のライセンスが必要です。このライセンスがない場合、ナレッジ記事に対する DML 操作を含むクラスメソッドをコールしたときにエラーが生じます。システム管理者ではなく、ナレッジユーザ機能のライセンスもない実行ユーザがクラスのメソッドをコールすると、コールされたメソッドにナレッジ記事の DML コードが含まれず、そのクラスの別のメソッドに含まれている場合でも、エラーが発生します。たとえば、次のクラスには 2 つのメソッドが含まれ、そのうちの 1 つのみがナレッジ記事に対して DML を実行します。管理者でもナレッジユーザでもないユーザが doNothing メソッドをコールすると、DML operation UPDATE not allowed on FAQ__kav というエラーが表示されます。
-
1public class KnowledgeAccess { 2 3 public void doNothing() { 4 } 5 6 public void DMLOperation() { 7 FAQ__kav[] articles = [SELECT Id FROM FAQ__kav WHERE PublishStatus = 'Draft' and Language = 'en_US']; 8 update articles; 9 } 10 11} - 回避策として、次のように、DML ステートメントへの入力配列を FAQ__kav 記事の配列から汎用の sObject 種別の配列にキャストします。
-
1public void DMLOperation() { 2 FAQ__kav[] articles = [SELECT id FROM FAQ__kav WHERE PublishStatus = 'Draft' and Language = 'en_US']; 3 update (sObject[]) articles; 4}