#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:
@@ -31,6 +31,8 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
*/
|
||||
public class BadSqlGrammarException extends InvalidDataAccessResourceUsageException {
|
||||
|
||||
private static final long serialVersionUID = 3814579246913482054L;
|
||||
|
||||
private final String sql;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user