失敗
EJB 2.0/2.1 の 検索メソッド (ejbFind や ejbSelect) では、条件に合うエンティティが検出されない場合、javax.ejb.ObjectNotFoundException (javax.ejb.FinderException のサブクラス) がスローされました。
しかし、EJB 3.0 では null が返されることもあれば、例外がスローされることもあります。 いったい、どうなってるの?
環境
このレポートは、以下の環境について記述したものです。
| JDK | JDK 6 |
| AP サーバ | JBoss Application Server 4.0.5 GA (With EJB 3.0) |
原因
EJB 3.0 でエンティティを検索するには、以下のいずれかのメソッドを使用することになります。
- EntityManager.find メソッドによる検索
- Query.getResultList メソッドによる検索
- Query.getSingleResult メソッドによる検索
これら 3 つのメソッドはエンティティ未検出時の振る舞いが異なりますので、それぞれに対応したコードを記述しなければなりません。
解決策
まず、エンティティ検索を行う 3 つのメソッドについて、エンティティが検出されなかった場合の振る舞いを理解します。 その上で、必要に応じて未検出時のコードを挿入することになります。
(1) EntityManager.find メソッドによる検索
EntityManager.find メソッドは、主キーでエンティティを検索します。 エンティティが検出されない場合は、null が返されます。
| シグネチャ | <T> T EntityManager.find(Class<T> entityClass, Object pk) |
| 説明 | 主キーでエンティティを検索します。 |
| 戻り値 | 主キーが示すエンティティ (未検出の場合は null) |
| 例外 |
java.lang.IllegalStateException - EntityManager がクローズされている場合 java.lang.IllegalArgumentException - エンティティの型または主キーの型が正しくない場合 |
EntityManager.find メソッドの使用例を、以下に示します。
// 主キー検索 (em は EntityManager 型の変数)
XxxEntity e = em.find(XxxEntity.class, "100");
// 未検出であるか判定
if (e == null) {
}
(2) Query.getResultList メソッドによる検索
Query.getResultList メソッドは、任意の条件でエンティティを検索します。 エンティティが検出されない場合は、空のリストが返されます。
| シグネチャ | List Query.getResultList() |
| 説明 | 問い合わせを実行し、任意の数のエンティティを取得します。 |
| 戻り値 | 条件に合うエンティティを格納したリスト (未検出の場合は空のリスト) |
| 例外 | java.lang.IllegalStateException - Query オブジェクトに設定されている EJB-QL が SELECT 文でない場合 |
Query.getResultList メソッドの使用例を、以下に示します。
// クエリの作成 (em は EntityManager 型の変数)
Query q = em.createQuery("SELECT x FROM XxxEntity x WHERE x.val = ?1");
// パラメータの設定
q.setParameter(1, "ABC");
// 条件に合うエンティティをすべて取得
List<XxxEntity> result = q.getResultList();
// 未検出であるか判定
if (result.size() < 1) {
}
(3) Query.getSingleResult メソッドによる検索
Query.getSingleResult メソッドは、任意の条件で単一エンティティを検索します。 エンティティが検出されない場合は、javax.persistence.NoResultException がスローされます。
| シグネチャ | Object Query.getSingleResult() |
| 説明 | 問い合わせを実行し、エンティティを1つ取得します。 |
| 戻り値 | 条件に合うエンティティ |
| 例外 |
javax.persistence.NoResultException - エンティティが検出されなかった場合 javax.persistence.NonUniqueResultException - エンティティが 2 件以上検出された場合 java.lang.IllegalStateException - Query オブジェクトに設定されている EJB-QL が SELECT 文でない場合 |
Query.getSingleResult メソッドの使用例を、以下に示します。
try {
// クエリの作成 (em は EntityManager 型の変数)
Query q = em.createQuery("SELECT x FROM XxxEntity x WHERE x.pk = ?1");
// パラメータの設定
q.setParameter(1, "100");
// 条件に合うエンティティを1つ取得
XxxEntity result = (XxxEntity) q.getSingleResult();
} catch (NoResultException ex) {
// 未検出である場合
}
