Part 3: 例外処理の実装例
前回はSalesforceの組み込み例外クラスの概要と使いどころを解説しました。
今回は、それらを実際にどのように扱うのか、具体的なコードサンプルを交えながら解説します。
1. DmlException の実装例
DML操作(insert, update, delete など)が失敗したときに発生する DmlException
を処理する例です。
(1) try-catch
を使った基本的なエラーハンドリング
try {
Account acc = new Account();
insert acc; // Name が必須なのに指定されていないのでエラー
} catch (DmlException e) {
System.debug('DMLエラー発生: ' + e.getMessage());
}
この場合、Name
が必須項目であるため DmlException
が発生し、
System.debug
に "Required fields are missing: [Name]"
というエラーメッセージが出力されます。
(2) どのレコードでエラーが発生したかを特定
try {
List<Account> accounts = new List<Account>{
new Account(Name = 'Test 1'),
new Account(), // これはエラー (Name が空)
new Account(Name = 'Test 3')
};
insert accounts;
} catch (DmlException e) {
for (Integer i = 0; i < e.getNumDml(); i++) {
System.debug('エラー対象レコード ID: ' + e.getDmlId(i));
System.debug('エラー項目: ' + e.getDmlFieldNames(i));
System.debug('エラーメッセージ: ' + e.getDmlMessage(i));
}
}
このコードでは、getDmlId()
, getDmlFieldNames()
, getDmlMessage()
を使って、どのレコードで何が原因のエラーなのかを詳細に取得できます。
2. QueryException の実装例
SOQL クエリで、結果が 0 件または複数件になった場合のエラーを処理する例です。
(1) クエリ結果が 0 件の場合
try {
Account acc = [SELECT Id FROM Account WHERE Name = '存在しない名前'];
} catch (QueryException e) {
System.debug('QueryException 発生: ' + e.getMessage());
}
このコードは List has no rows for assignment to SObject
というエラーを発生させます。
対策として、リストで受け取るようにすると安全です。
List<Account> accList = [SELECT Id FROM Account WHERE Name = '存在しない名前'];
if (accList.isEmpty()) {
System.debug('該当するアカウントが見つかりませんでした');
}
(2) クエリ結果が複数件の場合
try {
Account acc = [SELECT Id FROM Account]; // 1 件以上のレコードがあるとエラー
} catch (QueryException e) {
System.debug('QueryException 発生: ' + e.getMessage());
}
複数レコードが返る場合は List<Account>
で受け取るべきです。
3. CalloutException の実装例
外部 API に対するコールアウトが失敗した場合に発生する CalloutException
の処理方法です。
try {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://invalid-api.com/data');
request.setMethod('GET');
HttpResponse response = http.send(request);
} catch (CalloutException e) {
System.debug('CalloutException 発生: ' + e.getMessage());
}
この例では、API のエンドポイントが無効な場合に CalloutException
が発生します。
対策:
- コールアウト前に
HttpRequest.setTimeout()
でタイムアウト時間を指定する。 -
if(response.getStatusCode() != 200)
でレスポンスのステータスコードをチェックする。
4. LimitException の実装例
LimitException
は catch できない ため、ガバナ制限を意識した実装が必要です。
(1) SOQL クエリの制限
例えば、以下のようなコードは SOQL クエリを 101 回実行しようとしてエラー になります。
for (Integer i = 0; i < 101; i++) {
Account acc = [SELECT Id FROM Account LIMIT 1];
}
対策: SOQL をループ外で 1 回だけ実行する。
List<Account> accList = [SELECT Id FROM Account];
for (Account acc : accList) {
System.debug(acc.Id);
}
(2) DML 操作の制限
以下のコードは DML 操作を 151 回実行しようとしてエラー になります。
for (Integer i = 0; i < 151; i++) {
Account acc = new Account(Name = 'Test ' + i);
insert acc;
}
対策: insert
をループ内で 1 件ずつ実行せず、リストでまとめて DML を実行する。
List<Account> accList = new List<Account>();
for (Integer i = 0; i < 150; i++) {
accList.add(new Account(Name = 'Test ' + i));
}
insert accList;
5. NullPointerException の実装例
NullPointerException
は、null
の変数に対してメソッドを呼び出した場合に発生します。
(1) 発生するケース
String str;
System.debug(str.length()); // NullPointerException
(2) 対策
事前に null
チェックを行う。
if (str != null) {
System.debug(str.length());
} else {
System.debug('変数 str は null です');
}
6. カスタム例外クラスの作成
独自の例外を作成する場合は、Exception
クラスを継承して extends
する。
(1) カスタム例外クラスの定義
public class MyCustomException extends Exception {}
(2) 例外をスローする
try {
throw new MyCustomException('これはカスタム例外です');
} catch (MyCustomException e) {
System.debug(e.getMessage());
}
(3) 既存の例外をラップする
try {
throw new MyCustomException('カスタム例外', new DmlException());
} catch (MyCustomException e) {
System.debug(e.getMessage());
}
まとめ
今回は、例外処理の具体的なコードサンプルを解説しました。
特に DmlException
、QueryException
、CalloutException
、LimitException
などは、Salesforce の開発で頻繁に遭遇するので、しっかりと使いこなせるようにしておきましょう。
次の Part 4 では、さらに 実践的なエラーハンドリングのテクニック や トランザクション管理 について解説します。