0

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 ステートメントにラップします。ただし、私が気付いていない回避策があるかもしれません。

4

1 に答える 1