GlassFish勉強会で金魚本に載ってないJPQLの話をしてきた #GlassFishJP

ちなみに金魚本というのは以下の本です。

Beginning Java EE 6~GlassFish 3で始めるエンタープライズJava (Programmer's SELECTION)

Beginning Java EE 6~GlassFish 3で始めるエンタープライズJava (Programmer's SELECTION)


スライドは公開しましたが、勉強会にて口頭で補ったことが多かったので補足します。

JPQLとは

JPQLとはJPAで使われるクエリ記述言語です。
Entity および Entity 間のリレーションに対して問い合わせを行う事ができます。
SQLを直接記載しないため、データベースごとのSQL方言等を意識する必要がありません。*1
そのため、可搬性に優れたアプリケーションを作成することが出来ます。

JPQLでは主に複数のエンティティに対して同一の操作を行う時に使います。
JPQLではSELECT/UPDATE/DELETEの処理が行うことができ、予約後に関しては大文字小文字は区別しません。

ここから先に関しては、金魚本を読んでいることを前提としています。
しかしながら、SQLの知識が十分にあれば読んでいなくても理解することは出来るでしょう。

なお、すべてJPA2.0の内容です。

金魚本に載っていないけど 使えるJPQLの構文

JPQLでサポートされている構文のうち金魚本に載っていないものについて解説します。

副問い合わせ

副問い合わせが使用出来ることまでは金魚本に記載してあるのですが、副問い合わせの前にALL,ANY,SOMEのキーワードをつけれることに関しては記載されていません。
それぞれのキーワードの意味は以下のとおりです。

  • ALL -> 副問い合わせすべてに合致する
  • ANY -> 副問い合わせの結果の一つ以上に合致する
  • SOME -> 副問い合わせの結果の一つ以上に合致する

SOMEとANYは同じ意味です。

副問い合わせ(EXISTS句)

副問い合わせの結果に含まれていることを表します。
このスライドの例ではNOTを付けない場合はspouseもemployeeに含まれるemployeeの一覧を返します。

相関副問い合わせ

相関副問い合わせを行うこともできます。

結合

SQLと違うのは、SQLではJOINの後にUSINGもしくはONを使用して結合するカラムを指定していましたが、JPQLではエンティティの関連を利用してJOINを行うことです。
JPQLでは左外部結合もしくは内部結合のみがサポートされます。

Fetch Join



このスライドは、コーディング時に動かない時のTipsになります。
JPAの関連付けにはEAGERフェッチとLAZYフェッチというのがあるのですが、LAZYフェッチにした場合にはトランザクション境界外にてうまく動作しないことがあります。
その場合にLAZYフェッチを強制的にEAGERフェッチに変更する方法を示したものです。
何のことかわからない場合は、10ページ目のスライドに記載されたエラーメッセージを見た時に使用するものだとだけ覚えておいてください。

コンストラクタ式



個人的にJPQLの中で一番重要だと思っているのがこのコンストラクタ式です。
通常、Entityの操作をする場合、Entityのすべての値をデータベースから取得してしまいます。
1Entityであれば問題になることははずありませんが、数十、数百と取得する場合に性能面で問題となることがあります。
その場合に、必要なカラムのみをデータベースから取得することで性能劣化を抑えることができます。
そのために使用するのがこのコンストラクタ式です。

Entityを介さずにDTOに変換することができます。
スライドにも書いてあるように主な利用用途はサマリーを取得することです。


JPQL使用上の注意点

JPQL使用上の注意点として2点あげました。

すでにメモリ上に取得されたエンティティに対してはJPQLの操作は行われない

JPQLはメモリ上のオブジェクトに対しては影響を及ぼしません。
JPQLが実行される時は即座にSQLに変換されデータベースに対して反映が行われると考えたほうが良いです。
この例だと最後のJPQLが実行されたあとはデータベースとメモリ上のエンティティの状態は乖離していることになります。
JPQLとエンティティへの値の操作を併用する場合は実行順序に気をつけてください。

@VersionアノテーションはJPQLの実行には影響を及ぼさない

@VersionアノテーションJPAで楽観ロックを実装するために使用されるアノテーションです。
@Versionが付けられたカラムはEntityの状態が変更されるたびにインクリメントされていきます。
しかしながら、JPQLを使用する場合は@Versionの更新が自動では行われません。
このスライドの例のように他のEntity操作へ状態が変更されたことを通知するために手動でインクリメントする必要があります。
また、必要に応じてwhere句の条件とすることも検討してください。

JPQLの予約語

JPQLの予約語の一覧です。
今回説明していないものでもSQLに慣れていれば使用出来るものも多いと思うので、試してみてください。
ほとんどのものはSQLの時と同じ意味です。


今回の内容について


基本的に全てJSRに記載されている内容です。
今回説明していないものに関しても色々と記載されているので、目を通す価値はあると思います。
日本語の資料では、少し古い(JPA1.0の内容)ですが、マスタリングJavaEE5の記載内容が一番詳しいので、そちらを参照するのが良いでしょう。

マスタリングJavaEE5 第2版 (DVD付) (Programmer’s SELECTION)

マスタリングJavaEE5 第2版 (DVD付) (Programmer’s SELECTION)

*1:方言はJPAを実装したプロバイダが吸収してくれます