Skip to content

Commit da53a9a

Browse files
committed
#64 - Polishing.
Incorporated feedback from review. Polished documentation and Javadoc. Minor code improvements restructuring for better readability. Removed unused methods types. Some polishing for compiler warnings. Original pull request: #106.
1 parent 361d801 commit da53a9a

File tree

14 files changed

+100
-135
lines changed

14 files changed

+100
-135
lines changed

src/main/asciidoc/reference/r2dbc-core.adoc

+2-2
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,6 @@ As of writing the following drivers are available:
236236
* https://github.com/r2dbc/r2dbc-mssql[Microsoft SQL Server] (`io.r2dbc:r2dbc-mssql`)
237237
* https://github.com/jasync-sql/jasync-sql[Microsoft SQL Server] (`com.github.jasync-sql:jasync-r2dbc-mysql`)
238238

239-
Spring Data R2DBC reacts to database specifics by inspecting `ConnectionFactoryMetadata` and selects the appropriate database dialect.
240-
You can configure an own `Dialect` if the used driver is not yet known to Spring Data R2DBC.
239+
Spring Data R2DBC reacts to database specifics by inspecting `ConnectionFactoryMetadata` exposed by the `ConnectionFactory` and selects the appropriate database dialect accordingly.
240+
You can configure an own https://docs.spring.io/spring-data/r2dbc/docs/{version}/api/org/springframework/data/r2dbc/dialect/Dialect.html[`Dialect`] if the used driver is not yet known to Spring Data R2DBC.
241241

src/main/asciidoc/reference/r2dbc-databaseclient.adoc

+17-4
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ DatabaseClient.create(ConnectionFactory connectionFactory)
2424

2525
The above method creates a `DatabaseClient` with default settings.
2626

27-
You can also use `DatabaseClient.builder()` with further options to customize the client:
27+
You can also obtain a `Builder` instance via `DatabaseClient.builder()` with further options to customize the client by calling the following methods:
2828

29-
* `exceptionTranslator`: Supply a specific `R2dbcExceptionTranslator` to customize how R2DBC exceptions are translated into Spring's portable Data Access Exception hierarchy. See "`<<r2dbc.exception>>`" for more information.
30-
* `dataAccessStrategy`: Strategy how SQL queries are generated and how objects are mapped.
29+
* `….exceptionTranslator(…)`: Supply a specific `R2dbcExceptionTranslator` to customize how R2DBC exceptions are translated into Spring's portable Data Access Exception hierarchy. See "`<<r2dbc.exception>>`" for more information.
30+
* `….dataAccessStrategy(…)`: Strategy how SQL queries are generated and how objects are mapped.
3131

3232
Once built, a `DatabaseClient` instance is immutable. However, you can clone it and build a modified copy without affecting the original instance, as the following example shows:
3333

@@ -50,6 +50,19 @@ When you use Spring Data R2DBC, you can create a `ConnectionFactory` using your
5050
`ConnectionFactory` implementations can either return the same connection, different connections or provide connection pooling.
5151
`DatabaseClient` uses `ConnectionFactory` to create and release connections per operation without affinity to a particular connection across multiple operations.
5252

53+
Assuming you'd be using H2 as a database, a typical programmatic setup looks something like this:
54+
55+
[source, java]
56+
----
57+
H2ConnectionConfiguration config = … <1>
58+
ConnectionFactory factory = new H2ConnectionFactory(config); <2>
59+
60+
DatabaseClient client = DatabaseClient.create(factory); <3>
61+
----
62+
<1> Prepare the database specific configuration (host, port, credentials etc.)
63+
<2> Create a connection factory using that configuration.
64+
<3> Create a `DatabaseClient` to use that connection factory.
65+
5366
[[r2dbc.exception]]
5467
= Exception Translation
5568

