Skip to content

Commit cbffe9a

Browse files
author
mhyeon-lee
committed
DATAJDBC-498 Add LockMode for SelectBuilder
1 parent b701323 commit cbffe9a

File tree

7 files changed

+193
-15
lines changed

7 files changed

+193
-15
lines changed

spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/DefaultSelect.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
* Default {@link Select} implementation.
2828
*
2929
* @author Mark Paluch
30+
* @author Myeonghyeon Lee
3031
* @since 1.1
3132
*/
3233
class DefaultSelect implements Select {
@@ -39,9 +40,10 @@ class DefaultSelect implements Select {
3940
private final List<Join> joins;
4041
private final @Nullable Where where;
4142
private final List<OrderByField> orderBy;
43+
private final @Nullable LockMode lockMode;
4244

4345
DefaultSelect(boolean distinct, List<Expression> selectList, List<Table> from, long limit, long offset,
44-
List<Join> joins, @Nullable Condition where, List<OrderByField> orderBy) {
46+
List<Join> joins, @Nullable Condition where, List<OrderByField> orderBy, @Nullable LockMode lockMode) {
4547

4648
this.distinct = distinct;
4749
this.selectList = new SelectList(new ArrayList<>(selectList));
@@ -51,6 +53,7 @@ class DefaultSelect implements Select {
5153
this.joins = new ArrayList<>(joins);
5254
this.orderBy = Collections.unmodifiableList(new ArrayList<>(orderBy));
5355
this.where = where != null ? new Where(where) : null;
56+
this.lockMode = lockMode;
5457
}
5558

5659
/*
@@ -85,6 +88,16 @@ public boolean isDistinct() {
8588
return distinct;
8689
}
8790

91+
/*
92+
* (non-Javadoc)
93+
* @see org.springframework.data.relational.core.sql.Select#getLockMode()
94+
*/
95+
@Nullable
96+
@Override
97+
public LockMode getLockMode() {
98+
return lockMode;
99+
}
100+
88101
/*
89102
* (non-Javadoc)
90103
* @see org.springframework.data.relational.core.sql.Visitable#visit(org.springframework.data.relational.core.sql.Visitor)

spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/DefaultSelectBuilder.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
*
3232
* @author Mark Paluch
3333
* @author Jens Schauder
34+
* @author Myeonghyeon Lee
3435
* @since 1.1
3536
*/
3637
class DefaultSelectBuilder implements SelectBuilder, SelectAndFrom, SelectFromAndJoin, SelectWhereAndOr {
@@ -43,6 +44,7 @@ class DefaultSelectBuilder implements SelectBuilder, SelectAndFrom, SelectFromAn
4344
private List<Join> joins = new ArrayList<>();
4445
private @Nullable Condition where;
4546
private List<OrderByField> orderBy = new ArrayList<>();
47+
private @Nullable LockMode lockMode;
4648

4749
/*
4850
* (non-Javadoc)
@@ -265,13 +267,23 @@ public DefaultSelectBuilder join(Join join) {
265267
return this;
266268
}
267269

270+
/*
271+
* (non-Javadoc)
272+
* @see org.springframework.data.relational.core.sql.SelectBuilder.SelectLock#lock(org.springframework.data.relational.core.sql.LockMode)
273+
*/
274+
@Override
275+
public SelectLock lock(LockMode lockMode) {
276+
this.lockMode = lockMode;
277+
return this;
278+
}
279+
268280
/*
269281
* (non-Javadoc)
270282
* @see org.springframework.data.relational.core.sql.SelectBuilder.BuildSelect#build()
271283
*/
272284
@Override
273285
public Select build() {
274-
DefaultSelect select = new DefaultSelect(distinct, selectList, from, limit, offset, joins, where, orderBy);
286+
DefaultSelect select = new DefaultSelect(distinct, selectList, from, limit, offset, joins, where, orderBy, lockMode);
275287
SelectValidator.validate(select);
276288
return select;
277289
}
@@ -448,6 +460,16 @@ public SelectFromAndJoin offset(long offset) {
448460
return selectBuilder.offset(offset);
449461
}
450462

463+
/*
464+
* (non-Javadoc)
465+
* @see org.springframework.data.relational.core.sql.SelectBuilder.SelectLock#lock(org.springframework.data.relational.core.sql.LockMode)
466+
*/
467+
@Override
468+
public SelectLock lock(LockMode lockMode) {
469+
selectBuilder.join(finishJoin());
470+
return selectBuilder.lock(lockMode);
471+
}
472+
451473
/*
452474
* (non-Javadoc)
453475
* @see org.springframework.data.relational.core.sql.SelectBuilder.BuildSelect#build()
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.relational.core.sql;
17+
18+
/**
19+
* Lock Mode Types of SELECT statements.
20+
*
21+
* @author Myeonghyeon Lee
22+
* @since 2.0
23+
*/
24+
public enum LockMode {
25+
PESSIMISTIC_READ,
26+
PESSIMISTIC_WRITE
27+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.relational.core.sql;
17+
18+
/**
19+
* LockOptions has a LOCK option to apply to the Select statement.
20+
*
21+
* @author Myeonghyeon Lee
22+
* @since 2.0
23+
*/
24+
public class LockOptions {
25+
private final LockMode lockMode;
26+
27+
public LockOptions(LockMode lockMode) {
28+
this.lockMode = lockMode;
29+
}
30+
31+
public LockMode getLockMode() {
32+
return this.lockMode;
33+
}
34+
}

spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/Select.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.springframework.data.relational.core.sql;
1717

18+
import org.springframework.lang.Nullable;
19+
1820
import java.util.List;
1921
import java.util.OptionalLong;
2022

@@ -30,6 +32,7 @@
3032
* </ol>
3133
*
3234
* @author Mark Paluch
35+
* @author Myeonghyeon Lee
3336
* @since 1.1
3437
* @see StatementBuilder
3538
* @see SelectBuilder
@@ -71,4 +74,7 @@ static SelectBuilder builder() {
7174
* @return
7275
*/
7376
boolean isDistinct();
77+
78+
@Nullable
79+
LockMode getLockMode();
7480
}

spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/SelectBuilder.java

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
*
2323
* @author Mark Paluch
2424
* @author Jens Schauder
25+
* @author Myeonghyeon Lee
2526
* @since 1.1
2627
* @see StatementBuilder
2728
*/
@@ -211,9 +212,9 @@ interface SelectFrom extends BuildSelect {
211212
}
212213

213214
/**
214-
* Builder exposing {@code FROM}, {@code JOIN}, {@code WHERE} and {@code LIMIT/OFFSET} methods.
215+
* Builder exposing {@code FROM}, {@code JOIN}, {@code WHERE}, {@code LIMIT/OFFSET} and {@code LOCK} methods.
215216
*/
216-
interface SelectFromAndOrderBy extends SelectFrom, SelectOrdered, SelectLimitOffset, BuildSelect {
217+
interface SelectFromAndOrderBy extends SelectFrom, SelectOrdered, SelectLimitOffset, SelectLock, BuildSelect {
217218

218219
@Override
219220
SelectFromAndOrderBy limitOffset(long limit, long offset);
@@ -247,9 +248,10 @@ interface SelectFromAndOrderBy extends SelectFrom, SelectOrdered, SelectLimitOff
247248
}
248249

249250
/**
250-
* Builder exposing {@code FROM}, {@code JOIN}, {@code WHERE} and {@code LIMIT/OFFSET} methods.
251+
* Builder exposing {@code FROM}, {@code JOIN}, {@code WHERE}, {@code LIMIT/OFFSET} and {@code LOCK} methods.
251252
*/
252-
interface SelectFromAndJoin extends SelectFromAndOrderBy, BuildSelect, SelectJoin, SelectWhere, SelectLimitOffset {
253+
interface SelectFromAndJoin
254+
extends SelectFromAndOrderBy, BuildSelect, SelectJoin, SelectWhere, SelectLimitOffset, SelectLock {
253255

254256
/**
255257
* Declare a {@link Table} to {@code SELECT … FROM}. Multiple calls to this or other {@code from} methods keep
@@ -315,10 +317,10 @@ interface SelectFromAndJoin extends SelectFromAndOrderBy, BuildSelect, SelectJoi
315317
}
316318

317319
/**
318-
* Builder exposing {@code FROM}, {@code WHERE}, {@code LIMIT/OFFSET}, and JOIN {@code AND} continuation methods.
320+
* Builder exposing {@code FROM}, {@code WHERE}, {@code LIMIT/OFFSET}, JOIN {@code AND} and {@code LOCK} continuation methods.
319321
*/
320322
interface SelectFromAndJoinCondition
321-
extends BuildSelect, SelectJoin, SelectWhere, SelectOnCondition, SelectLimitOffset {
323+
extends BuildSelect, SelectJoin, SelectWhere, SelectOnCondition, SelectLimitOffset, SelectLock {
322324

323325
/**
324326
* Apply {@code limit} and {@code offset} parameters to the select statement. To read the first 20 rows from start
@@ -380,9 +382,9 @@ interface SelectLimitOffset {
380382
}
381383

382384
/**
383-
* Builder exposing {@code ORDER BY} methods.
385+
* Builder exposing {@code ORDER BY} and {@code LOCK} methods.
384386
*/
385-
interface SelectOrdered extends BuildSelect {
387+
interface SelectOrdered extends SelectLock, BuildSelect {
386388

387389
/**
388390
* Add one or more {@link Column columns} to order by.
@@ -410,9 +412,9 @@ interface SelectOrdered extends BuildSelect {
410412
}
411413

412414
/**
413-
* Interface exposing {@code WHERE} methods.
415+
* Interface exposing {@code WHERE}, {@code LOCK} methods.
414416
*/
415-
interface SelectWhere extends SelectOrdered, BuildSelect {
417+
interface SelectWhere extends SelectOrdered, SelectLock, BuildSelect {
416418

417419
/**
418420
* Apply a {@code WHERE} clause.
@@ -428,7 +430,7 @@ interface SelectWhere extends SelectOrdered, BuildSelect {
428430
/**
429431
* Interface exposing {@code AND}/{@code OR} combinator methods for {@code WHERE} {@link Condition}s.
430432
*/
431-
interface SelectWhereAndOr extends SelectOrdered, BuildSelect {
433+
interface SelectWhereAndOr extends SelectOrdered, SelectLock, BuildSelect {
432434

433435
/**
434436
* Combine the previous {@code WHERE} {@link Condition} using {@code AND}.
@@ -452,7 +454,7 @@ interface SelectWhereAndOr extends SelectOrdered, BuildSelect {
452454
/**
453455
* Interface exposing {@code JOIN} methods.
454456
*/
455-
interface SelectJoin extends BuildSelect {
457+
interface SelectJoin extends SelectLock, BuildSelect {
456458

457459
/**
458460
* Declare a {@code JOIN} {@code table}.
@@ -518,7 +520,7 @@ interface SelectOnConditionComparison {
518520
/**
519521
* Builder exposing JOIN and {@code JOIN … ON} continuation methods.
520522
*/
521-
interface SelectOnCondition extends SelectJoin, BuildSelect {
523+
interface SelectOnCondition extends SelectJoin, SelectLock, BuildSelect {
522524

523525
/**
524526
* Declare an additional source column in the {@code JOIN}.
@@ -530,6 +532,20 @@ interface SelectOnCondition extends SelectJoin, BuildSelect {
530532
SelectOnConditionComparison and(Expression column);
531533
}
532534

535+
/**
536+
* Lock methods.
537+
*/
538+
interface SelectLock extends BuildSelect {
539+
540+
/**
541+
* Apply lock to read.
542+
*
543+
* @param lockMode lockMode to read.
544+
* @return {@code this} builder.
545+
*/
546+
SelectLock lock(LockMode lockMode);
547+
}
548+
533549
/**
534550
* Interface exposing the {@link Select} build method.
535551
*/

spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/SelectBuilderUnitTests.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
* Unit tests for {@link SelectBuilder}.
2828
*
2929
* @author Mark Paluch
30+
* @author Myeonghyeon Lee
3031
*/
3132
public class SelectBuilderUnitTests {
3233

@@ -147,4 +148,63 @@ public void joins() {
147148
assertThat(join.getType()).isEqualTo(JoinType.JOIN);
148149
}
149150

151+
@Test // DATAJDBC-498
152+
public void selectWithLock() {
153+
154+
SelectBuilder builder = StatementBuilder.select();
155+
156+
Table table = SQL.table("mytable");
157+
Column foo = table.column("foo");
158+
Column bar = table.column("bar");
159+
LockMode lockMode = LockMode.PESSIMISTIC_WRITE;
160+
161+
Select select = builder.select(foo, bar).from(table).lock(lockMode).build();
162+
163+
CapturingVisitor visitor = new CapturingVisitor();
164+
select.visit(visitor);
165+
166+
assertThat(visitor.enter).containsSequence(foo, table, bar, table, new From(table), table);
167+
assertThat(select.getLockMode()).isEqualTo(lockMode);
168+
}
169+
170+
@Test // DATAJDBC-498
171+
public void selectWithWhereWithLock() {
172+
173+
SelectBuilder builder = StatementBuilder.select();
174+
175+
Table table = SQL.table("mytable");
176+
Column foo = table.column("foo");
177+
178+
Comparison condition = foo.isEqualTo(SQL.literalOf("bar"));
179+
LockMode lockMode = LockMode.PESSIMISTIC_WRITE;
180+
181+
Select select = builder.select(foo).from(table).where(condition).lock(lockMode).build();
182+
183+
CapturingVisitor visitor = new CapturingVisitor();
184+
select.visit(visitor);
185+
186+
assertThat(visitor.enter).containsSequence(foo, table, new From(table), table, new Where(condition));
187+
assertThat(select.getLockMode()).isEqualTo(lockMode);
188+
}
189+
190+
@Test // DATAJDBC-498
191+
public void orderByWithLock() {
192+
193+
SelectBuilder builder = StatementBuilder.select();
194+
195+
Table table = SQL.table("mytable");
196+
197+
Column foo = SQL.column("foo", table).as("foo");
198+
199+
OrderByField orderByField = OrderByField.from(foo).asc();
200+
LockMode lockMode = LockMode.PESSIMISTIC_WRITE;
201+
202+
Select select = builder.select(foo).from(table).orderBy(orderByField).lock(lockMode).build();
203+
204+
CapturingVisitor visitor = new CapturingVisitor();
205+
select.visit(visitor);
206+
207+
assertThat(visitor.enter).containsSequence(foo, table, new From(table), table, orderByField, foo);
208+
assertThat(select.getLockMode()).isEqualTo(lockMode);
209+
}
150210
}

0 commit comments

Comments
 (0)