【Apex】SOQL結果が0件の時の例外になるパターンと例外にならないパターンについて

実務でapexをみててレコードを1件だけ受け取りたいときにListを使用しているコードをみた
何故か気になったのでしらべた結果をまとめてみる

結論

  • 単一sObject代入:0件だと QueryExceptionList has no rows for assignment to SObject
  • List代入:0件でも 空リスト(例外なし、nullでもない)

詳しく

どうやら

Account a = [SELECT Id FROM Account WHERE Name = 'X' LIMIT 1];

のようにオブジェクトに代入しようとするコードがあり、結果が0件数だとQueryExceptionが発生して例外が投げられてしまう

しかし、

List rows = [SELECT Id FROM Account WHERE Name = 'X'];
// 0件 → rows.size() == 0、例外なし、rows自体はnullではない

のようにListで受け取るとExceptionにならず空リストが残るだけだかとなりからの場合にExceptionをなげず処理をおこないたい場合など柔軟に処理をかける

Listで受け取ってかつ0件の時にExceptionを投げたい場合

Listで受け取るが0件でExceptionを投げたい場合は以下のようにコードを記載することでExceptionを投げれる

List rows = [SELECT Id, Name FROM Account WHERE Name = :name LIMIT 1];
if (rows.isEmpty()) {
  throw new AuraHandledException('Account not found');
}
Account a = rows[0];

しかし、システム例外にはnewを使えないものもあり、場合によってはExceptionを継承したクラスを自分で実装する必要がでてくる、、(例外クラスのテストクラスとかってどんな感じなんだろうか、、)

おまけ:SOQLで文字列を使うときの注意

必ずバインド変数を使い、文字列連結をしない

文字列連携を使ってクエリ文を作成してからSOQLを使用してもクエリ実行は可能だが、エスケープ漏れなどが発生しやすい

String idStr = /* 外部入力など */;
List rows = [SELECT Id FROM Account WHERE Id = :idStr]; // OK
// '… WHERE Id = \'' + idStr + '\'' ← NG(エスケープ漏れ・バグの温床)
null/空白を早期リターンで弾く

バインド変数をSOQLで使用する際はバインド変数のnullチェックを事前に行うことによって予期せぬ不具合を防ぐことができる

if (String.isBlank(idStr)) {
// 実行しない・return・適切な例外など
}

Follow me!

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

PAGE TOP