From 45c07033ac67b929e12437fb8b676a9be65c8444 Mon Sep 17 00:00:00 2001 From: dahajnal Date: Fri, 13 Mar 2026 18:20:01 +0100 Subject: [PATCH 1/3] document skip locked --- java/working-with-cql/query-api.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/java/working-with-cql/query-api.md b/java/working-with-cql/query-api.md index ac3afc46fc..94a8d2096a 100644 --- a/java/working-with-cql/query-api.md +++ b/java/working-with-cql/query-api.md @@ -942,6 +942,35 @@ import static com.sap.cds.ql.cqn.CqnLock.Mode.SHARED; Select.from("bookshop.Books").byId(1).lock(SHARED); ``` +#### Wait Strategies + +By default, if the selected rows are already locked by another transaction, the query waits until the database's predefined timeout expires and then throws a `CdsLockTimeoutException`. You can control this behavior using the `lock(mode, waitStrategy)` method with a `CqnLock.Wait` strategy: + +- `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); + ``` + + Rows that are currently locked by other transactions are silently excluded from the result. 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 From 3fcd2c69081ad964a4cdcc56a770968caf3ca9d4 Mon Sep 17 00:00:00 2001 From: dahajnal Date: Wed, 25 Mar 2026 14:41:10 +0100 Subject: [PATCH 2/3] fix --- java/working-with-cql/query-api.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/java/working-with-cql/query-api.md b/java/working-with-cql/query-api.md index 94a8d2096a..82f36a5dcb 100644 --- a/java/working-with-cql/query-api.md +++ b/java/working-with-cql/query-api.md @@ -944,9 +944,23 @@ Select.from("bookshop.Books").byId(1).lock(SHARED); #### Wait Strategies -By default, if the selected rows are already locked by another transaction, the query waits until the database's predefined timeout expires and then throws a `CdsLockTimeoutException`. You can control this behavior using the `lock(mode, waitStrategy)` method with a `CqnLock.Wait` strategy: +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. -- `NOWAIT` — fail immediately if the rows are already locked: +- `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; From ca27a9b65b4c368ceee4760a8fb57f5d1605410c Mon Sep 17 00:00:00 2001 From: dahajnal Date: Wed, 25 Mar 2026 18:09:35 +0100 Subject: [PATCH 3/3] add boxes --- java/working-with-cql/query-api.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/java/working-with-cql/query-api.md b/java/working-with-cql/query-api.md index 82f36a5dcb..bcd82c66d9 100644 --- a/java/working-with-cql/query-api.md +++ b/java/working-with-cql/query-api.md @@ -981,7 +981,12 @@ If the selected rows are already locked by another transaction, by default, the .lock(EXCLUSIVE, SKIP_LOCKED); ``` - Rows that are currently locked by other transactions are silently excluded from the result. This is useful for queue-like processing where multiple workers consume available items concurrently without blocking each other. + ::: 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