JPQL(EclipseLink)でパラメータをbindする/しないの話
今、EclipseLinkでJPQL使って開発してます。
SQLのログを出しているとJPQLに埋め込んだ定数もパラメータ化されているのがちょっと気持ち悪いなと思ってたんですが、動作には問題なかったので、特に気にしてませんでした。
エラーとなる場合もある
ところが、どうもうまくいかない場合もあるようです。
続・JPQLでハマった話 - Java EE 事始め!
このブログでは起こった問題と回避策が紹介されています。
ここで紹介されているようにpersistence.xmlに
<property name="eclipselink.logging.level.sql" value="FINE"/> <property name="eclipselink.logging.parameters" value="true"/> <property name="eclipselink.jdbc.bind-parameters" value="false"/>
とすると、確かに値がSQLに埋め込まれた状態で発行されるようです。
これは、手元でSQLの実行結果を確認するのも楽ですね。
気になること
ただ、この設定をするとsetParameterメソッドでセットした値もSQLに埋め込まれてしまうため注意が必要です。
多くの場合は問題ないと思いますが、ちょっと気になった点があるので一応書いておきます。
Oracle等の一部のRDBMSではクエリの実行計画をキャッシュとして保持します。
SQLにプレースホルダをセットして値が変わるところだけをパラメータ化しておけば値が変わってもこのキャッシュが効きますが、埋め込まれてしまうとキャッシュが効きません。
パラメータ化クエリ | Use The Index, Luke!
実際にこのキャッシュが効かなくなることでDBが重くなるようなことはほとんどないとは思いますが、パラメータ化するかどうかはJPQL毎に設定する、というのもアリかと思います。
先のブログ内にあるリンクを見るとクエリごとにHintとして設定できるようです。
jdbc.bind-parameters | EclipseLink 2.5.x Java Persistence API (JPA) Extensions Reference
query.setHint(QueryHints.BIND_PARAMETERS, HintValues.TRUE); //もしくは @QueryHint(name=QueryHints.BIND_PARAMETERS, value=HintValues.TRUE);
なので、persistence.xmlではtrue(デフォルト)にしておいて、エラーになるところだけHintでfalseを設定するか、persistence.xmlではfalseにしておいて実効計画のキャッシュを効かせたいところだけHintをtrueにする、って設定もアリかな、と思いました。