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にする、って設定もアリかな、と思いました。