From 7c56af66329120fa2800a158ae3493f87fd14717 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 17 Oct 2018 14:43:05 +0200 Subject: [PATCH] DATAJDBC-272 - Polishing. Add missing relational.repository package that got lost during module split. --- pom.xml | 2 +- .../query/DtoInstantiatingConverter.java | 104 ++++++++++++++++ .../query/RelationalEntityInformation.java | 33 ++++++ .../query/RelationalEntityMetadata.java | 41 +++++++ .../query/RelationalParameterAccessor.java | 37 ++++++ .../query/RelationalParameters.java | 80 +++++++++++++ ...RelationalParametersParameterAccessor.java | 62 ++++++++++ .../query/SimpleRelationalEntityMetadata.java | 62 ++++++++++ .../repository/query/package-info.java | 7 ++ .../MappingRelationalEntityInformation.java | 111 ++++++++++++++++++ .../repository/support/package-info.java | 7 ++ 11 files changed, 545 insertions(+), 1 deletion(-) create mode 100755 spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/DtoInstantiatingConverter.java create mode 100755 spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalEntityInformation.java create mode 100755 spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalEntityMetadata.java create mode 100755 spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalParameterAccessor.java create mode 100755 spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalParameters.java create mode 100755 spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalParametersParameterAccessor.java create mode 100755 spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/SimpleRelationalEntityMetadata.java create mode 100755 spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/package-info.java create mode 100755 spring-data-relational/src/main/java/org/springframework/data/relational/repository/support/MappingRelationalEntityInformation.java create mode 100755 spring-data-relational/src/main/java/org/springframework/data/relational/repository/support/package-info.java diff --git a/pom.xml b/pom.xml index b987e1923..8fc0950eb 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.data spring-data-relational-parent - 1.1.0.BUILD-SNAPSHOT + 1.1.0.BUILD-SNAPSHOT pom Spring Data Relational Parent diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/DtoInstantiatingConverter.java b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/DtoInstantiatingConverter.java new file mode 100755 index 000000000..2eb0eba07 --- /dev/null +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/DtoInstantiatingConverter.java @@ -0,0 +1,104 @@ +/* + * 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 { + + private final Class targetType; + private final MappingContext, ? 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 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> 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((SimplePropertyHandler) property -> { + + if (constructor.isConstructorParameter(property)) { + return; + } + + dtoAccessor.setProperty(property, + sourceAccessor.getProperty(sourceEntity.getPersistentProperty(property.getName()))); + }); + + return dto; + } +} diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalEntityInformation.java b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalEntityInformation.java new file mode 100755 index 000000000..c03f202e9 --- /dev/null +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalEntityInformation.java @@ -0,0 +1,33 @@ +/* + * 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 extends EntityInformation { + + /** + * Returns the name of the table the entity shall be persisted to. + * + * @return + */ + String getTableName(); +} diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalEntityMetadata.java b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalEntityMetadata.java new file mode 100755 index 000000000..8691cb5a5 --- /dev/null +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalEntityMetadata.java @@ -0,0 +1,41 @@ +/* + * 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 extends EntityMetadata { + + /** + * 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(); +} diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalParameterAccessor.java b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalParameterAccessor.java new file mode 100755 index 000000000..0c5c586e4 --- /dev/null +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalParameterAccessor.java @@ -0,0 +1,37 @@ +/* + * 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.query.ParameterAccessor; +import org.springframework.data.repository.query.Parameters; + +/** + * Relational-specific {@link ParameterAccessor}. + * + * @author Mark Paluch + */ +public interface RelationalParameterAccessor extends ParameterAccessor { + + /** + * Returns the raw parameter values of the underlying query method. + */ + Object[] getValues(); + + /** + * @return the bindable parameters. + */ + Parameters getBindableParameters(); +} diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalParameters.java b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalParameters.java new file mode 100755 index 000000000..8af173e46 --- /dev/null +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalParameters.java @@ -0,0 +1,80 @@ +/* + * 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 { + + /** + * 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 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 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); + } + } +} diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalParametersParameterAccessor.java b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalParametersParameterAccessor.java new file mode 100755 index 000000000..f28a3bb83 --- /dev/null +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/RelationalParametersParameterAccessor.java @@ -0,0 +1,62 @@ +/* + * 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; + +/** + * Relational-specific {@link ParametersParameterAccessor}. + * + * @author Mark Paluch + */ +public class RelationalParametersParameterAccessor extends ParametersParameterAccessor + implements RelationalParameterAccessor { + + private final List 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.relational.repository.query.RelationalParameterAccessor#getValues() + */ + @Override + public Object[] getValues() { + return values.toArray(); + } + + /* (non-Javadoc) + * @see org.springframework.data.relational.repository.query.RelationalParameterAccessor#getBindableParameters() + */ + @Override + public Parameters getBindableParameters() { + return getParameters().getBindableParameters(); + } +} diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/SimpleRelationalEntityMetadata.java b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/SimpleRelationalEntityMetadata.java new file mode 100755 index 000000000..250ad8140 --- /dev/null +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/SimpleRelationalEntityMetadata.java @@ -0,0 +1,62 @@ +/* + * 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 implements RelationalEntityMetadata { + + private final Class 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 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 getJavaType() { + return type; + } + + /* (non-Javadoc) + * @see org.springframework.data.relational.repository.query.RelationalEntityMetadata#getTableName() + */ + public String getTableName() { + return tableEntity.getTableName(); + } +} diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/package-info.java b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/package-info.java new file mode 100755 index 000000000..ccd616a69 --- /dev/null +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/query/package-info.java @@ -0,0 +1,7 @@ +/** + * Query support for relational database repositories. + */ +@NonNullApi +package org.springframework.data.relational.repository.query; + +import org.springframework.lang.NonNullApi; diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/repository/support/MappingRelationalEntityInformation.java b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/support/MappingRelationalEntityInformation.java new file mode 100755 index 000000000..10d795c4c --- /dev/null +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/support/MappingRelationalEntityInformation.java @@ -0,0 +1,111 @@ +/* + * 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. + *

+ * Entity types that do not declare an explicit Id type fall back to {@link Long} as Id type. + * + * @author Mark Paluch + */ +public class MappingRelationalEntityInformation extends PersistentEntityInformation + implements RelationalEntityInformation { + + private final RelationalPersistentEntity entityMetadata; + private final @Nullable String customTableName; + private final Class fallbackIdType; + + /** + * Creates a new {@link MappingRelationalEntityInformation} for the given {@link RelationalPersistentEntity}. + * + * @param entity must not be {@literal null}. + */ + public MappingRelationalEntityInformation(RelationalPersistentEntity 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 entity, @Nullable Class 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 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 entity, @Nullable String customTableName, + @Nullable Class idType) { + + super(entity); + + this.entityMetadata = entity; + this.customTableName = customTableName; + this.fallbackIdType = idType != null ? idType : (Class) 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 getIdType() { + + if (this.entityMetadata.hasIdProperty()) { + return super.getIdType(); + } + + return fallbackIdType; + } +} diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/repository/support/package-info.java b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/support/package-info.java new file mode 100755 index 000000000..28aeb2514 --- /dev/null +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/repository/support/package-info.java @@ -0,0 +1,7 @@ +/** + * Support infrastructure for query derivation of relational database repositories. + */ +@NonNullApi +package org.springframework.data.relational.repository.support; + +import org.springframework.lang.NonNullApi;