From d5aea5203c5a97eebbbd096496d1d54bf7e5463a Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 10 Nov 2021 14:34:30 +0100 Subject: [PATCH] =?UTF-8?q?Move=20off=20RowMetadata.getColumnNames(?= =?UTF-8?q?=E2=80=A6)=20in=20preparation=20for=20R2DBC=200.9.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #683 --- .../r2dbc/convert/MappingR2dbcConverter.java | 34 +++++++++----- .../data/r2dbc/convert/RowMetadataUtils.java | 46 +++++++++++++++++++ .../r2dbc/convert/RowPropertyAccessor.java | 2 +- .../convert/EntityRowMapperUnitTests.java | 22 ++++----- ...ReactiveDataAccessStrategyTestSupport.java | 9 ++-- 5 files changed, 85 insertions(+), 28 deletions(-) create mode 100644 src/main/java/org/springframework/data/r2dbc/convert/RowMetadataUtils.java 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 5e55a849b..6bce82d75 100644 --- a/src/main/java/org/springframework/data/r2dbc/convert/MappingR2dbcConverter.java +++ b/src/main/java/org/springframework/data/r2dbc/convert/MappingR2dbcConverter.java @@ -15,12 +15,14 @@ */ package org.springframework.data.r2dbc.convert; +import io.r2dbc.spi.ColumnMetadata; import io.r2dbc.spi.Row; import io.r2dbc.spi.RowMetadata; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Optional; import java.util.function.BiFunction; @@ -163,7 +165,7 @@ public class MappingR2dbcConverter extends BasicRelationalConverter implements R try { Object value = null; - if (metadata == null || metadata.getColumnNames().contains(identifier)) { + if (metadata == null || RowMetadataUtils.containsColumn(metadata, identifier)) { value = row.get(identifier); } @@ -187,6 +189,7 @@ public class MappingR2dbcConverter extends BasicRelationalConverter implements R } } + public Object readValue(@Nullable Object value, TypeInformation type) { if (null == value) { @@ -624,17 +627,8 @@ public class MappingR2dbcConverter extends BasicRelationalConverter implements R private boolean potentiallySetId(Row row, RowMetadata metadata, PersistentPropertyAccessor propertyAccessor, RelationalPersistentProperty idProperty) { - Collection columns = metadata.getColumnNames(); - Object generatedIdValue = null; String idColumnName = idProperty.getColumnName().getReference(); - - if (columns.contains(idColumnName)) { - generatedIdValue = row.get(idColumnName); - } else if (columns.size() == 1) { - - String key = columns.iterator().next(); - generatedIdValue = row.get(key); - } + Object generatedIdValue = extractGeneratedIdentifier(row, metadata, idColumnName); if (generatedIdValue == null) { return false; @@ -646,6 +640,24 @@ public class MappingR2dbcConverter extends BasicRelationalConverter implements R return true; } + @Nullable + private Object extractGeneratedIdentifier(Row row, RowMetadata metadata, String idColumnName) { + + if (RowMetadataUtils.containsColumn(metadata, idColumnName)) { + return row.get(idColumnName); + } + + Iterable columns = metadata.getColumnMetadatas(); + Iterator it = columns.iterator(); + + if (it.hasNext()) { + ColumnMetadata column = it.next(); + return row.get(column.getName()); + } + + return null; + } + private RelationalPersistentEntity getRequiredPersistentEntity(Class type) { return (RelationalPersistentEntity) getMappingContext().getRequiredPersistentEntity(type); } diff --git a/src/main/java/org/springframework/data/r2dbc/convert/RowMetadataUtils.java b/src/main/java/org/springframework/data/r2dbc/convert/RowMetadataUtils.java new file mode 100644 index 000000000..cdb4138bb --- /dev/null +++ b/src/main/java/org/springframework/data/r2dbc/convert/RowMetadataUtils.java @@ -0,0 +1,46 @@ +/* + * Copyright 2021 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.convert; + +import io.r2dbc.spi.ColumnMetadata; +import io.r2dbc.spi.RowMetadata; + +/** + * Utility methods for {@link io.r2dbc.spi.RowMetadata} + * + * @author Mark Paluch + * @since 1.3.7 + */ +class RowMetadataUtils { + + /** + * Check whether the column {@code name} is contained in {@link RowMetadata}. The check happens case-insensitive. + * + * @param metadata the metadata object to inspect. + * @param name column name. + * @return {@code true} if the metadata contains the column {@code name}. + */ + public static boolean containsColumn(RowMetadata metadata, String name) { + + for (ColumnMetadata columnMetadata : metadata.getColumnMetadatas()) { + if (name.equalsIgnoreCase(columnMetadata.getName())) { + return true; + } + } + + return false; + } +} diff --git a/src/main/java/org/springframework/data/r2dbc/convert/RowPropertyAccessor.java b/src/main/java/org/springframework/data/r2dbc/convert/RowPropertyAccessor.java index 8cd0c76f0..3f186c221 100644 --- a/src/main/java/org/springframework/data/r2dbc/convert/RowPropertyAccessor.java +++ b/src/main/java/org/springframework/data/r2dbc/convert/RowPropertyAccessor.java @@ -44,7 +44,7 @@ class RowPropertyAccessor implements PropertyAccessor { @Override public boolean canRead(EvaluationContext context, @Nullable Object target, String name) { - return rowMetadata != null && target != null && rowMetadata.getColumnNames().contains(name); + return rowMetadata != null && target != null && RowMetadataUtils.containsColumn(rowMetadata, name); } @Override diff --git a/src/test/java/org/springframework/data/r2dbc/convert/EntityRowMapperUnitTests.java b/src/test/java/org/springframework/data/r2dbc/convert/EntityRowMapperUnitTests.java index 4e4890bf6..4a29155eb 100644 --- a/src/test/java/org/springframework/data/r2dbc/convert/EntityRowMapperUnitTests.java +++ b/src/test/java/org/springframework/data/r2dbc/convert/EntityRowMapperUnitTests.java @@ -5,14 +5,14 @@ import static org.mockito.Mockito.*; import io.r2dbc.spi.Row; import io.r2dbc.spi.RowMetadata; +import io.r2dbc.spi.test.MockColumnMetadata; +import io.r2dbc.spi.test.MockRowMetadata; import lombok.RequiredArgsConstructor; -import java.util.Collection; import java.util.EnumSet; import java.util.List; import java.util.Set; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; @@ -32,15 +32,15 @@ public class EntityRowMapperUnitTests { DefaultReactiveDataAccessStrategy strategy = new DefaultReactiveDataAccessStrategy(PostgresDialect.INSTANCE); Row rowMock = mock(Row.class); - RowMetadata metadata = mock(RowMetadata.class); - Collection columns = mock(Collection.class); - - @BeforeEach - public void before() { - - when(columns.contains(anyString())).thenReturn(true); - when(metadata.getColumnNames()).thenReturn(columns); - } + RowMetadata metadata = MockRowMetadata.builder() + .columnMetadata(MockColumnMetadata.builder().name("integer_set").build()) + .columnMetadata(MockColumnMetadata.builder().name("boxed_integers").build()) + .columnMetadata(MockColumnMetadata.builder().name("primitive_integers").build()) + .columnMetadata(MockColumnMetadata.builder().name("enum_array").build()) + .columnMetadata(MockColumnMetadata.builder().name("set_of_enum").build()) + .columnMetadata(MockColumnMetadata.builder().name("enum_set").build()) + .columnMetadata(MockColumnMetadata.builder().name("id").build()) + .columnMetadata(MockColumnMetadata.builder().name("ids").build()).build(); @Test // gh-22 public void shouldMapSimpleEntity() { diff --git a/src/test/java/org/springframework/data/r2dbc/core/ReactiveDataAccessStrategyTestSupport.java b/src/test/java/org/springframework/data/r2dbc/core/ReactiveDataAccessStrategyTestSupport.java index 1475b7790..849f8c95f 100644 --- a/src/test/java/org/springframework/data/r2dbc/core/ReactiveDataAccessStrategyTestSupport.java +++ b/src/test/java/org/springframework/data/r2dbc/core/ReactiveDataAccessStrategyTestSupport.java @@ -20,6 +20,8 @@ import static org.mockito.Mockito.*; import io.r2dbc.spi.Row; import io.r2dbc.spi.RowMetadata; +import io.r2dbc.spi.test.MockColumnMetadata; +import io.r2dbc.spi.test.MockRowMetadata; import lombok.Data; import java.math.BigDecimal; @@ -29,7 +31,6 @@ import java.time.LocalDateTime; import java.time.LocalTime; import java.time.OffsetDateTime; import java.time.ZonedDateTime; -import java.util.Collection; import java.util.UUID; import java.util.function.BiConsumer; import java.util.function.Function; @@ -196,10 +197,8 @@ public abstract class ReactiveDataAccessStrategyTestSupport { ReactiveDataAccessStrategy strategy = getStrategy(); Row rowMock = mock(Row.class); - RowMetadata metadataMock = mock(RowMetadata.class); - Collection columnNames = mock(Collection.class); - when(metadataMock.getColumnNames()).thenReturn(columnNames); - when(columnNames.contains(fieldname)).thenReturn(true); + RowMetadata metadataMock = MockRowMetadata.builder() + .columnMetadata(MockColumnMetadata.builder().name(fieldname).build()).build(); PrimitiveTypes toSave = new PrimitiveTypes(); setter.accept(toSave, testValue);