From d4a06a781ca1c0336be2ca7ee83dd42a1dff2ab7 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 22 May 2019 15:50:02 +0200 Subject: [PATCH] #87 - Consistently use RowMetadata. We now apply row metadata checks also for property population. --- .../r2dbc/convert/MappingR2dbcConverter.java | 23 +++++++++++------ ...stractR2dbcRepositoryIntegrationTests.java | 25 +++++++++++++++---- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/springframework/data/r2dbc/convert/MappingR2dbcConverter.java b/src/main/java/org/springframework/data/r2dbc/convert/MappingR2dbcConverter.java index d337eba..c10bde3 100644 --- a/src/main/java/org/springframework/data/r2dbc/convert/MappingR2dbcConverter.java +++ b/src/main/java/org/springframework/data/r2dbc/convert/MappingR2dbcConverter.java @@ -22,6 +22,7 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; import java.lang.reflect.Array; +import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; @@ -117,7 +118,7 @@ public class MappingR2dbcConverter extends BasicRelationalConverter implements R private R read(RelationalPersistentEntity entity, Row row, @Nullable RowMetadata metadata) { - R result = createInstance(row, "", entity); + R result = createInstance(row, metadata, "", entity); ConvertingPropertyAccessor propertyAccessor = new ConvertingPropertyAccessor<>( entity.getPropertyAccessor(result), getConversionService()); @@ -208,7 +209,7 @@ public class MappingR2dbcConverter extends BasicRelationalConverter implements R return null; } - Object instance = createInstance(row, prefix, entity); + Object instance = createInstance(row, metadata, prefix, entity); PersistentPropertyAccessor accessor = entity.getPropertyAccessor(instance); ConvertingPropertyAccessor propertyAccessor = new ConvertingPropertyAccessor<>(accessor, getConversionService()); @@ -222,9 +223,11 @@ public class MappingR2dbcConverter extends BasicRelationalConverter implements R return (S) instance; } - private S createInstance(Row row, String prefix, RelationalPersistentEntity entity) { + private S createInstance(Row row, @Nullable RowMetadata rowMetadata, String prefix, + RelationalPersistentEntity entity) { - RowParameterValueProvider rowParameterValueProvider = new RowParameterValueProvider(row, entity, this, prefix); + RowParameterValueProvider rowParameterValueProvider = new RowParameterValueProvider(row, rowMetadata, entity, this, + prefix); return createInstance(entity, rowParameterValueProvider::getParameterValue); } @@ -393,16 +396,16 @@ public class MappingR2dbcConverter extends BasicRelationalConverter implements R private boolean potentiallySetId(Row row, RowMetadata metadata, PersistentPropertyAccessor propertyAccessor, RelationalPersistentProperty idProperty) { - Map columns = createMetadataMap(metadata); + Collection columns = metadata.getColumnNames(); Object generatedIdValue = null; - if (columns.containsKey(idProperty.getColumnName())) { + if (columns.contains(idProperty.getColumnName())) { generatedIdValue = row.get(idProperty.getColumnName()); } if (columns.size() == 1) { - String key = columns.keySet().iterator().next(); + String key = columns.iterator().next(); generatedIdValue = row.get(key); } @@ -416,7 +419,6 @@ public class MappingR2dbcConverter extends BasicRelationalConverter implements R return true; } - @SuppressWarnings("unchecked") private RelationalPersistentEntity getRequiredPersistentEntity(Class type) { return (RelationalPersistentEntity) getMappingContext().getRequiredPersistentEntity(type); } @@ -436,6 +438,7 @@ public class MappingR2dbcConverter extends BasicRelationalConverter implements R private static class RowParameterValueProvider implements ParameterValueProvider { private final @NonNull Row resultSet; + private final @Nullable RowMetadata metadata; private final @NonNull RelationalPersistentEntity entity; private final @NonNull RelationalConverter converter; private final @NonNull String prefix; @@ -453,6 +456,10 @@ public class MappingR2dbcConverter extends BasicRelationalConverter implements R try { + if (metadata != null && !metadata.getColumnNames().contains(column)) { + return null; + } + Object value = resultSet.get(column); if (value == null) { diff --git a/src/test/java/org/springframework/data/r2dbc/repository/AbstractR2dbcRepositoryIntegrationTests.java b/src/test/java/org/springframework/data/r2dbc/repository/AbstractR2dbcRepositoryIntegrationTests.java index eb06b0e..1f8cd34 100644 --- a/src/test/java/org/springframework/data/r2dbc/repository/AbstractR2dbcRepositoryIntegrationTests.java +++ b/src/test/java/org/springframework/data/r2dbc/repository/AbstractR2dbcRepositoryIntegrationTests.java @@ -19,8 +19,9 @@ import static org.assertj.core.api.Assertions.*; import io.r2dbc.spi.ConnectionFactory; import lombok.AllArgsConstructor; -import lombok.Data; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -37,6 +38,7 @@ import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.r2dbc.convert.MappingR2dbcConverter; import org.springframework.data.r2dbc.core.DefaultReactiveDataAccessStrategy; import org.springframework.data.r2dbc.core.TransactionalDatabaseClient; @@ -210,14 +212,27 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg Flux findAllIds(); } - @Data + @Getter + @Setter @Table("legoset") - @AllArgsConstructor @NoArgsConstructor - static class LegoSet { - @Id Integer id; + static class LegoSet extends Lego { String name; Integer manual; + + @PersistenceConstructor + public LegoSet(Integer id, String name, Integer manual) { + super(id); + this.name = name; + this.manual = manual; + } + } + + @AllArgsConstructor + @NoArgsConstructor + @Getter + static class Lego { + @Id Integer id; } interface Named {