#2 - Polishing.

This commit is contained in:
Mark Paluch
2018-10-17 11:04:34 +02:00
parent ce0a707500
commit 12dc98bcbd
28 changed files with 254 additions and 753 deletions

View File

@@ -1,68 +0,0 @@
/*
* Copyright 2017-2018 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
*
* http://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.jdbc.repository.config;
import java.util.Locale;
import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactoryBean;
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport;
import org.springframework.data.repository.core.RepositoryMetadata;
/**
* {@link org.springframework.data.repository.config.RepositoryConfigurationExtension} extending the repository
* registration process by registering JDBC repositories.
*
* @author Jens Schauder
* @author Mark Paluch
*/
public class JdbcRepositoryConfigExtension extends RepositoryConfigurationExtensionSupport {
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryConfigurationExtension#getModuleName()
*/
@Override
public String getModuleName() {
return "JDBC";
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getRepositoryFactoryBeanClassName()
*/
@Override
public String getRepositoryFactoryBeanClassName() {
return JdbcRepositoryFactoryBean.class.getName();
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getModulePrefix()
*/
@Override
protected String getModulePrefix() {
return getModuleName().toLowerCase(Locale.US);
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#useRepositoryConfiguration(org.springframework.data.repository.core.RepositoryMetadata)
*/
@Override
protected boolean useRepositoryConfiguration(RepositoryMetadata metadata) {
return !metadata.isReactiveRepository();
}
}

View File

@@ -315,7 +315,6 @@ public interface DatabaseClient {
*/
S project(String... selectedFields);
/**
* Configure {@link Sort}.
*

View File

@@ -48,28 +48,27 @@ class DefaultSqlResult<T> implements SqlResult<T> {
this.resultFunction = resultFunction;
this.updatedRowsFunction = updatedRowsFunction;
this.fetchSpec = new DefaultFetchSpec<>(connectionAccessor, sql,
new SqlFunction<Connection, Flux<T>>() {
@Override
public Flux<T> apply(Connection connection) {
return resultFunction.apply(connection).flatMap(result -> result.map(mappingFunction));
}
this.fetchSpec = new DefaultFetchSpec<>(connectionAccessor, sql, new SqlFunction<Connection, Flux<T>>() {
@Override
public Flux<T> apply(Connection connection) {
return resultFunction.apply(connection).flatMap(result -> result.map(mappingFunction));
}
@Override
public String getSql() {
return sql;
}
}, new SqlFunction<Connection, Mono<Integer>>() {
@Override
public Mono<Integer> apply(Connection connection) {
return updatedRowsFunction.apply(connection);
}
@Override
public String getSql() {
return sql;
}
}, new SqlFunction<Connection, Mono<Integer>>() {
@Override
public Mono<Integer> apply(Connection connection) {
return updatedRowsFunction.apply(connection);
}
@Override
public String getSql() {
return sql;
}
});
@Override
public String getSql() {
return sql;
}
});
}
/* (non-Javadoc)

View File

@@ -155,8 +155,7 @@ public class EntityRowMapper<T> implements BiFunction<Row, RowMetadata, T> {
String column = prefix + entity.getRequiredPersistentProperty(parameter.getName()).getColumnName();
try {
return conversionService.convert(resultSet.get(column),
parameter.getType().getType());
return conversionService.convert(resultSet.get(column), parameter.getType().getType());
} catch (Exception o_O) {
throw new MappingException(String.format("Couldn't read column %s from Row.", column), o_O);
}

View File

@@ -109,4 +109,3 @@ public class MappingR2dbcConverter {
return relationalConverter.getMappingContext();
}
}

View File

@@ -13,25 +13,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.relational.repository.query;
package org.springframework.data.r2dbc.repository.query;
import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.Parameters;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.data.annotation.QueryAnnotation;
/**
* JDBC-specific {@link ParameterAccessor}.
*
* Annotation to provide SQL statements that will get used for executing the method.
*
* @author Mark Paluch
*/
public interface RelationalParameterAccessor extends ParameterAccessor {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@QueryAnnotation
@Documented
public @interface Query {
/**
* Returns the raw parameter values of the underlying query method.
* The SQL statement to execute when the annotated method gets invoked.
*/
Object[] getValues();
/**
* @return the bindable parameters.
*/
Parameters<?, ?> getBindableParameters();
String value();
}

View File

@@ -26,7 +26,6 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.data.jdbc.repository.query.Query;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.data.r2dbc.repository.query;
import org.springframework.data.jdbc.repository.query.Query;
import org.springframework.data.r2dbc.function.DatabaseClient;
import org.springframework.data.r2dbc.function.DatabaseClient.BindSpec;
import org.springframework.data.r2dbc.function.convert.MappingR2dbcConverter;

View File

@@ -1,108 +0,0 @@
/*
* Copyright 2018 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
*
* http://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.relational.repository.query;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.EntityInstantiator;
import org.springframework.data.convert.EntityInstantiators;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.PreferredConstructor;
import org.springframework.data.mapping.PreferredConstructor.Parameter;
import org.springframework.data.mapping.SimplePropertyHandler;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.ParameterValueProvider;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.util.Assert;
/**
* {@link Converter} to instantiate DTOs from fully equipped domain objects.
*
* @author Mark Paluch
*/
public class DtoInstantiatingConverter implements Converter<Object, Object> {
private final Class<?> targetType;
private final MappingContext<? extends PersistentEntity<?, ?>, ? extends PersistentProperty<?>> context;
private final EntityInstantiator instantiator;
/**
* Creates a new {@link Converter} to instantiate DTOs.
*
* @param dtoType must not be {@literal null}.
* @param context must not be {@literal null}.
* @param instantiators must not be {@literal null}.
*/
public DtoInstantiatingConverter(Class<?> dtoType,
MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> context,
EntityInstantiators instantiator) {
Assert.notNull(dtoType, "DTO type must not be null!");
Assert.notNull(context, "MappingContext must not be null!");
Assert.notNull(instantiator, "EntityInstantiators must not be null!");
this.targetType = dtoType;
this.context = context;
this.instantiator = instantiator.getInstantiatorFor(context.getRequiredPersistentEntity(dtoType));
}
/*
* (non-Javadoc)
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public Object convert(Object source) {
if (targetType.isInterface()) {
return source;
}
final PersistentEntity<?, ?> sourceEntity = context.getRequiredPersistentEntity(source.getClass());
final PersistentPropertyAccessor sourceAccessor = sourceEntity.getPropertyAccessor(source);
final PersistentEntity<?, ?> targetEntity = context.getRequiredPersistentEntity(targetType);
final PreferredConstructor<?, ? extends PersistentProperty<?>> constructor = targetEntity
.getPersistenceConstructor();
@SuppressWarnings({ "rawtypes", "unchecked" })
Object dto = instantiator.createInstance(targetEntity, new ParameterValueProvider() {
@Override
public Object getParameterValue(Parameter parameter) {
return sourceAccessor.getProperty(sourceEntity.getPersistentProperty(parameter.getName()));
}
});
final PersistentPropertyAccessor dtoAccessor = targetEntity.getPropertyAccessor(dto);
targetEntity.doWithProperties(new SimplePropertyHandler() {
@Override
public void doWithPersistentProperty(PersistentProperty<?> property) {
if (constructor.isConstructorParameter(property)) {
return;
}
dtoAccessor.setProperty(property,
sourceAccessor.getProperty(sourceEntity.getPersistentProperty(property.getName())));
}
});
return dto;
}
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2018 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
*
* http://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.relational.repository.query;
import org.springframework.data.repository.core.EntityInformation;
/**
* Relational database-specific {@link EntityInformation}.
*
* @author Mark Paluch
*/
public interface RelationalEntityInformation<T, ID> extends EntityInformation<T, ID> {
/**
* Returns the name of the table the entity shall be persisted to.
*
* @return
*/
String getTableName();
}

View File

@@ -1,41 +0,0 @@
/*
* Copyright 2018 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
*
* http://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.relational.repository.query;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.repository.core.EntityMetadata;
/**
* Extension of {@link EntityMetadata} to additionally expose the collection name an entity shall be persisted to.
*
* @author Mark Paluch
*/
public interface RelationalEntityMetadata<T> extends EntityMetadata<T> {
/**
* Returns the name of the table the entity shall be persisted to.
*
* @return
*/
String getTableName();
/**
* Returns the {@link RelationalPersistentEntity} that supposed to determine the table to be queried.
*
* @return
*/
RelationalPersistentEntity<?> getTableEntity();
}

View File

@@ -1,80 +0,0 @@
/*
* Copyright 2018 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
*
* http://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.relational.repository.query;
import java.lang.reflect.Method;
import java.util.List;
import org.springframework.core.MethodParameter;
import org.springframework.data.relational.repository.query.RelationalParameters.RelationalParameter;
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.Parameters;
/**
* Custom extension of {@link Parameters}.
*
* @author Mark Paluch
*/
public class RelationalParameters extends Parameters<RelationalParameters, RelationalParameter> {
/**
* Creates a new {@link RelationalParameters} instance from the given {@link Method}.
*
* @param method must not be {@literal null}.
*/
public RelationalParameters(Method method) {
super(method);
}
private RelationalParameters(List<RelationalParameter> parameters) {
super(parameters);
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.Parameters#createParameter(org.springframework.core.MethodParameter)
*/
@Override
protected RelationalParameter createParameter(MethodParameter parameter) {
return new RelationalParameter(parameter);
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.Parameters#createFrom(java.util.List)
*/
@Override
protected RelationalParameters createFrom(List<RelationalParameter> parameters) {
return new RelationalParameters(parameters);
}
/**
* Custom {@link Parameter} implementation.
*
* @author Mark Paluch
*/
public static class RelationalParameter extends Parameter {
/**
* Creates a new {@link RelationalParameter}.
*
* @param parameter must not be {@literal null}.
*/
RelationalParameter(MethodParameter parameter) {
super(parameter);
}
}
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright 2018 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
*
* http://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.relational.repository.query;
import java.util.Arrays;
import java.util.List;
import org.springframework.data.repository.query.Parameters;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.repository.query.QueryMethod;
/**
* JDBC-specific {@link ParametersParameterAccessor}.
*
* @author Mark Paluch
*/
public class RelationalParametersParameterAccessor extends ParametersParameterAccessor
implements RelationalParameterAccessor {
private final List<Object> values;
/**
* Creates a new {@link RelationalParametersParameterAccessor}.
*
* @param method must not be {@literal null}.
* @param values must not be {@literal null}.
*/
public RelationalParametersParameterAccessor(QueryMethod method, Object[] values) {
super(method.getParameters(), values);
this.values = Arrays.asList(values);
}
/* (non-Javadoc)
* @see org.springframework.data.jdbc.repository.query.JdbcParameterAccessor#getValues()
*/
@Override
public Object[] getValues() {
return values.toArray();
}
/* (non-Javadoc)
* @see org.springframework.data.jdbc.repository.query.RelationalParameterAccessor#getBindableParameters()
*/
@Override
public Parameters<?, ?> getBindableParameters() {
return getParameters().getBindableParameters();
}
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright 2018 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
*
* http://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.relational.repository.query;
import lombok.Getter;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.util.Assert;
/**
* Default implementation of {@link RelationalEntityMetadata}.
*
* @author Mark Paluch
*/
public class SimpleRelationalEntityMetadata<T> implements RelationalEntityMetadata<T> {
private final Class<T> type;
private final @Getter RelationalPersistentEntity<?> tableEntity;
/**
* Creates a new {@link SimpleRelationalEntityMetadata} using the given type and {@link RelationalPersistentEntity} to
* use for table lookups.
*
* @param type must not be {@literal null}.
* @param tableEntity must not be {@literal null}.
*/
public SimpleRelationalEntityMetadata(Class<T> type, RelationalPersistentEntity<?> tableEntity) {
Assert.notNull(type, "Type must not be null!");
Assert.notNull(tableEntity, "Table entity must not be null!");
this.type = type;
this.tableEntity = tableEntity;
}
/* (non-Javadoc)
* @see org.springframework.data.repository.core.EntityMetadata#getJavaType()
*/
public Class<T> getJavaType() {
return type;
}
/* (non-Javadoc)
* @see org.springframework.data.jdbc.repository.query.RelationalEntityMetadata#getTableName()
*/
public String getTableName() {
return tableEntity.getTableName();
}
}

View File

@@ -1,7 +0,0 @@
/**
* Query support for relational database repositories.
*/
@NonNullApi
package org.springframework.data.relational.repository.query;
import org.springframework.lang.NonNullApi;

View File

@@ -1,111 +0,0 @@
/*
* Copyright 2018 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
*
* http://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.relational.repository.support;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.repository.query.RelationalEntityInformation;
import org.springframework.data.repository.core.support.PersistentEntityInformation;
import org.springframework.lang.Nullable;
/**
* {@link RelationalEntityInformation} implementation using a {@link RelationalPersistentEntity} instance to lookup the
* necessary information. Can be configured with a custom table name.
* <p>
* Entity types that do not declare an explicit Id type fall back to {@link Long} as Id type.
*
* @author Mark Paluch
*/
public class MappingRelationalEntityInformation<T, ID> extends PersistentEntityInformation<T, ID>
implements RelationalEntityInformation<T, ID> {
private final RelationalPersistentEntity<T> entityMetadata;
private final @Nullable String customTableName;
private final Class<ID> fallbackIdType;
/**
* Creates a new {@link MappingRelationalEntityInformation} for the given {@link RelationalPersistentEntity}.
*
* @param entity must not be {@literal null}.
*/
public MappingRelationalEntityInformation(RelationalPersistentEntity<T> entity) {
this(entity, null, null);
}
/**
* Creates a new {@link MappingRelationalEntityInformation} for the given {@link RelationalPersistentEntity} and
* fallback identifier type.
*
* @param entity must not be {@literal null}.
* @param fallbackIdType can be {@literal null}.
*/
public MappingRelationalEntityInformation(RelationalPersistentEntity<T> entity, @Nullable Class<ID> fallbackIdType) {
this(entity, null, fallbackIdType);
}
/**
* Creates a new {@link MappingRelationalEntityInformation} for the given {@link RelationalPersistentEntity} and
* custom table name.
*
* @param entity must not be {@literal null}.
* @param customTableName can be {@literal null}.
*/
public MappingRelationalEntityInformation(RelationalPersistentEntity<T> entity, String customTableName) {
this(entity, customTableName, null);
}
/**
* Creates a new {@link MappingRelationalEntityInformation} for the given {@link RelationalPersistentEntity},
* collection name and identifier type.
*
* @param entity must not be {@literal null}.
* @param customTableName can be {@literal null}.
* @param idType can be {@literal null}.
*/
@SuppressWarnings("unchecked")
private MappingRelationalEntityInformation(RelationalPersistentEntity<T> entity, @Nullable String customTableName,
@Nullable Class<ID> idType) {
super(entity);
this.entityMetadata = entity;
this.customTableName = customTableName;
this.fallbackIdType = idType != null ? idType : (Class<ID>) Long.class;
}
/* (non-Javadoc)
* @see org.springframework.data.relational.repository.query.RelationalEntityInformation#getTableName()
*/
public String getTableName() {
return customTableName == null ? entityMetadata.getTableName() : customTableName;
}
public String getIdAttribute() {
return entityMetadata.getRequiredIdProperty().getName();
}
/* (non-Javadoc)
* @see org.springframework.data.repository.core.support.PersistentEntityInformation#getIdType()
*/
@Override
public Class<ID> getIdType() {
if (this.entityMetadata.hasIdProperty()) {
return super.getIdType();
}
return fallbackIdType;
}
}

View File

@@ -1,7 +0,0 @@
/**
* Support infrastructure for query derivation of relational database repositories.
*/
@NonNullApi
package org.springframework.data.relational.repository.support;
import org.springframework.lang.NonNullApi;