How would I accomplish the following query with 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;
The method call I'm trying looks like this:
T.findByXIsNull(sort: "Y", order:"desc", lock: true)
However, I got the following error (Oracle 11gR2): ORA-02014: cannot select FOR UPDATE from view with DISTINCT, GROUP BY, etc.
The reason I believe it's failing is because Hibernate is converting it to the following query:
SELECT *
FROM (
SELECT *
FROM T
WHERE X is NULL
ORDER BY Y DESC
)
WHERE ROWNUM <= 1 FOR UPDATE;
This query is trying to apply the FOR UPDATE directly on the clause limiting rownum. A wrapper select statement is needed to apply the FOR UPDATE, as in my example at the top (and discussed here: How to solve ORA-02014: cannot select FOR UPDATE from view with DISTINCT, GROUP BY). How can this be accomplished?
Update1
Looks like this is a bug in GORM/Hibernate in generating the query when both order by
and rownnum <= ?
is specified. Both of the following work individually:
T.findByXIsNull(sort: "Y", order:"desc")
T.findByXIsNull(lock: true)
But together T.findByXIsNull(sort: "Y", order:"desc", lock:true)
they fail with the ORA-02014 error. The fix would be for Hibernate to generate the SQL as I described at the top of this post, which wraps the lock into another outer select statement. However, there may be a workaround that I'm not aware of.