JPAで、同じCriteriaなのに違うSQLが生成されることがあって、毎回違う結果を返してくるのでハマりました。
EclipseLink 2.3.2です。
同じテーブルをさすRootを2つ作ると、場合によって解釈が違うという感じです。
つまり
CriteriaQuery cq = em.createQuery(TDUser.class); Root<TDUser> root1 = cq.from(TDUser.class); Root<TDUser> root2 = cq.from(TDUser.class); cq.where(cb.equal(root1.get("id").as(Long.class), 10L); cq.orderBy(cb.asc(root2.get("id")); em.createQuery(cq).getResultList();
のように、whereとorderByで別のRootオブジェクトを使うと、場合によって次の2通りのSQLが生成されることがあります。
select ID, NAME from td_user where ID=10 order by ID
または
select t0.ID, t0.NAME from td_user t0, td_user t1 where t1.ID=10 order by t0.ID
です。
場合によってというか、だいたい2/3の確率で後者です。
もちろん、後者の場合にはwhere句が効かないので、全件取得になってしまいます。
一箇所で記述するときにはRootをちゃんと使いまわすので問題になりにくいですが、便利メソッドを作ってCriteria構築処理が分割されると陥りやすいと思います。
Criteriaは、クエリーを部分的に共通化できるというのが強みなのに、それをやってしまうとハマるというのは非常に困った挙動です。
常にどちらか決まってればいいのだけど。
すごくハマりました。