初めてのJPA--シンプルで使いやすい、Java EEのデータ永続化機能の基本を学ぶ

Oracle Java & Developers編集部
2015-07-08 17:00:00
  • このエントリーをはてなブックマークに追加

JPAのクエリ言語「JPQL」の基本

 JPAで使用するクエリ言語JPQLについても説明しておきましょう。JPQLは、"SQLのオブジェクト版"とも呼ぶべきもので、SQLを使える人ならば簡単に理解できます。

 例えば、先の「One-to-Many(双方向)」で示した「Cart(注文)」と「Orderline(注文明細)」のケースでJPQLを使うことを考えてみます。このケースにおいて、例えば「田中さんの明細書を引き出す」というSELECT文を書くと、次のようになります。

【リスト3:「田中さんの明細書を引き出す」ためのSELECT文】
select c from Cart c where c.name = ‘田中’

 ご覧のとおり、「c」というオブジェクトを使っている以外は、通常のSQL文とほとんど変わりません。以下に、このクエリ文のポイントを挙げます。

  • cはエンティティ(この例では、Cart)の別名(エイリアス)である
  • SELECT句にエイリアスを指定すると、全件を取得する(この例の場合、Cartのオブジェクト全件を取得する)という意味になる
  • WHERE句などでは、エイリアスのプロパティ(フィールド名)を使って記述する

 また、WHERE句では、下表に示すようなSQLでもおなじみの演算子を利用できます。

【表4:JPQLで使用可能な演算子の例】

演算子 備考
= c.name='山田'

>=
c.price>1000

<=
c.price<=500
<> c.price <> 1000
BETWEEN c.price BETWEEN 100 and 1000
LIKE 文字列の一致を検査する
IN 括弧内のリストに該当するものがあるかどうか
IS NULL  
IS EMPTY  
AND OR NOT()  

 JPQLは、オブジェクト指向言語ならではの優れた特徴も備えています。その1つが、「関係のあるエンティティでは、自動的にJOIN機能が働く」というものです。例えば、次のJPQL文をご覧ください。

【リスト4:JPQLで書いたクエリの例(JOINを省略)】
select o from OrderLine o where o.cart.customer = '田中宏'

 このシンプルさは、JOIN機能が自動的に働くことで実現されています。もしJOINを明示的に使うとしたら、次のような文を書かなくてはなりません。

【リスト5:リスト4と同じ内容を、JOINを明示的に使って書いた例】
select o from OrderLine o join Cart c on o.cart.cartID = c.cartID where o.cart.customer = '田中宏'

 さらに、JPQLではCOUNT、MAXといった集計関数も使うことができます。ただし、エンティティ以外に対して使った場合、取得する値は配列型のObject[]型となり、キャストが必要なため記述が面倒になります。

【リスト6:集計関数を使ったJPQL文の例】
Object[] array = select c.customer, count(c) from OrderLine o join Cart c on o.cart = c group by c

 コーディングを簡単にするには、結果のマッピングを行うための次のようなクラスを作っておくとよいでしょう。

【リスト7:集計関数で取得したオブジェクトのキャストを行うためのユーティリティ・クラス】
package bean; public class Sum{ private String name; private long count; public Sum(String name, long count){ this.name = name; this.count = count; } // setter/getterメソッドなど }

 そのうえで、このクラス(Sum)のコンストラクタで処理結果を受け、List<Sum>に渡すようにすると便利です。


※クリックすると拡大画像が見られます

※クリックすると拡大画像が見られます

 加えて、「SELECT DISTINCT」と「JOIN FETCH」の組み合わせと使うと、例えば「Cartオブジェクトと、それにひも付くOrderLine(複数)を一度に取得する」といったクエリを生成することができます。

【リスト8:Cartオブジェクトと、それにひも付くOrderLine(複数)を一度に取得するためのJPQL文】
select distinct c from Cart c join fetch c.orderLines

 これは、「One-to-Many」の関係における「N+1問題」、つまり「Cartエンティティからすべてのデータを取得しようとすると、CartエンティティごとにOrderlineエンティティを取得するためのSQL文が生成されてしまう」という問題を回避するための書き方です。

 1つ注意点も挙げておきます。JPQLを使う際には、必ずSQLのログを確認することを忘れないでください。その理由は、JPQLからSQLへの変換により、無駄なSQL文が生成される場合があるためです。SQLのログを取るには、JPAの設定ファイルであるpersistence.xmlに次のような設定を記述しておきます。


※クリックすると拡大画像が見られます

JPQLの使い方

 JPQLを使うには、まずエンティティ・クラスにJPQL文を記述します。このとき、プログラム実行時にパラメータの値をセットできるように指定することも可能です。


※クリックすると拡大画像が見られます

 そして、JPQLを実行するメソッドを定義したEJBクラスを作ります。


※クリックすると拡大画像が見られます

 このEJBクラスでエンティティのJPQL文を呼び出してクエリを生成し、パラメータの値をセットするわけです。クエリの実行結果は、getResultListなどのメソッドで受け取ります。

 以上、駆け足となりましたが、JPAの基本的な事項について説明しました。ご覧いただいたように、JPAはとても使いやすく、シンプルなAPIです。これからJava EE開発に取り組む皆さんは、ぜひJPAをご活用ください。

このサイトでは、利用状況の把握や広告配信などのために、Cookieなどを使用してアクセスデータを取得・利用しています。 これ以降ページを遷移した場合、Cookieなどの設定や使用に同意したことになります。
Cookieなどの設定や使用の詳細、オプトアウトについては詳細をご覧ください。
[ 閉じる ]