Skip to content

Commit 0a0e774

Browse files
committed
DATAJDBC-137 - Fixes warnings and improves Javadoc.
All packages now use @NoNullApi. All warnings related to that fixed, except a few cases where upstream annotations are simply wrong. Added null checks. Fixed generic types where possible. Improved Javadoc. Code Formatting.
1 parent b9c6b8b commit 0a0e774

File tree

62 files changed

+716
-196
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+716
-196
lines changed

src/main/java/org/springframework/data/jdbc/core/CascadingDataAccessStrategy.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public <T> void deleteAll(Class<T> domainType) {
6565
}
6666

6767
@Override
68-
public <T> void deleteAll(PropertyPath propertyPath) {
68+
public void deleteAll(PropertyPath propertyPath) {
6969
collectVoid(das -> das.deleteAll(propertyPath));
7070
}
7171

@@ -100,7 +100,7 @@ public <T> boolean existsById(Object id, Class<T> domainType) {
100100
}
101101

102102
private <T> T collect(Function<DataAccessStrategy, T> function) {
103-
return strategies.stream().collect(new FunctionCollector<T>(function));
103+
return strategies.stream().collect(new FunctionCollector<>(function));
104104
}
105105

106106
private void collectVoid(Consumer<DataAccessStrategy> consumer) {

src/main/java/org/springframework/data/jdbc/core/DataAccessStrategy.java

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,45 +19,108 @@
1919

2020
import org.springframework.data.jdbc.core.mapping.JdbcPersistentProperty;
2121
import org.springframework.data.mapping.PropertyPath;
22+
import org.springframework.lang.Nullable;
2223

2324
/**
24-
* Abstraction for accesses to the database that should be implementable with a single SQL statement and relates to a
25-
* single entity as opposed to {@link JdbcEntityOperations} which provides interactions related to complete aggregates.
25+
* Abstraction for accesses to the database that should be implementable with a single SQL statement per method and
26+
* relates to a single entity as opposed to {@link JdbcAggregateOperations} which provides interactions related to
27+
* complete aggregates.
2628
*
2729
* @author Jens Schauder
2830
* @since 1.0
2931
*/
3032
public interface DataAccessStrategy {
3133

34+
/**
35+
* Inserts a the data of a single entity. Referenced entities don't get handled.
36+
*
37+
* @param instance the instance to be stored. Must not be {@code null}.
38+
* @param domainType the type of the instance. Must not be {@code null}.
39+
* @param additionalParameters name-value pairs of additional parameters. Especially ids of parent entities that need
40+
* to get referenced are contained in this map. Must not be {@code null}.
41+
* @param <T> the type of the instance.
42+
*/
3243
<T> void insert(T instance, Class<T> domainType, Map<String, Object> additionalParameters);
3344

45+
/**
46+
* Updates the data of a single entity in the database. Referenced entities don't get handled.
47+
*
48+
* @param instance the instance to save. Must not be {@code null}.
49+
* @param domainType the type of the instance to save. Must not be {@code null}.
50+
* @param <T> the type of the instance to save.
51+
*/
3452
<T> void update(T instance, Class<T> domainType);
3553

54+
/**
55+
* deletes a single row identified by the id, from the table identified by the domainType. Does not handle cascading
56+
* deletes.
57+
*
58+
* @param id the id of the row to be deleted. Must not be {@code null}.
59+
* @param domainType the type of entity to be deleted. Implicitely determines the table to operate on. Must not be
60+
* {@code null}.
61+
*/
3662
void delete(Object id, Class<?> domainType);
3763

3864
/**
3965
* Deletes all entities reachable via {@literal propertyPath} from the instance identified by {@literal rootId}.
4066
*
41-
* @param rootId Id of the root object on which the {@literal propertyPath} is based.
42-
* @param propertyPath Leading from the root object to the entities to be deleted.
67+
* @param rootId Id of the root object on which the {@literal propertyPath} is based. Must not be {@code null}.
68+
* @param propertyPath Leading from the root object to the entities to be deleted. Must not be {@code null}.
4369
*/
4470
void delete(Object rootId, PropertyPath propertyPath);
4571

72+
/**
73+
* Deletes all entities of the given domain type.
74+
*
75+
* @param domainType the domain type for which to delete all entries. Must not be {@code null}.
76+
* @param <T> type of the domain type.
77+
*/
4678
<T> void deleteAll(Class<T> domainType);
4779

4880
/**
4981
* Deletes all entities reachable via {@literal propertyPath} from any instance.
5082
*
51-
* @param propertyPath Leading from the root object to the entities to be deleted.
83+
* @param propertyPath Leading from the root object to the entities to be deleted. Must not be {@code null}.
5284
*/
53-
<T> void deleteAll(PropertyPath propertyPath);
85+
void deleteAll(PropertyPath propertyPath);
5486

87+
/**
88+
* Counts the rows in the table representing the given domain type.
89+
*
90+
* @param domainType the domain type for which to count the elements. Must not be {@code null}.
91+
* @return the count. Guaranteed to be not {@code null}.
92+
*/
5593
long count(Class<?> domainType);
5694

95+
/**
96+
* Loads a single entity identified by type and id.
97+
*
98+
* @param id the id of the entity to load. Must not be {@code null}.
99+
* @param domainType the domain type of the entity. Must not be {@code null}.
100+
* @param <T> the type of the entity.
101+
* @return Might return {@code null}.
102+
*/
103+
@Nullable
57104
<T> T findById(Object id, Class<T> domainType);
58105

106+
/**
107+
* Loads alls entities of the given type.
108+
*
109+
* @param domainType the type of entities to load. Must not be {@code null}.
110+
* @param <T> the type of entities to load.
111+
* @return Guaranteed to be not {@code null}.
112+
*/
59113
<T> Iterable<T> findAll(Class<T> domainType);
60114

115+
/**
116+
* Loads all entities that match one of the ids passed as an argument. It is not guaranteed that the number of ids
117+
* passed in matches the number of entities returned.
118+
*
119+
* @param ids the Ids of the entities to load. Must not be {@code null}.
120+
* @param domainType the type of entities to laod. Must not be {@code null}.
121+
* @param <T> type of entities to load.
122+
* @return the loaded entities. Guaranteed to be not {@code null}.
123+
*/
61124
<T> Iterable<T> findAllById(Iterable<?> ids, Class<T> domainType);
62125

63126
/**
@@ -68,5 +131,13 @@ public interface DataAccessStrategy {
68131
*/
69132
<T> Iterable<T> findAllByProperty(Object rootId, JdbcPersistentProperty property);
70133

134+
/**
135+
* returns if a row with the given id exists for the given type.
136+
*
137+
* @param id the id of the entity for which to check. Must not be {@code null}.
138+
* @param domainType the type of the entity to check for. Must not be {@code null}.
139+
* @param <T> the type of the entity.
140+
* @return {@code true} if a matching row exists, otherwise {@code false}.
141+
*/
71142
<T> boolean existsById(Object id, Class<T> domainType);
72143
}

src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
4242
import org.springframework.jdbc.support.GeneratedKeyHolder;
4343
import org.springframework.jdbc.support.KeyHolder;
44+
import org.springframework.lang.Nullable;
4445
import org.springframework.util.Assert;
4546

4647
/**
@@ -88,6 +89,9 @@ public <T> void insert(T instance, Class<T> domainType, Map<String, Object> addi
8889
JdbcPersistentProperty idProperty = persistentEntity.getIdProperty();
8990

9091
if (idValue != null) {
92+
93+
Assert.notNull(idProperty, "Since we have a non-null idValue, we must have an idProperty as well.");
94+
9195
additionalParameters.put(idProperty.getColumnName(), convert(idValue, idProperty.getColumnType()));
9296
}
9397

@@ -167,7 +171,7 @@ public <T> void deleteAll(Class<T> domainType) {
167171
* @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(org.springframework.data.mapping.PropertyPath)
168172
*/
169173
@Override
170-
public <T> void deleteAll(PropertyPath propertyPath) {
174+
public void deleteAll(PropertyPath propertyPath) {
171175
operations.getJdbcOperations().update(sql(propertyPath.getOwningType().getType()).createDeleteAllSql(propertyPath));
172176
}
173177

@@ -177,21 +181,27 @@ public <T> void deleteAll(PropertyPath propertyPath) {
177181
*/
178182
@Override
179183
public long count(Class<?> domainType) {
180-
return operations.getJdbcOperations().queryForObject(sql(domainType).getCount(), Long.class);
184+
185+
Long result = operations.getJdbcOperations().queryForObject(sql(domainType).getCount(), Long.class);
186+
187+
Assert.notNull(result, "The result of a count query must not be null.");
188+
189+
return result;
181190
}
182191

183192
/*
184193
* (non-Javadoc)
185194
* @see org.springframework.data.jdbc.core.DataAccessStrategy#findById(java.lang.Object, java.lang.Class)
186195
*/
196+
@SuppressWarnings("unchecked")
187197
@Override
188198
public <T> T findById(Object id, Class<T> domainType) {
189199

190200
String findOneSql = sql(domainType).getFindOne();
191201
MapSqlParameterSource parameter = createIdParameterSource(id, domainType);
192202

193203
try {
194-
return operations.queryForObject(findOneSql, parameter, getEntityRowMapper(domainType));
204+
return operations.queryForObject(findOneSql, parameter, (RowMapper<T>) getEntityRowMapper(domainType));
195205
} catch (EmptyResultDataAccessException e) {
196206
return null;
197207
}
@@ -201,15 +211,17 @@ public <T> T findById(Object id, Class<T> domainType) {
201211
* (non-Javadoc)
202212
* @see org.springframework.data.jdbc.core.DataAccessStrategy#findAll(java.lang.Class)
203213
*/
214+
@SuppressWarnings("unchecked")
204215
@Override
205216
public <T> Iterable<T> findAll(Class<T> domainType) {
206-
return operations.query(sql(domainType).getFindAll(), getEntityRowMapper(domainType));
217+
return operations.query(sql(domainType).getFindAll(), (RowMapper<T>) getEntityRowMapper(domainType));
207218
}
208219

209220
/*
210221
* (non-Javadoc)
211222
* @see org.springframework.data.jdbc.core.DataAccessStrategy#findAllById(java.lang.Iterable, java.lang.Class)
212223
*/
224+
@SuppressWarnings("unchecked")
213225
@Override
214226
public <T> Iterable<T> findAllById(Iterable<?> ids, Class<T> domainType) {
215227

@@ -223,7 +235,7 @@ public <T> Iterable<T> findAllById(Iterable<?> ids, Class<T> domainType) {
223235
.collect(Collectors.toList()) //
224236
);
225237

226-
return operations.query(findAllInListSql, parameter, getEntityRowMapper(domainType));
238+
return operations.query(findAllInListSql, parameter, (RowMapper<T>) getEntityRowMapper(domainType));
227239
}
228240

229241
/*
@@ -242,9 +254,10 @@ public <T> Iterable<T> findAllByProperty(Object rootId, JdbcPersistentProperty p
242254

243255
MapSqlParameterSource parameter = new MapSqlParameterSource(property.getReverseColumnName(), rootId);
244256

245-
return (Iterable<T>) operations.query(findAllByProperty, parameter, property.isMap() //
246-
? getMapEntityRowMapper(property) //
247-
: getEntityRowMapper(actualType));
257+
return operations.query(findAllByProperty, parameter, //
258+
(RowMapper<T>) (property.isMap() //
259+
? this.getMapEntityRowMapper(property) //
260+
: this.getEntityRowMapper(actualType)));
248261
}
249262

250263
/*
@@ -257,7 +270,11 @@ public <T> boolean existsById(Object id, Class<T> domainType) {
257270
String existsSql = sql(domainType).getExists();
258271
MapSqlParameterSource parameter = createIdParameterSource(id, domainType);
259272

260-
return operations.queryForObject(existsSql, parameter, Boolean.class);
273+
Boolean result = operations.queryForObject(existsSql, parameter, Boolean.class);
274+
275+
Assert.notNull(result, "The result of an exists query must not be null");
276+
277+
return result;
261278
}
262279

263280
private <S> MapSqlParameterSource getPropertyMap(final S instance, JdbcPersistentEntity<S> persistentEntity) {
@@ -277,14 +294,16 @@ private <S> MapSqlParameterSource getPropertyMap(final S instance, JdbcPersisten
277294
}
278295

279296
@SuppressWarnings("unchecked")
297+
@Nullable
280298
private <S, ID> ID getIdValueOrNull(S instance, JdbcPersistentEntity<S> persistentEntity) {
281299

282300
ID idValue = (ID) persistentEntity.getIdentifierAccessor(instance).getIdentifier();
283301

284302
return isIdPropertyNullOrScalarZero(idValue, persistentEntity) ? null : idValue;
285303
}
286304

287-
private static <S, ID> boolean isIdPropertyNullOrScalarZero(ID idValue, JdbcPersistentEntity<S> persistentEntity) {
305+
private static <S, ID> boolean isIdPropertyNullOrScalarZero(@Nullable ID idValue,
306+
JdbcPersistentEntity<S> persistentEntity) {
288307

289308
JdbcPersistentProperty idProperty = persistentEntity.getIdProperty();
290309
return idValue == null //
@@ -319,30 +338,38 @@ private <S> Optional<Object> getIdFromHolder(KeyHolder holder, JdbcPersistentEnt
319338
return Optional.ofNullable(holder.getKey());
320339
} catch (InvalidDataAccessApiUsageException e) {
321340
// Postgres returns a value for each column
322-
return Optional.ofNullable(holder.getKeys().get(persistentEntity.getIdColumn()));
341+
Map<String, Object> keys = holder.getKeys();
342+
return Optional.ofNullable(keys == null ? null : keys.get(persistentEntity.getIdColumn()));
323343
}
324344
}
325345

326-
public <T> EntityRowMapper<T> getEntityRowMapper(Class<T> domainType) {
346+
public EntityRowMapper<?> getEntityRowMapper(Class<?> domainType) {
327347
return new EntityRowMapper<>(getRequiredPersistentEntity(domainType), context, instantiators, accessStrategy);
328348
}
329349

330-
private RowMapper getMapEntityRowMapper(JdbcPersistentProperty property) {
331-
return new MapEntityRowMapper(getEntityRowMapper(property.getActualType()), property.getKeyColumn());
350+
@SuppressWarnings("unchecked")
351+
private RowMapper<?> getMapEntityRowMapper(JdbcPersistentProperty property) {
352+
353+
String keyColumn = property.getKeyColumn();
354+
355+
Assert.notNull(keyColumn, () -> "keyColumn must not be null for " + property);
356+
357+
return new MapEntityRowMapper<>(getEntityRowMapper(property.getActualType()), keyColumn);
332358
}
333359

334360
private <T> MapSqlParameterSource createIdParameterSource(Object id, Class<T> domainType) {
335361

336-
return new MapSqlParameterSource("id",
337-
convert(id, getRequiredPersistentEntity(domainType).getRequiredIdProperty().getColumnType()));
362+
Class<?> columnType = getRequiredPersistentEntity(domainType).getRequiredIdProperty().getColumnType();
363+
return new MapSqlParameterSource("id", convert(id, columnType));
338364
}
339365

340366
@SuppressWarnings("unchecked")
341367
private <S> JdbcPersistentEntity<S> getRequiredPersistentEntity(Class<S> domainType) {
342368
return (JdbcPersistentEntity<S>) context.getRequiredPersistentEntity(domainType);
343369
}
344370

345-
private <V> V convert(Object from, Class<V> to) {
371+
@Nullable
372+
private <V> V convert(@Nullable Object from, Class<V> to) {
346373

347374
if (from == null) {
348375
return null;

src/main/java/org/springframework/data/jdbc/core/DefaultJdbcInterpreter.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.data.jdbc.core.mapping.JdbcPersistentEntity;
2828
import org.springframework.data.jdbc.core.conversion.Interpreter;
2929
import org.springframework.data.mapping.PropertyPath;
30+
import org.springframework.lang.Nullable;
3031
import org.springframework.util.Assert;
3132

3233
/**
@@ -103,6 +104,7 @@ private <T> void addDependingOnInformation(Insert<T> insert, Map<String, Object>
103104
additionalColumnValues.put(columnName, identifier);
104105
}
105106

107+
@Nullable
106108
private Object getIdFromEntityDependingOn(DbAction dependingOn, JdbcPersistentEntity<?> persistentEntity) {
107109
return persistentEntity.getIdentifierAccessor(dependingOn.getEntity()).getIdentifier();
108110
}

src/main/java/org/springframework/data/jdbc/core/DelegatingDataAccessStrategy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public <T> void deleteAll(Class<T> domainType) {
5858
}
5959

6060
@Override
61-
public <T> void deleteAll(PropertyPath propertyPath) {
61+
public void deleteAll(PropertyPath propertyPath) {
6262
delegate.deleteAll(propertyPath);
6363
}
6464

0 commit comments

Comments
 (0)