Skip to content

Commit aad40a3

Browse files
committed
Polishing.
Added `@since` comments for new methods and classes. General formatting and code style tweaking. Github references for new tests added. Fixes for integration tests with various databases: - Not all stores support submillisecond precision for Instant. - Count for exists query doesn't work for all databases, nor does `LEAST(COUNT(1), 1)` - MariaDB defaults timestamp columns to the current time. - Ordering was applied twice. - DATETIME in SqlServer has a most peculiar preceision. We switch to DATETIME2. Original pull request #1195 See #1192
1 parent 27e2aa2 commit aad40a3

File tree

18 files changed

+273
-248
lines changed

18 files changed

+273
-248
lines changed

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ public interface JdbcAggregateOperations {
196196
* @param entityClass the entity type must not be {@literal null}.
197197
* @return exactly one result or {@link Optional#empty()} if no match found.
198198
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if more than one match found.
199+
* @since 3.0
199200
*/
200201
<T> Optional<T> selectOne(Query query, Class<T> entityClass);
201202

@@ -204,18 +205,19 @@ public interface JdbcAggregateOperations {
204205
*
205206
* @param query must not be {@literal null}.
206207
* @param entityClass the entity type must not be {@literal null}.
207-
* @param sort the sorting that should be used on the result.
208208
* @return a non-null sorted list with all the matching results.
209209
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if more than one match found.
210+
* @since 3.0
210211
*/
211-
<T> Iterable<T> select(Query query, Class<T> entityClass, Sort sort);
212+
<T> Iterable<T> select(Query query, Class<T> entityClass);
212213

213214
/**
214215
* Determine whether there are aggregates that match the {@link Query}
215216
*
216217
* @param query must not be {@literal null}.
217218
* @param entityClass the entity type must not be {@literal null}.
218219
* @return {@literal true} if the object exists.
220+
* @since 3.0
219221
*/
220222
<T> boolean exists(Query query, Class<T> entityClass);
221223

@@ -225,6 +227,7 @@ public interface JdbcAggregateOperations {
225227
* @param query must not be {@literal null}.
226228
* @param entityClass the entity type must not be {@literal null}.
227229
* @return the number of instances stored in the database. Guaranteed to be not {@code null}.
230+
* @since 3.0
228231
*/
229232
<T> long count(Query query, Class<T> entityClass);
230233

@@ -236,6 +239,7 @@ public interface JdbcAggregateOperations {
236239
* @param entityClass the entity type must not be {@literal null}.
237240
* @param pageable can be null.
238241
* @return a {@link Page} of entities matching the given {@link Example}.
242+
* @since 3.0
239243
*/
240244
<T> Page<T> select(Query query, Class<T> entityClass, Pageable pageable);
241245
}

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations {
7474

7575
private final DataAccessStrategy accessStrategy;
7676
private final AggregateChangeExecutor executor;
77-
7877
private final JdbcConverter converter;
7978

8079
private EntityCallbacks entityCallbacks = EntityCallbacks.create();
@@ -248,7 +247,7 @@ public <T> Optional<T> selectOne(Query query, Class<T> entityClass) {
248247
}
249248

250249
@Override
251-
public <T> Iterable<T> select(Query query, Class<T> entityClass, Sort sort) {
250+
public <T> Iterable<T> select(Query query, Class<T> entityClass) {
252251
return accessStrategy.select(query, entityClass);
253252
}
254253

@@ -264,16 +263,13 @@ public <T> long count(Query query, Class<T> entityClass) {
264263

265264
@Override
266265
public <T> Page<T> select(Query query, Class<T> entityClass, Pageable pageable) {
266+
267267
Iterable<T> items = triggerAfterConvert(accessStrategy.select(query, entityClass, pageable));
268268
List<T> content = StreamSupport.stream(items.spliterator(), false).collect(Collectors.toList());
269269

270270
return PageableExecutionUtils.getPage(content, pageable, () -> accessStrategy.count(query, entityClass));
271271
}
272272

273-
/*
274-
* (non-Javadoc)
275-
* @see org.springframework.data.jdbc.core.JdbcAggregateOperations#findAll(java.lang.Class)
276-
*/
277273
@Override
278274
public <T> Iterable<T> findAll(Class<T> domainType) {
279275

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

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

18+
import static java.lang.Boolean.*;
19+
1820
import java.util.ArrayList;
1921
import java.util.List;
2022
import java.util.Optional;
@@ -29,10 +31,8 @@
2931
import org.springframework.data.relational.core.query.Query;
3032
import org.springframework.data.relational.core.sql.LockMode;
3133

32-
import static java.lang.Boolean.*;
33-
3434
/**
35-
* Delegates each methods to the {@link DataAccessStrategy}s passed to the constructor in turn until the first that does
35+
* Delegates each method to the {@link DataAccessStrategy}s passed to the constructor in turn until the first that does
3636
* not throw an exception.
3737
*
3838
* @author Jens Schauder

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ public interface DataAccessStrategy extends RelationResolver {
114114
* @param previousVersion The previous version assigned to the instance being saved.
115115
* @param <T> the type of the instance to save.
116116
* @return whether the update actually updated a row.
117-
* @throws OptimisticLockingFailureException if the update fails to update at least one row assuming the
118-
* optimistic locking version check failed.
117+
* @throws OptimisticLockingFailureException if the update fails to update at least one row assuming the optimistic
118+
* locking version check failed.
119119
* @since 2.0
120120
*/
121121
<T> boolean updateWithVersion(T instance, Class<T> domainType, Number previousVersion);
@@ -155,8 +155,8 @@ public interface DataAccessStrategy extends RelationResolver {
155155
* @param domainType the type of entity to be deleted. Implicitly determines the table to operate on. Must not be
156156
* {@code null}.
157157
* @param previousVersion The previous version assigned to the instance being saved.
158-
* @throws OptimisticLockingFailureException if the update fails to update at least one row assuming the
159-
* optimistic locking version check failed.
158+
* @throws OptimisticLockingFailureException if the update fails to update at least one row assuming the optimistic
159+
* locking version check failed.
160160
* @since 2.0
161161
*/
162162
<T> void deleteWithVersion(Object id, Class<T> domainType, Number previousVersion);
@@ -292,6 +292,7 @@ Iterable<Object> findAllByPath(Identifier identifier,
292292
* @param probeType the type of entities. Must not be {@code null}.
293293
* @return exactly one result or {@link Optional#empty()} if no match found.
294294
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if more than one match found.
295+
* @since 3.0
295296
*/
296297
<T> Optional<T> selectOne(Query query, Class<T> probeType);
297298

@@ -302,6 +303,7 @@ Iterable<Object> findAllByPath(Identifier identifier,
302303
* @param probeType the type of entities. Must not be {@code null}.
303304
* @return a non-null list with all the matching results.
304305
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if more than one match found.
306+
* @since 3.0
305307
*/
306308
<T> Iterable<T> select(Query query, Class<T> probeType);
307309

@@ -314,6 +316,7 @@ Iterable<Object> findAllByPath(Identifier identifier,
314316
* @param pageable the pagination that should be applied. Must not be {@literal null}.
315317
* @return a non-null list with all the matching results.
316318
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if more than one match found.
319+
* @since 3.0
317320
*/
318321
<T> Iterable<T> select(Query query, Class<T> probeType, Pageable pageable);
319322

@@ -323,6 +326,7 @@ Iterable<Object> findAllByPath(Identifier identifier,
323326
* @param query must not be {@literal null}.
324327
* @param probeType the type of entities. Must not be {@code null}.
325328
* @return {@literal true} if the object exists.
329+
* @since 3.0
326330
*/
327331
<T> boolean exists(Query query, Class<T> probeType);
328332

@@ -332,6 +336,7 @@ Iterable<Object> findAllByPath(Identifier identifier,
332336
* @param probeType the probe type for which to count the elements. Must not be {@code null}.
333337
* @param query the query which elements have to match.
334338
* @return the count. Guaranteed to be not {@code null}.
339+
* @since 3.0
335340
*/
336341
<T> long count(Query query, Class<T> probeType);
337342
}

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

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@
2020
import java.sql.ResultSet;
2121
import java.util.Collections;
2222
import java.util.List;
23-
import java.util.Map;
2423
import java.util.Optional;
25-
import java.util.function.Predicate;
2624

2725
import org.springframework.dao.EmptyResultDataAccessException;
2826
import org.springframework.dao.OptimisticLockingFailureException;
@@ -262,27 +260,24 @@ public long count(Class<?> domainType) {
262260
}
263261

264262
@Override
265-
@SuppressWarnings("unchecked")
266263
public <T> T findById(Object id, Class<T> domainType) {
267264

268265
String findOneSql = sql(domainType).getFindOne();
269266
SqlIdentifierParameterSource parameter = sqlParametersFactory.forQueryById(id, domainType, ID_SQL_PARAMETER);
270267

271268
try {
272-
return operations.queryForObject(findOneSql, parameter, (RowMapper<T>) getEntityRowMapper(domainType));
269+
return operations.queryForObject(findOneSql, parameter, getEntityRowMapper(domainType));
273270
} catch (EmptyResultDataAccessException e) {
274271
return null;
275272
}
276273
}
277274

278275
@Override
279-
@SuppressWarnings("unchecked")
280276
public <T> Iterable<T> findAll(Class<T> domainType) {
281-
return operations.query(sql(domainType).getFindAll(), (RowMapper<T>) getEntityRowMapper(domainType));
277+
return operations.query(sql(domainType).getFindAll(), getEntityRowMapper(domainType));
282278
}
283279

284280
@Override
285-
@SuppressWarnings("unchecked")
286281
public <T> Iterable<T> findAllById(Iterable<?> ids, Class<T> domainType) {
287282

288283
if (!ids.iterator().hasNext()) {
@@ -293,7 +288,7 @@ public <T> Iterable<T> findAllById(Iterable<?> ids, Class<T> domainType) {
293288

294289
String findAllInListSql = sql(domainType).getFindAllInList();
295290

296-
return operations.query(findAllInListSql, parameterSource, (RowMapper<T>) getEntityRowMapper(domainType));
291+
return operations.query(findAllInListSql, parameterSource, getEntityRowMapper(domainType));
297292
}
298293

299294
@Override
@@ -330,73 +325,74 @@ public <T> boolean existsById(Object id, Class<T> domainType) {
330325
}
331326

332327
@Override
333-
@SuppressWarnings("unchecked")
334328
public <T> Iterable<T> findAll(Class<T> domainType, Sort sort) {
335-
return operations.query(sql(domainType).getFindAll(sort), (RowMapper<T>) getEntityRowMapper(domainType));
329+
return operations.query(sql(domainType).getFindAll(sort), getEntityRowMapper(domainType));
336330
}
337331

338332
@Override
339-
@SuppressWarnings("unchecked")
340333
public <T> Iterable<T> findAll(Class<T> domainType, Pageable pageable) {
341-
return operations.query(sql(domainType).getFindAll(pageable), (RowMapper<T>) getEntityRowMapper(domainType));
334+
return operations.query(sql(domainType).getFindAll(pageable), getEntityRowMapper(domainType));
342335
}
343336

344337
@Override
345338
public <T> Optional<T> selectOne(Query query, Class<T> probeType) {
339+
346340
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
347341
String sqlQuery = sql(probeType).selectByQuery(query, parameterSource);
348342

349-
T foundObject;
350343
try {
351-
foundObject = operations.queryForObject(sqlQuery, parameterSource, (RowMapper<T>) getEntityRowMapper(probeType));
344+
return Optional.ofNullable(
345+
operations.queryForObject(sqlQuery, parameterSource, getEntityRowMapper(probeType)));
352346
} catch (EmptyResultDataAccessException e) {
353-
foundObject = null;
347+
return Optional.empty();
354348
}
355-
356-
return Optional.ofNullable(foundObject);
357349
}
358350

359351
@Override
360352
public <T> Iterable<T> select(Query query, Class<T> probeType) {
353+
361354
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
362355
String sqlQuery = sql(probeType).selectByQuery(query, parameterSource);
363356

364-
return operations.query(sqlQuery, parameterSource, (RowMapper<T>) getEntityRowMapper(probeType));
357+
return operations.query(sqlQuery, parameterSource, getEntityRowMapper(probeType));
365358
}
366359

367360
@Override
368361
public <T> Iterable<T> select(Query query, Class<T> probeType, Pageable pageable) {
362+
369363
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
370364
String sqlQuery = sql(probeType).selectByQuery(query, parameterSource, pageable);
371365

372-
return operations.query(sqlQuery, parameterSource, (RowMapper<T>) getEntityRowMapper(probeType));
366+
return operations.query(sqlQuery, parameterSource, getEntityRowMapper(probeType));
373367
}
374368

375369
@Override
376370
public <T> boolean exists(Query query, Class<T> probeType) {
377-
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
378371

372+
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
379373
String sqlQuery = sql(probeType).existsByQuery(query, parameterSource);
380374

381375
Boolean result = operations.queryForObject(sqlQuery, parameterSource, Boolean.class);
382-
Assert.notNull(result, "The result of an exists query must not be null");
376+
377+
Assert.state(result != null, "The result of an exists query must not be null");
383378

384379
return result;
385380
}
386381

387382
@Override
388383
public <T> long count(Query query, Class<T> probeType) {
384+
389385
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
390386
String sqlQuery = sql(probeType).countByQuery(query, parameterSource);
391387

392388
Long result = operations.queryForObject(sqlQuery, parameterSource, Long.class);
393389

394-
Assert.notNull(result, "The result of a count query must not be null.");
390+
Assert.state(result != null, "The result of a count query must not be null.");
395391

396392
return result;
397393
}
398394

399-
private EntityRowMapper<?> getEntityRowMapper(Class<?> domainType) {
395+
private <T> EntityRowMapper<T> getEntityRowMapper(Class<T> domainType) {
400396
return new EntityRowMapper<>(getRequiredPersistentEntity(domainType), converter);
401397
}
402398

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.springframework.data.jdbc.core.convert;
1717

1818
import java.util.List;
19+
import java.util.Optional;
1920

2021
import org.springframework.data.domain.Pageable;
2122
import org.springframework.data.domain.Sort;
@@ -26,8 +27,6 @@
2627
import org.springframework.data.relational.core.sql.LockMode;
2728
import org.springframework.util.Assert;
2829

29-
import java.util.Optional;
30-
3130
/**
3231
* Delegates all method calls to an instance set after construction. This is useful for {@link DataAccessStrategy}s with
3332
* cyclic dependencies.

0 commit comments

Comments
 (0)