GORM を使用して次のクエリを実行するにはどうすればよいですか?
select *
from T where id in
(
SELECT id
FROM (
SELECT *
FROM T
WHERE X is NULL
ORDER BY Y DESC
)
WHERE ROWNUM <= 1
)
FOR UPDATE;
私が試しているメソッド呼び出しは次のようになります。
T.findByXIsNull(sort: "Y", order:"desc", lock: true)
ただし、次のエラーが発生しました (Oracle 11gR2): ORA-02014: DISTINCT、GROUP BY などのビューから FOR UPDATE を選択できません。
失敗していると思われる理由は、Hibernate が次のクエリに変換しているためです。
SELECT *
FROM (
SELECT *
FROM T
WHERE X is NULL
ORDER BY Y DESC
)
WHERE ROWNUM <= 1 FOR UPDATE;
このクエリは、ROWNUM を制限する句に FOR UPDATE を直接適用しようとしています。上の例のように、FOR UPDATE を適用するには、ラッパーの select ステートメントが必要です (ここで説明します: How to solve ORA-02014: cannot select FOR UPDATE from view with DISTINCT, GROUP BY )。これはどのように達成できますか?
アップデート1
order by
これは、との両方rownnum <= ?
が指定されている場合にクエリを生成する際の GORM/Hibernate のバグのようです。次の両方が個別に機能します。
T.findByXIsNull(sort: "Y", order:"desc")
T.findByXIsNull(lock: true)
しかし、一緒T.findByXIsNull(sort: "Y", order:"desc", lock:true)
に ORA-02014 エラーで失敗します。修正は、この投稿の冒頭で説明したように、Hibernate が SQL を生成することであり、ロックを別の外側の select ステートメントにラップします。ただし、私が気付いていない回避策があるかもしれません。