@@ -66,7 +79,7 @@ It considers R2DBC's categorized exception hierarchy to translate these into Spr
6679
`SqlErrorCodeR2dbcExceptionTranslator` uses specific vendor codes using Spring JDBC's `SQLErrorCodes`.
6780
It is more precise than the SQLState implementation.
6881
The error code translations are based on codes held in a JavaBean type class called `SQLErrorCodes`.
69-
This class is created and populated by an `SQLErrorCodesFactory`, which (as the name suggests) is a factory for creating SQLErrorCodes based on the contents of a configuration file named `sql-error-codes.xml` from Spring's Data Access module.
82+
Instances of this class are created and populated by an `SQLErrorCodesFactory`, which (as the name suggests) is a factory for creating SQLErrorCodes based on the contents of a configuration file named `sql-error-codes.xml` from Spring's Data Access module.
7083
This file is populated with vendor codes and based on the `ConnectionFactoryName` taken from `ConnectionFactoryMetadata`.
7184
The codes for the actual database you are using are used.
7285

src/main/java/org/springframework/data/r2dbc/BadSqlGrammarException.java

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
*/
3232
public class BadSqlGrammarException extends InvalidDataAccessResourceUsageException {
3333

34+
private static final long serialVersionUID = 3814579246913482054L;
35+
3436
private final String sql;
3537

3638
/**

src/main/java/org/springframework/data/r2dbc/UncategorizedR2dbcException.java

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
*/
2828
public class UncategorizedR2dbcException extends UncategorizedDataAccessException {
2929

30+
private static final long serialVersionUID = 361587356435210266L;
31+
3032
/**
3133
* SQL that led to the problem
3234
*/

src/main/java/org/springframework/data/r2dbc/function/DefaultDatabaseClient.java

+12-30
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import org.apache.commons.logging.Log;
4646
import org.apache.commons.logging.LogFactory;
4747
import org.reactivestreams.Publisher;
48-
4948
import org.springframework.dao.DataAccessException;
5049
import org.springframework.dao.InvalidDataAccessApiUsageException;
5150
import org.springframework.data.domain.Pageable;
@@ -232,7 +231,7 @@ protected Connection createConnectionProxy(Connection con) {
232231
protected DataAccessException translateException(String task, @Nullable String sql, R2dbcException ex) {
233232

234233
DataAccessException dae = this.exceptionTranslator.translate(task, sql, ex);
235-
return (dae != null ? dae : new UncategorizedR2dbcException(task, sql, ex));
234+
return dae != null ? dae : new UncategorizedR2dbcException(task, sql, ex);
236235
}
237236

238237
/**
@@ -267,25 +266,6 @@ protected DefaultGenericExecuteSpec createGenericExecuteSpec(Supplier<String> sq
267266
return new DefaultGenericExecuteSpec(sqlSupplier);
268267
}
269268

270-
private static void doBind(Statement statement, Map<String, SettableValue> byName,
271-
Map<Integer, SettableValue> byIndex) {
272-
273-
bindByIndex(statement, byIndex);
274-
bindByName(statement, byName);
275-
}
276-
277-
private static void bindByName(Statement statement, Map<String, SettableValue> byName) {
278-
279-
byName.forEach((name, o) -> {
280-
281-
if (o.getValue() != null) {
282-
statement.bind(name, o.getValue());
283-
} else {
284-
statement.bindNull(name, o.getType());
285-
}
286-
});
287-
}
288-
289269
private static void bindByIndex(Statement statement, Map<Integer, SettableValue> byIndex) {
290270

291271
byIndex.forEach((i, o) -> {
@@ -591,7 +571,7 @@ public DefaultTypedExecuteSpec<T> bindNull(int index, Class<?> type) {
591571

592572
@Override
593573
public DefaultTypedExecuteSpec<T> bind(String name, Object value) {
594-
return (DefaultTypedExecuteSpec) super.bind(name, value);
574+
return (DefaultTypedExecuteSpec<T>) super.bind(name, value);
595575
}
596576

597577
@Override
@@ -789,14 +769,11 @@ private class DefaultTypedSelectSpec<T> extends DefaultSelectSpecSupport impleme
789769
this.mappingFunction = dataAccessStrategy.getRowMapper(typeToRead);
790770
}
791771

792-
DefaultTypedSelectSpec(String table, List<String> projectedFields, Criteria criteria, Sort sort, Pageable page,
793-
BiFunction<Row, RowMetadata, T> mappingFunction) {
794-
this(table, projectedFields, criteria, sort, page, null, mappingFunction);
795-
}
796-
797772
DefaultTypedSelectSpec(String table, List<String> projectedFields, Criteria criteria, Sort sort, Pageable page,
798773
Class<T> typeToRead, BiFunction<Row, RowMetadata, T> mappingFunction) {
774+
799775
super(table, projectedFields, criteria, sort, page);
776+
800777
this.typeToRead = typeToRead;
801778
this.mappingFunction = mappingFunction;
802779
}
@@ -900,13 +877,14 @@ class DefaultGenericInsertSpec<T> implements GenericInsertSpec<T> {
900877
private final BiFunction<Row, RowMetadata, T> mappingFunction;
901878

902879
@Override
903-
public GenericInsertSpec value(String field, Object value) {
880+
public GenericInsertSpec<T> value(String field, Object value) {
904881

905882
Assert.notNull(field, "Field must not be null!");
906883
Assert.notNull(value,
907884
() -> String.format("Value for field %s must not be null. Use nullValue(…) instead.", field));
908885

909886
Map<String, SettableValue> byName = new LinkedHashMap<>(this.byName);
887+
910888
if (value instanceof SettableValue) {
911889
byName.put(field, (SettableValue) value);
912890
} else {
@@ -917,7 +895,7 @@ public GenericInsertSpec value(String field, Object value) {
917895
}
918896

919897
@Override
920-
public GenericInsertSpec nullValue(String field) {
898+
public GenericInsertSpec<T> nullValue(String field) {
921899

922900
Assert.notNull(field, "Field must not be null!");
923901

@@ -991,6 +969,7 @@ public TypedInsertSpec<T> table(String tableName) {
991969
}
992970

993971
@Override
972+
@SuppressWarnings({ "rawtypes", "unchecked" })
994973
public InsertSpec using(T objectToInsert) {
995974

996975
Assert.notNull(objectToInsert, "Object to insert must not be null!");
@@ -1000,6 +979,7 @@ public InsertSpec using(T objectToInsert) {
1000979
}
1001980

1002981
@Override
982+
@SuppressWarnings({ "rawtypes", "unchecked" })
1003983
public InsertSpec using(Publisher<T> objectToInsert) {
1004984

1005985
Assert.notNull(objectToInsert, "Publisher to insert must not be null!");
@@ -1417,7 +1397,7 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
14171397

14181398
if (method.getName().equals("equals")) {
14191399
// Only consider equal when proxies are identical.
1420-
return (proxy == args[0]);
1400+
return proxy == args[0];
14211401
} else if (method.getName().equals("hashCode")) {
14221402
// Use hashCode of PersistenceManager proxy.
14231403
return System.identityHashCode(proxy);
@@ -1454,6 +1434,8 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
14541434
@RequiredArgsConstructor
14551435
static class ConnectionCloseHolder extends AtomicBoolean {
14561436

1437+
private static final long serialVersionUID = -8994138383301201380L;
1438+
14571439
final Connection connection;
14581440
final Function<Connection, Publisher<Void>> closeFunction;
14591441

src/main/java/org/springframework/data/r2dbc/function/DefaultStatementFactory.java

-35
This file was deleted.

src/main/java/org/springframework/data/r2dbc/function/convert/MappingR2dbcConverter.java

+20-20
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
* Converter for R2DBC.
5656
*
5757
* @author Mark Paluch
58+
* @author Oliver Drotbohm
5859
*/
5960
public class MappingR2dbcConverter extends BasicRelationalConverter implements R2dbcConverter {
6061

@@ -176,29 +177,29 @@ private Object getPotentiallyConvertedSimpleRead(@Nullable Object value, @Nullab
176177
return getConversionService().convert(value, target);
177178
}
178179

180+
@SuppressWarnings("unchecked")
179181
private <S> S readEntityFrom(Row row, PersistentProperty<?> property) {
180182

181183
String prefix = property.getName() + "_";
182184

183-
RelationalPersistentEntity<S> entity = (RelationalPersistentEntity<S>) getMappingContext()
184-
.getRequiredPersistentEntity(property.getActualType());
185+
RelationalPersistentEntity<?> entity = getMappingContext().getRequiredPersistentEntity(property.getActualType());
185186

186187
if (readFrom(row, entity.getRequiredIdProperty(), prefix) == null) {
187188
return null;
188189
}
189190

190-
S instance = createInstance(row, prefix, entity);
191+
Object instance = createInstance(row, prefix, entity);
191192

192-
PersistentPropertyAccessor<S> accessor = entity.getPropertyAccessor(instance);
193-
ConvertingPropertyAccessor<S> propertyAccessor = new ConvertingPropertyAccessor<>(accessor, getConversionService());
193+
PersistentPropertyAccessor<?> accessor = entity.getPropertyAccessor(instance);
194+
ConvertingPropertyAccessor<?> propertyAccessor = new ConvertingPropertyAccessor<>(accessor, getConversionService());
194195

195196
for (RelationalPersistentProperty p : entity) {
196197
if (!entity.isConstructorArgument(property)) {
197198
propertyAccessor.setProperty(p, readFrom(row, p, prefix));
198199
}
199200
}
200201

201-
return instance;
202+
return (S) instance;
202203
}
203204

204205
private <S> S createInstance(Row row, String prefix, RelationalPersistentEntity<S> entity) {
@@ -346,17 +347,16 @@ public <T> BiFunction<Row, RowMetadata, T> populateIdIfNecessary(T object) {
346347

347348
return (row, metadata) -> {
348349

349-
PersistentPropertyAccessor propertyAccessor = entity.getPropertyAccessor(object);
350+
PersistentPropertyAccessor<?> propertyAccessor = entity.getPropertyAccessor(object);
350351
RelationalPersistentProperty idProperty = entity.getRequiredIdProperty();
351352

352-
if (propertyAccessor.getProperty(idProperty) == null) {
353-
354-
if (potentiallySetId(row, metadata, propertyAccessor, idProperty)) {
355-
return (T) propertyAccessor.getBean();
356-
}
353+
if (propertyAccessor.getProperty(idProperty) != null) {
354+
return object;
357355
}
358356

359-
return object;
357+
return potentiallySetId(row, metadata, propertyAccessor, idProperty) //
358+
? (T) propertyAccessor.getBean() //
359+
: object;
360360
};
361361
}
362362

@@ -376,19 +376,19 @@ private boolean potentiallySetId(Row row, RowMetadata metadata, PersistentProper
376376
generatedIdValue = row.get(key);
377377
}
378378

379-
if (generatedIdValue != null) {
380-
381-
ConversionService conversionService = getConversionService();
382-
propertyAccessor.setProperty(idProperty, conversionService.convert(generatedIdValue, idProperty.getType()));
383-
return true;
379+
if (generatedIdValue == null) {
380+
return false;
384381
}
385382

386-
return false;
383+
ConversionService conversionService = getConversionService();
384+
propertyAccessor.setProperty(idProperty, conversionService.convert(generatedIdValue, idProperty.getType()));
385+
386+
return true;
387387
}
388388

389389
@SuppressWarnings("unchecked")
390390
private <R> RelationalPersistentEntity<R> getRequiredPersistentEntity(Class<R> type) {
391-
return (RelationalPersistentEntity) getMappingContext().getRequiredPersistentEntity(type);
391+
return (RelationalPersistentEntity<R>) getMappingContext().getRequiredPersistentEntity(type);
392392
}
393393

394394
private static Map<String, ColumnMetadata> createMetadataMap(RowMetadata metadata) {

0 commit comments

Comments
 (0)