Part 2: 組み込み例外クラスの詳細

## **Part 2: 組み込み例外クラスの詳細**

ここでは、Salesforceが提供している組み込みの例外クラスについて、具体的な内容と実装例を交えて説明します。

---

### **1. 各例外クラスの概要と使いどころ**

- **AsyncException**  
  非同期処理（Futureメソッド、Queueable、バッチ処理など）のエンキュー失敗時に発生します。  
  *例:* 非同期呼び出しがキューに登録できなかった場合など。

- **BigObjectException**  
  Big Objectのレコードにアクセスまたは挿入を試みた際に、接続タイムアウトなどの問題が発生すると投げられます。  
  *例:* 大量のデータを操作する処理中に発生するタイムアウトエラー。

- **CalloutException**  
  外部システムへのWebコールアウトで、接続失敗やタイムアウトなどが起こる場合に使用されます。  
  *例:* 外部APIへのリクエスト時にエラーが発生した場合。

- **DmlException**  
  DML操作（insert、update、deleteなど）に問題があるときに発生します。  
  *具体例:* 必須項目が欠落している状態で`insert`を試みた場合。  
  ```apex
  try {
      Account a = new Account(); // Nameは必須項目だと仮定
      insert a;
  } catch(DmlException e) {
      System.debug('DMLエラー: ' + e.getMessage());
  }
  ```

- **EmailException**  
  メール送信処理で失敗が発生した場合に投げられます。  
  *例:* メールアドレスの形式が不正な場合など。

- **ExternalObjectException**  
  外部オブジェクトへのアクセス中に、接続タイムアウトやその他の接続問題が発生した場合に利用されます。

- **InvalidParameterValueException**  
  メソッドに無効なパラメータを渡した場合に発生します。  
  *例:* 期待していない形式のパラメータを使用した場合。

- **LimitException**  
  ガバナ制限（CPU時間、DML操作数、SOQLクエリ数など）を超えたときに発生します。  
  ※この例外はキャッチすることができませんので、事前にガバナ制限を意識した実装が必要です。

- **JSONException**  
  JSONのパースや生成中にエラーが発生した場合に使われます。  
  *例:* 不正なJSON形式の文字列をパースしようとした場合。

- **ListException**  
  リストの範囲外アクセス（インデックスエラー）など、リスト操作に関する問題を示します。  
  *例:* 存在しないインデックスにアクセスしようとする場合。

- **MathException**  
  0による除算など、算術演算のエラーが起きたときに発生します。  
  ```apex
  try {
      Integer result = 10 / 0;
  } catch(MathException e) {
      System.debug('算術演算エラー: ' + e.getMessage());
  }
  ```

- **NoAccessException**  
  アクセス権がないレコードにアクセスしようとしたときに発生します。  
  *例:* ユーザーが閲覧権限のないデータにアクセスした場合。

- **NoDataFoundException**  
  既に削除されたレコードや存在しないデータへアクセスしようとした場合に投げられます。

- **NullPointerException**  
  nullの参照に対してメソッドやプロパティを呼び出すと発生します。  
  ```apex
  try {
      String s;
      System.debug(s.length());
  } catch(NullPointerException e) {
      System.debug('Nullポインタ例外発生: ' + e.getMessage());
  }
  ```

- **TypeException**  
  型変換に失敗したときに発生します。  
  *例:* `Integer.valueOf('a')` のような不正な変換。

- **QueryException**  
  SOQLクエリに関するエラーを示します。  
  たとえば、以下のようなコードではエラーになります。
  ```apex
  try {
      // 存在しない名前のレコードを単一のsObject変数に代入しようとする
      Account a = [SELECT Id FROM Account WHERE Name = '存在しない名前'];
  } catch(QueryException e) {
      System.debug('QueryException発生: ' + e.getMessage());
  }
  ```
  ※クエリ結果が0件や複数件の場合、単一のsObject変数に代入すると例外が発生します。対策としては、リスト型変数に代入する方法があります。

---

### **2. Exceptionクラスで利用できるメソッド**

Salesforceの例外クラスは、例外の原因や詳細情報を取得するための便利なメソッドが用意されています。

- **一般的なメソッド**
  - `getCause()`  
    → 例外の根本原因（元となった例外オブジェクト）を取得します。
  - `getLineNumber()`  
    → 例外が発生したコードの行番号を返します。
  - `getMessage()`  
    → エラーメッセージ（理由）を取得します。
  - `getStackTraceString()`  
    → スタックトレース情報（例外発生の経緯）を文字列として返します。
  - `getTypeName()`  
    → 例外のクラス名（例: DmlException, QueryException）を取得します。
  - `initCause(Exception e)`  
    → 他の例外を原因として設定できます。
  - `setMessage(String msg)`  
    → エラーメッセージを上書き設定できます。

- **DML例外専用のメソッド**
  - `getDmlFieldNames(Integer index)`  
    → エラーが発生したレコードで問題となった項目名のリストを取得します。
  - `getDmlId(Integer index)`  
    → エラー対象のレコードIDを取得します。
  - `getDmlMessage(Integer index)`  
    → レコードに対するエラーメッセージを取得します。
  - `getNumDml()`  
    → エラーが発生したDML操作における、対象レコードの数を返します。

---

### **3. 組み込み例外クラスの選び方**

どの例外クラスを利用すべきかは、発生するエラーの性質によります。たとえば：  
- **DML操作に失敗した場合**は、必ず`DmlException`で捕捉し、エラー原因となった項目やレコード情報をログに残すと、後続のデバッグが容易になります。  
- **SOQLの実行時**は、クエリ結果が予期せず0件または複数件の場合に`QueryException`が発生するため、結果をリストで受け取るか、`try-catch`で囲むと良いでしょう。  
- **ガバナ制限**に達した場合は`LimitException`が発生しますが、これはキャッチできないため、事前の設計や実装時のチェックが重要です。

---

これで組み込み例外クラスの基本的な役割と、各例外の使いどころが理解できたと思います。  
次の **Part 3** では、具体的な実装例を交えた例外処理のコードサンプルについて解説していきます。