Add Query.withLock(LockType) and withLock(LockType, LockWait) (#2116)

Add Query.withLock(LockType) and withLock(LockType, LockWait)
This commit is contained in:
Rob Bygrave
2020-12-01 21:31:53 +13:00
committed by GitHub
parent f6c4024ae5
commit c66875449b
8 changed files with 139 additions and 7 deletions
@@ -169,14 +169,38 @@ public interface ExpressionList<T> {
*/
UpdateQuery<T> asUpdate();
/**
* Execute the query with the given lock type and WAIT.
* <p>
* Note that <code>forUpdate()</code> is the same as
* <code>withLock(LockType.UPDATE)</code>.
* <p>
* Provides us with the ability to explicitly use Postgres
* SHARE, KEY SHARE, NO KEY UPDATE and UPDATE row locks.
*/
Query<T> withLock(Query.LockType lockType);
/**
* Execute the query with the given lock type and lock wait.
* <p>
* Note that <code>forUpdateNoWait()</code> is the same as
* <code>withLock(LockType.UPDATE, LockWait.NOWAIT)</code>.
* <p>
* Provides us with the ability to explicitly use Postgres
* SHARE, KEY SHARE, NO KEY UPDATE and UPDATE row locks.
*/
Query<T> withLock(Query.LockType lockType, Query.LockWait lockWait);
/**
* Execute using "for update" clause which results in the DB locking the record.
*/
Query<T> forUpdate();
/**
* Deprecated - migrate to withLock().
* Execute using "for update" with given lock type (currently Postgres only).
*/
@Deprecated
Query<T> forUpdate(Query.LockType lockType);
/**
@@ -188,8 +212,10 @@ public interface ExpressionList<T> {
Query<T> forUpdateNoWait();
/**
* Deprecated - migrate to withLock().
* Execute using "for update nowait" with given lock type (currently Postgres only).
*/
@Deprecated
Query<T> forUpdateNoWait(Query.LockType lockType);
/**
@@ -201,8 +227,10 @@ public interface ExpressionList<T> {
Query<T> forUpdateSkipLocked();
/**
* Deprecated - migrate to withLock().
* Execute using "for update skip locked" with given lock type (currently Postgres only).
*/
@Deprecated
Query<T> forUpdateSkipLocked(Query.LockType lockType);
/**
+36 -6
View File
@@ -184,7 +184,8 @@ public interface Query<T> {
*/
enum LockType {
/**
* The default lock type - See PlatformConfig.forUpdateNoKey option.
* The default lock type being either UPDATE or NO_KEY_UPDATE based on
* PlatformConfig.forUpdateNoKey configuration (Postgres option).
*/
DEFAULT,
@@ -194,17 +195,17 @@ public interface Query<T> {
UPDATE,
/**
* FOR NO KEY UPDATE.
* FOR NO KEY UPDATE (Postgres only).
*/
NO_KEY_UPDATE,
/**
* FOR SHARE UPDATE.
* FOR SHARE (Postgres only).
*/
SHARE,
/**
* FOR KEY SHARE UPDATE.
* FOR KEY SHARE (Postgres only).
*/
KEY_SHARE
}
@@ -1643,40 +1644,69 @@ public interface Query<T> {
*/
String getGeneratedSql();
/**
* Execute the query with the given lock type and WAIT.
* <p>
* Note that <code>forUpdate()</code> is the same as
* <code>withLock(LockType.UPDATE)</code>.
* <p>
* Provides us with the ability to explicitly use Postgres
* SHARE, KEY SHARE, NO KEY UPDATE and UPDATE row locks.
*/
Query<T> withLock(LockType lockType);
/**
* Execute the query with the given lock type and lock wait.
* <p>
* Note that <code>forUpdateNoWait()</code> is the same as
* <code>withLock(LockType.UPDATE, LockWait.NOWAIT)</code>.
* <p>
* Provides us with the ability to explicitly use Postgres
* SHARE, KEY SHARE, NO KEY UPDATE and UPDATE row locks.
*/
Query<T> withLock(LockType lockType, LockWait lockWait);
/**
* Execute using "for update" clause which results in the DB locking the record.
* <p>
* The same as <code>withLock(LockType.UPDATE, LockWait.WAIT)</code>.
*/
Query<T> forUpdate();
/**
* Execute using "for update" with given lock type (currently Postgres only).
*/
@Deprecated
Query<T> forUpdate(LockType lockType);
/**
* Execute using "for update" clause with "no wait" option.
* <p>
* This is typically a Postgres and Oracle only option at this stage.
* </p>
* <p>
* The same as <code>withLock(LockType.UPDATE, LockWait.NOWAIT)</code>.
*/
Query<T> forUpdateNoWait();
/**
* Execute using "for update nowait" with given lock type (currently Postgres only).
*/
@Deprecated
Query<T> forUpdateNoWait(LockType lockType);
/**
* Execute using "for update" clause with "skip locked" option.
* <p>
* This is typically a Postgres and Oracle only option at this stage.
* </p>
* <p>
* The same as <code>withLock(LockType.UPDATE, LockWait.SKIPLOCKED)</code>.
*/
Query<T> forUpdateSkipLocked();
/**
* Execute using "for update skip locked" with given lock type (currently Postgres only).
*/
@Deprecated
Query<T> forUpdateSkipLocked(LockType lockType);
/**
@@ -486,6 +486,16 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
return query.filterMany(manyProperty).where(expressions, params);
}
@Override
public Query<T> withLock(Query.LockType lockType) {
return query.withLock(lockType);
}
@Override
public Query<T> withLock(Query.LockType lockType, Query.LockWait lockWait) {
return query.withLock(lockType, lockWait);
}
@Override
public Query<T> forUpdate() {
return query.forUpdate();
@@ -491,6 +491,16 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
return exprList.findOneOrEmpty();
}
@Override
public Query<T> withLock(Query.LockType lockType) {
return exprList.withLock(lockType);
}
@Override
public Query<T> withLock(Query.LockType lockType, Query.LockWait lockWait) {
return exprList.withLock(lockType, lockWait);
}
@Override
public Query<T> forUpdate() {
return exprList.forUpdate();
@@ -544,6 +544,16 @@ class DefaultFetchGroupQuery<T> implements SpiFetchGroupQuery<T> {
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
}
@Override
public Query<T> withLock(LockType lockType) {
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
}
@Override
public Query<T> withLock(LockType lockType, LockWait lockWait) {
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
}
@Override
public Query<T> forUpdate() {
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
@@ -963,6 +963,16 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
return this;
}
@Override
public Query<T> withLock(LockType lockType) {
return setForUpdateWithMode(LockWait.WAIT, lockType);
}
@Override
public Query<T> withLock(LockType lockType, LockWait lockWait) {
return setForUpdateWithMode(lockWait, lockType);
}
@Override
public DefaultOrmQuery<T> forUpdate() {
return setForUpdateWithMode(LockWait.WAIT, LockType.DEFAULT);
@@ -55,7 +55,7 @@ public class TestQueryForUpdatePostgresLock extends BaseTestCase {
private void lockArticle(Integer id) {
timePreLock = System.currentTimeMillis();
log.info("lock start");
DB.find(Article.class).setId(id).forUpdate(NO_KEY_UPDATE).findOne();
DB.find(Article.class).setId(id).withLock(NO_KEY_UPDATE).findOne();
sleep(1000);
timePostLock = System.currentTimeMillis();
log.info("lock done");
@@ -685,6 +685,34 @@ public abstract class TQRootBean<T, R> {
return root;
}
/**
* Execute the query with the given lock type and WAIT.
* <p>
* Note that <code>forUpdate()</code> is the same as
* <code>withLock(LockType.UPDATE)</code>.
* <p>
* Provides us with the ability to explicitly use Postgres
* SHARE, KEY SHARE, NO KEY UPDATE and UPDATE row locks.
*/
R withLock(Query.LockType lockType) {
query.withLock(lockType);
return root;
}
/**
* Execute the query with the given lock type and lock wait.
* <p>
* Note that <code>forUpdateNoWait()</code> is the same as
* <code>withLock(LockType.UPDATE, LockWait.NOWAIT)</code>.
* <p>
* Provides us with the ability to explicitly use Postgres
* SHARE, KEY SHARE, NO KEY UPDATE and UPDATE row locks.
*/
R withLock(Query.LockType lockType, Query.LockWait lockWait) {
query.withLock(lockType, lockWait);
return root;
}
/**
* Execute using "for update" clause which results in the DB locking the record.
*/
@@ -694,8 +722,10 @@ public abstract class TQRootBean<T, R> {
}
/**
* Deprecated - migrate to withLock().
* Execute using "for update" with given lock type (currently Postgres only).
*/
@Deprecated
public R forUpdate(Query.LockType lockType) {
query.forUpdate(lockType);
return root;
@@ -712,8 +742,10 @@ public abstract class TQRootBean<T, R> {
}
/**
* Deprecated - migrate to withLock().
* Execute using "for update nowait" with given lock type (currently Postgres only).
*/
@Deprecated
public R forUpdateNoWait(Query.LockType lockType) {
query.forUpdateNoWait(lockType);
return root;
@@ -731,8 +763,10 @@ public abstract class TQRootBean<T, R> {
}
/**
* Deprecated - migrate to withLock().
* Execute using "for update skip locked" with given lock type (currently Postgres only).
*/
@Deprecated
public R forUpdateSkipLocked(Query.LockType lockType) {
query.forUpdateSkipLocked(lockType);
return root;