diff --git a/java/working-with-cql/query-api.md b/java/working-with-cql/query-api.md index ac3afc46fc..bcd82c66d9 100644 --- a/java/working-with-cql/query-api.md +++ b/java/working-with-cql/query-api.md @@ -942,6 +942,54 @@ import static com.sap.cds.ql.cqn.CqnLock.Mode.SHARED; Select.from("bookshop.Books").byId(1).lock(SHARED); ``` +#### Wait Strategies + +If the selected rows are already locked by another transaction, by default, the query waits until the lock is released. You can specify a [wait strategy](https://javadoc.io/doc/com.sap.cds/cds4j-api/latest/com/sap/cds/ql/cqn/CqnLock.Wait.Strategy.html) to control whether and how long the query execution shall wait. + +- `DEFAULT` - wait until the lock is released: + + By default, if the selected rows are locked by another transaction, the query waits for the lock to be relased. If the lock is not released within the database's predefined timeout a `CdsLockTimeoutException` is thrown: + ```java + Select.from("bookshop.Books").byId(1).lock(); + ``` +- `WAIT` - wait unless given timeout expires: + ```java + import static com.sap.cds.ql.cqn.CqnLock.Mode.EXCLUSIVE; + + // wait max 10s + Select.from("bookshop.Books").byId(1).lock(EXCLUSIVE, 10); + ``` + +- `NOWAIT` — fail _immediately_ if the rows are already locked: + + ```java + import static com.sap.cds.ql.cqn.CqnLock.Mode.EXCLUSIVE; + import static com.sap.cds.ql.cqn.CqnLock.Wait.NOWAIT; + + Select.from("bookshop.Books").byId(1).lock(EXCLUSIVE, NOWAIT); + ``` + If any target row is locked, a `CdsLockTimeoutException` is thrown without waiting. + +- `SKIP LOCKED` — skip locked rows and return only unlocked rows: + + ```java + import static com.sap.cds.ql.cqn.CqnLock.Mode.EXCLUSIVE; + import static com.sap.cds.ql.cqn.CqnLock.Wait.SKIP_LOCKED; + + Select.from("bookshop.Books") + .where(b -> b.get("stock").gt(0)) + .lock(EXCLUSIVE, SKIP_LOCKED); + ``` + + ::: warning + Rows that are currently locked by other transactions are silently excluded from the result. + ::: + ::: tip + This is useful for queue-like processing where multiple workers consume available items concurrently without blocking each other. + ::: + +#### Restrictions + Not every entity exposed via a CDS entity can be locked with the `lock()` clause. To use the `lock()` clause, databases require that the target of such statements is represented by one of the following: - a single table - a simple view, so that the database can unambiguously identify which rows to lock