#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.
This commit is contained in:
Oliver Drotbohm
2019-05-08 10:36:21 +02:00
parent 361d801b14
commit da53a9a934
14 changed files with 100 additions and 135 deletions

View File

@@ -31,6 +31,8 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException;
*/
public class BadSqlGrammarException extends InvalidDataAccessResourceUsageException {
private static final long serialVersionUID = 3814579246913482054L;
private final String sql;
/**

View File

@@ -27,6 +27,8 @@ import org.springframework.lang.Nullable;
*/
public class UncategorizedR2dbcException extends UncategorizedDataAccessException {
private static final long serialVersionUID = 361587356435210266L;
/**
* SQL that led to the problem
*/

View File

@@ -45,7 +45,6 @@ import java.util.stream.Collectors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.reactivestreams.Publisher;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Pageable;
@@ -232,7 +231,7 @@ class DefaultDatabaseClient implements DatabaseClient, ConnectionAccessor {
protected DataAccessException translateException(String task, @Nullable String sql, R2dbcException ex) {
DataAccessException dae = this.exceptionTranslator.translate(task, sql, ex);
return (dae != null ? dae : new UncategorizedR2dbcException(task, sql, ex));
return dae != null ? dae : new UncategorizedR2dbcException(task, sql, ex);
}
/**
@@ -267,25 +266,6 @@ class DefaultDatabaseClient implements DatabaseClient, ConnectionAccessor {
return new DefaultGenericExecuteSpec(sqlSupplier);
}
private static void doBind(Statement statement, Map<String, SettableValue> byName,
Map<Integer, SettableValue> byIndex) {
bindByIndex(statement, byIndex);
bindByName(statement, byName);
}
private static void bindByName(Statement statement, Map<String, SettableValue> byName) {
byName.forEach((name, o) -> {
if (o.getValue() != null) {
statement.bind(name, o.getValue());
} else {
statement.bindNull(name, o.getType());
}
});
}
private static void bindByIndex(Statement statement, Map<Integer, SettableValue> byIndex) {
byIndex.forEach((i, o) -> {
@@ -591,7 +571,7 @@ class DefaultDatabaseClient implements DatabaseClient, ConnectionAccessor {
@Override
public DefaultTypedExecuteSpec<T> bind(String name, Object value) {
return (DefaultTypedExecuteSpec) super.bind(name, value);
return (DefaultTypedExecuteSpec<T>) super.bind(name, value);
}
@Override
@@ -789,14 +769,11 @@ class DefaultDatabaseClient implements DatabaseClient, ConnectionAccessor {
this.mappingFunction = dataAccessStrategy.getRowMapper(typeToRead);
}
DefaultTypedSelectSpec(String table, List<String> projectedFields, Criteria criteria, Sort sort, Pageable page,
BiFunction<Row, RowMetadata, T> mappingFunction) {
this(table, projectedFields, criteria, sort, page, null, mappingFunction);
}
DefaultTypedSelectSpec(String table, List<String> projectedFields, Criteria criteria, Sort sort, Pageable page,
Class<T> typeToRead, BiFunction<Row, RowMetadata, T> mappingFunction) {
super(table, projectedFields, criteria, sort, page);
this.typeToRead = typeToRead;
this.mappingFunction = mappingFunction;
}
@@ -900,13 +877,14 @@ class DefaultDatabaseClient implements DatabaseClient, ConnectionAccessor {
private final BiFunction<Row, RowMetadata, T> mappingFunction;
@Override
public GenericInsertSpec value(String field, Object value) {
public GenericInsertSpec<T> value(String field, Object value) {
Assert.notNull(field, "Field must not be null!");
Assert.notNull(value,
() -> String.format("Value for field %s must not be null. Use nullValue(…) instead.", field));
Map<String, SettableValue> byName = new LinkedHashMap<>(this.byName);
if (value instanceof SettableValue) {
byName.put(field, (SettableValue) value);
} else {
@@ -917,7 +895,7 @@ class DefaultDatabaseClient implements DatabaseClient, ConnectionAccessor {
}
@Override
public GenericInsertSpec nullValue(String field) {
public GenericInsertSpec<T> nullValue(String field) {
Assert.notNull(field, "Field must not be null!");
@@ -991,6 +969,7 @@ class DefaultDatabaseClient implements DatabaseClient, ConnectionAccessor {
}
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public InsertSpec using(T objectToInsert) {
Assert.notNull(objectToInsert, "Object to insert must not be null!");
@@ -1000,6 +979,7 @@ class DefaultDatabaseClient implements DatabaseClient, ConnectionAccessor {
}
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public InsertSpec using(Publisher<T> objectToInsert) {
Assert.notNull(objectToInsert, "Publisher to insert must not be null!");
@@ -1417,7 +1397,7 @@ class DefaultDatabaseClient implements DatabaseClient, ConnectionAccessor {
if (method.getName().equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0]);
return proxy == args[0];
} else if (method.getName().equals("hashCode")) {
// Use hashCode of PersistenceManager proxy.
return System.identityHashCode(proxy);
@@ -1454,6 +1434,8 @@ class DefaultDatabaseClient implements DatabaseClient, ConnectionAccessor {
@RequiredArgsConstructor
static class ConnectionCloseHolder extends AtomicBoolean {
private static final long serialVersionUID = -8994138383301201380L;
final Connection connection;
final Function<Connection, Publisher<Void>> closeFunction;

View File

@@ -1,35 +0,0 @@
/*
* Copyright 2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.r2dbc.function;
import lombok.RequiredArgsConstructor;
import org.springframework.data.r2dbc.dialect.Dialect;
import org.springframework.data.relational.core.sql.render.RenderContext;
/**
* Default {@link StatementFactory} implementation.
*
* @author Mark Paluch
*/
// TODO: Move DefaultPreparedOperation et al to a better place. Probably StatementMapper.
@RequiredArgsConstructor
class DefaultStatementFactory {
private final Dialect dialect;
private final RenderContext renderContext;
}

View File

@@ -55,6 +55,7 @@ import org.springframework.util.ClassUtils;
* Converter for R2DBC.
*
* @author Mark Paluch
* @author Oliver Drotbohm
*/
public class MappingR2dbcConverter extends BasicRelationalConverter implements R2dbcConverter {
@@ -176,21 +177,21 @@ public class MappingR2dbcConverter extends BasicRelationalConverter implements R
return getConversionService().convert(value, target);
}
@SuppressWarnings("unchecked")
private <S> S readEntityFrom(Row row, PersistentProperty<?> property) {
String prefix = property.getName() + "_";
RelationalPersistentEntity<S> entity = (RelationalPersistentEntity<S>) getMappingContext()
.getRequiredPersistentEntity(property.getActualType());
RelationalPersistentEntity<?> entity = getMappingContext().getRequiredPersistentEntity(property.getActualType());
if (readFrom(row, entity.getRequiredIdProperty(), prefix) == null) {
return null;
}
S instance = createInstance(row, prefix, entity);
Object instance = createInstance(row, prefix, entity);
PersistentPropertyAccessor<S> accessor = entity.getPropertyAccessor(instance);
ConvertingPropertyAccessor<S> propertyAccessor = new ConvertingPropertyAccessor<>(accessor, getConversionService());
PersistentPropertyAccessor<?> accessor = entity.getPropertyAccessor(instance);
ConvertingPropertyAccessor<?> propertyAccessor = new ConvertingPropertyAccessor<>(accessor, getConversionService());
for (RelationalPersistentProperty p : entity) {
if (!entity.isConstructorArgument(property)) {
@@ -198,7 +199,7 @@ public class MappingR2dbcConverter extends BasicRelationalConverter implements R
}
}
return instance;
return (S) instance;
}
private <S> S createInstance(Row row, String prefix, RelationalPersistentEntity<S> entity) {
@@ -346,17 +347,16 @@ public class MappingR2dbcConverter extends BasicRelationalConverter implements R
return (row, metadata) -> {
PersistentPropertyAccessor propertyAccessor = entity.getPropertyAccessor(object);
PersistentPropertyAccessor<?> propertyAccessor = entity.getPropertyAccessor(object);
RelationalPersistentProperty idProperty = entity.getRequiredIdProperty();
if (propertyAccessor.getProperty(idProperty) == null) {
if (potentiallySetId(row, metadata, propertyAccessor, idProperty)) {
return (T) propertyAccessor.getBean();
}
if (propertyAccessor.getProperty(idProperty) != null) {
return object;
}
return object;
return potentiallySetId(row, metadata, propertyAccessor, idProperty) //
? (T) propertyAccessor.getBean() //
: object;
};
}
@@ -376,19 +376,19 @@ public class MappingR2dbcConverter extends BasicRelationalConverter implements R
generatedIdValue = row.get(key);
}
if (generatedIdValue != null) {
ConversionService conversionService = getConversionService();
propertyAccessor.setProperty(idProperty, conversionService.convert(generatedIdValue, idProperty.getType()));
return true;
if (generatedIdValue == null) {
return false;
}
return false;
ConversionService conversionService = getConversionService();
propertyAccessor.setProperty(idProperty, conversionService.convert(generatedIdValue, idProperty.getType()));
return true;
}
@SuppressWarnings("unchecked")
private <R> RelationalPersistentEntity<R> getRequiredPersistentEntity(Class<R> type) {
return (RelationalPersistentEntity) getMappingContext().getRequiredPersistentEntity(type);
return (RelationalPersistentEntity<R>) getMappingContext().getRequiredPersistentEntity(type);
}
private static Map<String, ColumnMetadata> createMetadataMap(RowMetadata metadata) {

View File

@@ -30,6 +30,7 @@ import org.springframework.util.Assert;
* {@code where(property(…).is(…)}.
*
* @author Mark Paluch
* @author Oliver Drotbohm
*/
public class Criteria {
@@ -164,7 +165,7 @@ public class Criteria {
/**
* Creates a {@link Criteria} using equality.
*
* @param value
* @param value must not be {@literal null}.
* @return
*/
Criteria is(Object value);
@@ -172,7 +173,7 @@ public class Criteria {
/**
* Creates a {@link Criteria} using equality (is not).
*
* @param value
* @param value must not be {@literal null}.
* @return
*/
Criteria not(Object value);
@@ -180,7 +181,7 @@ public class Criteria {
/**
* Creates a {@link Criteria} using {@code IN}.
*
* @param values
* @param values must not be {@literal null}.
* @return
*/
Criteria in(Object... values);
@@ -188,7 +189,7 @@ public class Criteria {
/**
* Creates a {@link Criteria} using {@code IN}.
*
* @param values
* @param values must not be {@literal null}.
* @return
*/
Criteria in(Collection<? extends Object> values);
@@ -196,7 +197,7 @@ public class Criteria {
/**
* Creates a {@link Criteria} using {@code NOT IN}.
*
* @param values
* @param values must not be {@literal null}.
* @return
*/
Criteria notIn(Object... values);
@@ -204,7 +205,7 @@ public class Criteria {
/**
* Creates a {@link Criteria} using {@code NOT IN}.
*
* @param values
* @param values must not be {@literal null}.
* @return
*/
Criteria notIn(Collection<? extends Object> values);
@@ -212,7 +213,7 @@ public class Criteria {
/**
* Creates a {@link Criteria} using less-than ({@literal <}).
*
* @param value
* @param value must not be {@literal null}.
* @return
*/
Criteria lessThan(Object value);
@@ -220,7 +221,7 @@ public class Criteria {
/**
* Creates a {@link Criteria} using less-than or equal to ({@literal <=}).
*
* @param value
* @param value must not be {@literal null}.
* @return
*/
Criteria lessThanOrEquals(Object value);
@@ -228,7 +229,7 @@ public class Criteria {
/**
* Creates a {@link Criteria} using greater-than({@literal >}).
*
* @param value
* @param value must not be {@literal null}.
* @return
*/
Criteria greaterThan(Object value);
@@ -236,7 +237,7 @@ public class Criteria {
/**
* Creates a {@link Criteria} using greater-than or equal to ({@literal >=}).
*
* @param value
* @param value must not be {@literal null}.
* @return
*/
Criteria greaterThanOrEquals(Object value);
@@ -244,7 +245,7 @@ public class Criteria {
/**
* Creates a {@link Criteria} using {@code LIKE}.
*
* @param value
* @param value must not be {@literal null}.
* @return
*/
Criteria like(Object value);
@@ -304,6 +305,7 @@ public class Criteria {
public Criteria in(Object... values) {
Assert.notNull(values, "Values must not be null!");
Assert.noNullElements(values, "Values must not contain a null value!");
if (values.length > 1 && values[1] instanceof Collection) {
throw new InvalidDataAccessApiUsageException(
@@ -321,6 +323,7 @@ public class Criteria {
public Criteria in(Collection<?> values) {
Assert.notNull(values, "Values must not be null!");
Assert.noNullElements(values.toArray(), "Values must not contain a null value!");
return createCriteria(Comparator.IN, values);
}
@@ -333,6 +336,7 @@ public class Criteria {
public Criteria notIn(Object... values) {
Assert.notNull(values, "Values must not be null!");
Assert.noNullElements(values, "Values must not contain a null value!");
if (values.length > 1 && values[1] instanceof Collection) {
throw new InvalidDataAccessApiUsageException(
@@ -350,6 +354,7 @@ public class Criteria {
public Criteria notIn(Collection<?> values) {
Assert.notNull(values, "Values must not be null!");
Assert.noNullElements(values.toArray(), "Values must not contain a null value!");
return createCriteria(Comparator.NOT_IN, values);
}

View File

@@ -204,20 +204,22 @@ public class QueryMapper {
private Condition createCondition(Column column, @Nullable Object mappedValue, Class<?> valueType,
MutableBindings bindings, Comparator comparator) {
switch (comparator) {
case IS_NULL:
return column.isNull();
case IS_NOT_NULL:
return column.isNotNull();
if (comparator.equals(Comparator.IS_NULL)) {
return column.isNull();
}
if (comparator.equals(Comparator.IS_NOT_NULL)) {
return column.isNotNull();
}
if (comparator == Comparator.NOT_IN || comparator == Comparator.IN) {
Condition condition;
if (mappedValue instanceof Iterable) {
List<Expression> expressions = new ArrayList<>(
mappedValue instanceof Collection ? ((Collection) mappedValue).size() : 10);
mappedValue instanceof Collection ? ((Collection<?>) mappedValue).size() : 10);
for (Object o : (Iterable<?>) mappedValue) {
@@ -260,9 +262,9 @@ public class QueryMapper {
return column.isGreaterOrEqualTo(expression);
case LIKE:
return column.like(expression);
default:
throw new UnsupportedOperationException("Comparator " + comparator + " not supported");
}
throw new UnsupportedOperationException("Comparator " + comparator + " not supported");
}
Field createPropertyField(@Nullable RelationalPersistentEntity<?> entity, String key,

View File

@@ -18,7 +18,6 @@ package org.springframework.data.r2dbc.function.query;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -27,6 +26,7 @@ import org.springframework.util.Assert;
* Class to easily construct SQL update assignments.
*
* @author Mark Paluch
* @author Oliver Drotbohm
*/
public class Update {
@@ -41,8 +41,8 @@ public class Update {
/**
* Static factory method to create an {@link Update} using the provided column.
*
* @param column
* @param value
* @param column must not be {@literal null}.
* @param value can be {@literal null}.
* @return
*/
public static Update update(String column, @Nullable Object value) {
@@ -52,14 +52,23 @@ public class Update {
/**
* Update a column by assigning a value.
*
* @param column
* @param value
* @param column must not be {@literal null}.
* @param value can be {@literal null}.
* @return
*/
public Update set(String column, @Nullable Object value) {
return addMultiFieldOperation(column, value);
}
/**
* Returns all assignments.
*
* @return
*/
public Map<String, Object> getAssignments() {
return Collections.unmodifiableMap(this.columnsToUpdate);
}
private Update addMultiFieldOperation(String key, Object value) {
Assert.hasText(key, "Column for update must not be null or blank");
@@ -69,18 +78,4 @@ public class Update {
return new Update(updates);
}
/**
* Performs the given action for each column-value tuple in this {@link Update object} until all entries have been
* processed or the action throws an exception.
*
* @param action must not be {@literal null}.
*/
void forEachColumn(BiConsumer<? super String, ? super Object> action) {
this.columnsToUpdate.forEach(action);
}
public Map<String, Object> getAssignments() {
return Collections.unmodifiableMap(this.columnsToUpdate);
}
}

View File

@@ -51,7 +51,10 @@ import org.springframework.util.ClassUtils;
*/
public class R2dbcQueryMethod extends QueryMethod {
@SuppressWarnings("rawtypes") //
private static final ClassTypeInformation<Page> PAGE_TYPE = ClassTypeInformation.from(Page.class);
@SuppressWarnings("rawtypes") //
private static final ClassTypeInformation<Slice> SLICE_TYPE = ClassTypeInformation.from(Slice.class);
private final Method method;