「//fix this/」の記事インデックス

//fix this/ Javaコードの間違いをさがせ!


このシリーズは、あなたのコーディング・スキルを試すコーナーです。毎号オラクルのJavaエバンジェリストたちが、Javaコードに関する難問を出題し、正解と解説を掲載します。是非、毎号チャレンジして貴方のコーディング能力の向上にお役立て下さい。


第7回目 (Java Magazine 2013/Mar-Aprからの出題)


1. 今回のテーマ 「そして再び、JPA」 

Java Persistence API(JPA)にはパラメータ化された SQL とその結果セットの処理方法において、公開されていない意外な事実があります。



2. コード

ある若手プログラマは、JPA を使用して、パラメータ化された SQL クエリとその実行部分をプログラムに追加するよう依頼されました。 コードは次のようになりました。


EntityManager em = ...;
String sql = "select department from emp where fname=? and mname=? and lname=?";
Query query = em.createNativeQuery(sql);
String[] name = new String[3];
for (int i=0; i<3; i++) query.setParameter(i, name[i]);
List departments = query.getResultList();
if (departments == null)
   System.out.println("Not available");
else
   for(String department : departments)
     System.out.println(department);

このコードは正しく動作しませんでした。どこがいけなかったのでしょうか。



3.正しいのはどれ?

上記のコードについて、正しい修正方法を選んでください。

1)createNativeQuery() の代わりに、createQuery() を使用する

2)パラメータの値を一重引用符で囲む

3)パラメータの設定順序を変える

4)部門リストのサイズをチェックする

<ヒント>
JPAは多くの点でJDBCに似ています。






【答え】

今回はちょっとトリッキーでしたね。実は、このコードには 2 つのバグが含まれていたため正解は 3)と 4)です。当たった人はかなりの腕前です!!

3)に関して言うと、ネイティブ SQL にパラメータを指定する場合、インデックスは 0 ではなく1 から始まります。このことは JDBCドキュメントには記載されていますが、JPA ドキュメントには記載されていません。 プログラマはこれに気づかなかったため、Java のコレクションと同様にゼロから始まるインデックスを使用していました。

4)についてですが、query.getResultList() を呼び出すと常に List が返されますが、 結果セットが空である場合は空の List が返されます。 この事実も JPAドキュメントには記載されていません。

正しいコードは次のようになります。


EntityManager em = ...;
String sql = "select department from emp where fname=? and
mname=? and lname=?";
Query query = em.createNativeQuery(sql);
String[] name=new String[3];
for (int i=1; i<4; i++) query.setParameter(i, name[i]);
List departments = query.getResultList();
if (departments.isEmpty())
  System.out.println("Not available");
else
  for(String department : departments)
    System.out.println(department);


<< 第6回へ戻る I 第8回へ進む >>

「//fix this/」の記事インデックス