Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 91a2199

Browse files
JdbcAggregateOperations delete by query
Issue link: #1978 Add deleteAllByQuery method to JdbcAggregateOperations This method enables deleting aggregates based on a query by performing the following steps: 1. Lock the target rows using SELECT ... FOR UPDATE based on the query conditions. 2. Delete sub-entities by leveraging a subquery that selects the matching root rows. 3. Delete the root entities using the query conditions. But if the query has no criteria, deletion is performed in the same way as deleteAll method of JdbcAggregateOperations Signed-off-by: JaeYeon Kim <ghgh415263@naver.com>
1 parent 245b8e5 commit 91a2199

File tree

15 files changed

+505
-0
lines changed

15 files changed

+505
-0
lines changed

‎spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/AggregateChangeExecutor.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
* @author Myeonghyeon Lee
3131
* @author Chirag Tailor
3232
* @author Mikhail Polivakha
33+
* @author Jaeyeon Kim
3334
* @since 2.0
3435
*/
3536
class AggregateChangeExecutor {
@@ -101,10 +102,16 @@ private void execute(DbAction<?> action, JdbcAggregateChangeExecutionContext exe
101102
executionContext.executeBatchDeleteRoot(batchDeleteRoot);
102103
} else if (action instanceof DbAction.DeleteAllRoot<?> deleteAllRoot) {
103104
executionContext.executeDeleteAllRoot(deleteAllRoot);
105+
} else if (action instanceof DbAction.DeleteRootByQuery<?> deleteRootByQuery) {
106+
executionContext.excuteDeleteRootByQuery(deleteRootByQuery);
107+
} else if (action instanceof DbAction.DeleteByQuery<?> deleteByQuery) {
108+
executionContext.excuteDeleteByQuery(deleteByQuery);
104109
} else if (action instanceof DbAction.AcquireLockRoot<?> acquireLockRoot) {
105110
executionContext.executeAcquireLock(acquireLockRoot);
106111
} else if (action instanceof DbAction.AcquireLockAllRoot<?> acquireLockAllRoot) {
107112
executionContext.executeAcquireLockAllRoot(acquireLockAllRoot);
113+
} else if (action instanceof DbAction.AcquireLockAllRootByQuery<?> acquireLockAllRootByQuery) {
114+
executionContext.executeAcquireLockRootByQuery(acquireLockAllRootByQuery);
108115
} else {
109116
throw new RuntimeException("unexpected action");
110117
}

‎spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateChangeExecutionContext.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
* @author Myeonghyeon Lee
6161
* @author Chirag Tailor
6262
* @author Mark Paluch
63+
* @author Jaeyeon Kim
6364
*/
6465
@SuppressWarnings("rawtypes")
6566
class JdbcAggregateChangeExecutionContext {
@@ -169,6 +170,16 @@ <T> void executeDeleteAll(DbAction.DeleteAll<T> delete) {
169170
accessStrategy.deleteAll(delete.getPropertyPath());
170171
}
171172

173+
<T> void excuteDeleteRootByQuery(DbAction.DeleteRootByQuery<T> deleteRootByQuery) {
174+
175+
accessStrategy.deleteByQuery(deleteRootByQuery.getQuery(), deleteRootByQuery.getEntityType());
176+
}
177+
178+
<T> void excuteDeleteByQuery(DbAction.DeleteByQuery<T> deleteByQuery) {
179+
180+
accessStrategy.deleteByQuery(deleteByQuery.getQuery(), deleteByQuery.getPropertyPath());
181+
}
182+
172183
<T> void executeAcquireLock(DbAction.AcquireLockRoot<T> acquireLock) {
173184
accessStrategy.acquireLockById(acquireLock.getId(), LockMode.PESSIMISTIC_WRITE, acquireLock.getEntityType());
174185
}
@@ -177,6 +188,10 @@ <T> void executeAcquireLockAllRoot(DbAction.AcquireLockAllRoot<T> acquireLock) {
177188
accessStrategy.acquireLockAll(LockMode.PESSIMISTIC_WRITE, acquireLock.getEntityType());
178189
}
179190

191+
<T> void executeAcquireLockRootByQuery(DbAction.AcquireLockAllRootByQuery<T> acquireLock) {
192+
accessStrategy.acquireLockByQuery(acquireLock.getQuery(), LockMode.PESSIMISTIC_WRITE, acquireLock.getEntityType());
193+
}
194+
180195
private void add(DbActionExecutionResult result) {
181196
results.put(result.getAction(), result);
182197
}

‎spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateOperations.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
* @author Myeonghyeon Lee
4141
* @author Sergey Korotaev
4242
* @author Tomohiko Ozawa
43+
* @author Jaeyeon Kim
4344
*/
4445
public interface JdbcAggregateOperations {
4546

@@ -328,6 +329,15 @@ public interface JdbcAggregateOperations {
328329
*/
329330
<T> void deleteAll(Iterable<? extends T> aggregateRoots);
330331

332+
/**
333+
* Deletes all aggregates of the given type that match the provided query.
334+
*
335+
* @param query Must not be {@code null}.
336+
* @param domainType the type of the aggregate root. Must not be {@code null}.
337+
* @param <T> the type of the aggregate root.
338+
*/
339+
<T> void deleteAllByQuery(Query query, Class<T> domainType);
340+
331341
/**
332342
* Returns the {@link JdbcConverter}.
333343
*

‎spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
* @author Diego Krupitza
7373
* @author Sergey Korotaev
7474
* @author Mikhail Polivakha
75+
* @author Jaeyeon Kim
7576
*/
7677
public class JdbcAggregateTemplate implements JdbcAggregateOperations, ApplicationContextAware {
7778

@@ -484,6 +485,17 @@ public <T> void deleteAll(Iterable<? extends T> instances) {
484485
}
485486
}
486487

488+
@Override
489+
public <T> void deleteAllByQuery(Query query, Class<T> domainType) {
490+
491+
Assert.notNull(query, "Query must not be null");
492+
Assert.notNull(domainType, "Domain type must not be null");
493+
494+
MutableAggregateChange<?> change = createDeletingChange(query, domainType);
495+
496+
executor.executeDelete(change);
497+
}
498+
487499
@Override
488500
public DataAccessStrategy getDataAccessStrategy() {
489501
return accessStrategy;
@@ -672,6 +684,13 @@ private MutableAggregateChange<?> createDeletingChange(Class<?> domainType) {
672684
return aggregateChange;
673685
}
674686

687+
private MutableAggregateChange<?> createDeletingChange(Query query, Class<?> domainType) {
688+
689+
MutableAggregateChange<?> aggregateChange = MutableAggregateChange.forDelete(domainType);
690+
jdbcEntityDeleteWriter.writeForQuery(query, aggregateChange);
691+
return aggregateChange;
692+
}
693+
675694
private <T> List<T> triggerAfterConvert(Iterable<T> all) {
676695

677696
List<T> result = new ArrayList<>();

‎spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/CascadingDataAccessStrategy.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
* @author Chirag Tailor
4848
* @author Diego Krupitza
4949
* @author Sergey Korotaev
50+
* @author Jaeyeon Kim
5051
* @since 1.1
5152
*/
5253
public class CascadingDataAccessStrategy implements DataAccessStrategy {
@@ -128,6 +129,16 @@ public void deleteAll(PersistentPropertyPath<RelationalPersistentProperty> prope
128129
collectVoid(das -> das.deleteAll(propertyPath));
129130
}
130131

132+
@Override
133+
public void deleteByQuery(Query query, Class<?> domainType) {
134+
collectVoid(das -> das.deleteByQuery(query, domainType));
135+
}
136+
137+
@Override
138+
public void deleteByQuery(Query query, PersistentPropertyPath<RelationalPersistentProperty> propertyPath) {
139+
collectVoid(das -> das.deleteByQuery(query, propertyPath));
140+
}
141+
131142
@Override
132143
public <T> void acquireLockById(Object id, LockMode lockMode, Class<T> domainType) {
133144
collectVoid(das -> das.acquireLockById(id, lockMode, domainType));
@@ -138,6 +149,11 @@ public <T> void acquireLockAll(LockMode lockMode, Class<T> domainType) {
138149
collectVoid(das -> das.acquireLockAll(lockMode, domainType));
139150
}
140151

152+
@Override
153+
public <T> void acquireLockByQuery(Query query, LockMode lockMode, Class<T> domainType) {
154+
collectVoid(das -> das.acquireLockByQuery(query, lockMode, domainType));
155+
}
156+
141157
@Override
142158
public long count(Class<?> domainType) {
143159
return collect(das -> das.count(domainType));

‎spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DataAccessStrategy.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
* @author Chirag Tailor
4646
* @author Diego Krupitza
4747
* @author Sergey Korotaev
48+
* @author Jaeyeon Kim
4849
*/
4950
public interface DataAccessStrategy extends ReadingDataAccessStrategy, RelationResolver {
5051

@@ -191,6 +192,22 @@ public interface DataAccessStrategy extends ReadingDataAccessStrategy, RelationR
191192
*/
192193
void deleteAll(PersistentPropertyPath<RelationalPersistentProperty> propertyPath);
193194

195+
/**
196+
* Deletes all root entities of the given domain type that match the given {@link Query}.
197+
*
198+
* @param query the query specifying which rows to delete. Must not be {@code null}.
199+
* @param domainType the domain type of the entity. Must not be {@code null}.
200+
*/
201+
void deleteByQuery(Query query, Class<?> domainType);
202+
203+
/**
204+
* Deletes entities reachable via the given {@link PersistentPropertyPath} from root entities that match the given {@link Query}.
205+
*
206+
* @param query the query specifying which root entities to consider for deleting related entities. Must not be {@code null}.
207+
* @param propertyPath Leading from the root object to the entities to be deleted. Must not be {@code null}.
208+
*/
209+
void deleteByQuery(Query query, PersistentPropertyPath<RelationalPersistentProperty> propertyPath);
210+
194211
/**
195212
* Acquire a lock on the aggregate specified by id.
196213
*
@@ -208,6 +225,16 @@ public interface DataAccessStrategy extends ReadingDataAccessStrategy, RelationR
208225
*/
209226
<T> void acquireLockAll(LockMode lockMode, Class<T> domainType);
210227

228+
/**
229+
* Acquire a lock on all aggregates that match the given {@link Query}.
230+
*
231+
* @param query the query specifying which entities to lock. Must not be {@code null}.
232+
* @param lockMode the lock mode to apply to the query (e.g. {@code FOR UPDATE}). Must not be {@code null}.
233+
* @param domainType the domain type of the entities to be locked. Must not be {@code null}.
234+
* @param <T> the type of the domain entity.
235+
*/
236+
<T> void acquireLockByQuery(Query query, LockMode lockMode, Class<T> domainType);
237+
211238
/**
212239
* Counts the rows in the table representing the given domain type.
213240
*

‎spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultDataAccessStrategy.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
* @author Diego Krupitza
6565
* @author Sergey Korotaev
6666
* @author Mikhail Polivakha
67+
* @author Jaeyeon Kim
6768
* @since 1.1
6869
*/
6970
public class DefaultDataAccessStrategy implements DataAccessStrategy {
@@ -254,6 +255,29 @@ public void deleteAll(PersistentPropertyPath<RelationalPersistentProperty> prope
254255
operations.getJdbcOperations().update(sql(getBaseType(propertyPath)).createDeleteAllSql(propertyPath));
255256
}
256257

258+
@Override
259+
public void deleteByQuery(Query query, Class<?> domainType) {
260+
261+
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
262+
String deleteSql = sql(domainType).createDeleteByQuery(query, parameterSource);
263+
264+
operations.update(deleteSql, parameterSource);
265+
}
266+
267+
@Override
268+
public void deleteByQuery(Query query, PersistentPropertyPath<RelationalPersistentProperty> propertyPath) {
269+
270+
RelationalPersistentEntity<?> rootEntity = context.getRequiredPersistentEntity(getBaseType(propertyPath));
271+
272+
RelationalPersistentProperty referencingProperty = propertyPath.getLeafProperty();
273+
Assert.notNull(referencingProperty, "No property found matching the PropertyPath " + propertyPath);
274+
275+
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
276+
String deleteSql = sql(rootEntity.getType()).createDeleteInSubselectByPath(query, parameterSource, propertyPath);
277+
278+
operations.update(deleteSql, parameterSource);
279+
}
280+
257281
@Override
258282
public <T> void acquireLockById(Object id, LockMode lockMode, Class<T> domainType) {
259283

@@ -270,6 +294,15 @@ public <T> void acquireLockAll(LockMode lockMode, Class<T> domainType) {
270294
operations.getJdbcOperations().query(acquireLockAllSql, ResultSet::next);
271295
}
272296

297+
@Override
298+
public <T> void acquireLockByQuery(Query query, LockMode lockMode, Class<T> domainType) {
299+
300+
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
301+
String acquireLockByQuerySql = sql(domainType).getAcquireLockByQuery(query, parameterSource, lockMode);
302+
303+
operations.query(acquireLockByQuerySql, parameterSource, ResultSet::next);
304+
}
305+
273306
@Override
274307
public long count(Class<?> domainType) {
275308

‎spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DelegatingDataAccessStrategy.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
* @author Chirag Tailor
4242
* @author Diego Krupitza
4343
* @author Sergey Korotaev
44+
* @author Jaeyeon Kim
4445
* @since 1.1
4546
*/
4647
public class DelegatingDataAccessStrategy implements DataAccessStrategy {
@@ -121,6 +122,16 @@ public void deleteAll(PersistentPropertyPath<RelationalPersistentProperty> prope
121122
delegate.deleteAll(propertyPath);
122123
}
123124

125+
@Override
126+
public void deleteByQuery(Query query, Class<?> domainType) {
127+
delegate.deleteByQuery(query, domainType);
128+
}
129+
130+
@Override
131+
public void deleteByQuery(Query query, PersistentPropertyPath<RelationalPersistentProperty> propertyPath) {
132+
delegate.deleteByQuery(query, propertyPath);
133+
}
134+
124135
@Override
125136
public <T> void acquireLockById(Object id, LockMode lockMode, Class<T> domainType) {
126137
delegate.acquireLockById(id, lockMode, domainType);
@@ -131,6 +142,11 @@ public <T> void acquireLockAll(LockMode lockMode, Class<T> domainType) {
131142
delegate.acquireLockAll(lockMode, domainType);
132143
}
133144

145+
@Override
146+
public <T> void acquireLockByQuery(Query query, LockMode lockMode, Class<T> domainType) {
147+
delegate.acquireLockByQuery(query, lockMode, domainType);
148+
}
149+
134150
@Override
135151
public long count(Class<?> domainType) {
136152
return delegate.count(domainType);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /