From 06c2a3a246dc96e003fd1bab8a429e45a958e254 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 3 Dec 2018 17:30:48 +0100 Subject: [PATCH] #22 - Polishing. Add author tag. Add unit test for EntityRowMapper. Original pull request: #31. --- .../function/convert/EntityRowMapper.java | 30 ++++--- .../convert/EntityRowMapperUnitTests.java | 79 +++++++++++++++++++ 2 files changed, 96 insertions(+), 13 deletions(-) create mode 100644 src/test/java/org/springframework/data/r2dbc/function/convert/EntityRowMapperUnitTests.java diff --git a/src/main/java/org/springframework/data/r2dbc/function/convert/EntityRowMapper.java b/src/main/java/org/springframework/data/r2dbc/function/convert/EntityRowMapper.java index 33cffd8f3..2f9e89c3c 100644 --- a/src/main/java/org/springframework/data/r2dbc/function/convert/EntityRowMapper.java +++ b/src/main/java/org/springframework/data/r2dbc/function/convert/EntityRowMapper.java @@ -23,7 +23,6 @@ import lombok.RequiredArgsConstructor; import java.sql.ResultSet; import java.util.function.BiFunction; -import org.springframework.core.convert.ConversionService; import org.springframework.data.mapping.MappingException; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.PersistentPropertyAccessor; @@ -39,7 +38,7 @@ import org.springframework.lang.Nullable; * Maps a {@link io.r2dbc.spi.Row} to an entity of type {@code T}, including entities referenced. * * @author Mark Paluch - * @since 1.0 + * @author Ryland Degnan */ public class EntityRowMapper implements BiFunction { @@ -52,13 +51,17 @@ public class EntityRowMapper implements BiFunction { this.converter = converter; } + /* + * (non-Javadoc) + * @see java.util.function.BiFunction#apply(java.lang.Object, java.lang.Object) + */ @Override public T apply(Row row, RowMetadata metadata) { T result = createInstance(row, "", entity); - ConvertingPropertyAccessor propertyAccessor = new ConvertingPropertyAccessor(entity.getPropertyAccessor(result), - converter.getConversionService()); + ConvertingPropertyAccessor propertyAccessor = new ConvertingPropertyAccessor<>( + entity.getPropertyAccessor(result), converter.getConversionService()); for (RelationalPersistentProperty property : entity) { @@ -93,7 +96,7 @@ public class EntityRowMapper implements BiFunction { return readEntityFrom(row, property); } - return row.get(prefix + property.getColumnName()); + return converter.readValue(row.get(prefix + property.getColumnName()), property.getTypeInformation()); } catch (Exception o_O) { throw new MappingException(String.format("Could not read property %s from result set!", property), o_O); @@ -104,7 +107,6 @@ public class EntityRowMapper implements BiFunction { String prefix = property.getName() + "_"; - @SuppressWarnings("unchecked") RelationalPersistentEntity entity = (RelationalPersistentEntity) converter.getMappingContext() .getRequiredPersistentEntity(property.getActualType()); @@ -114,8 +116,8 @@ public class EntityRowMapper implements BiFunction { S instance = createInstance(row, prefix, entity); - PersistentPropertyAccessor accessor = entity.getPropertyAccessor(instance); - ConvertingPropertyAccessor propertyAccessor = new ConvertingPropertyAccessor(accessor, + PersistentPropertyAccessor accessor = entity.getPropertyAccessor(instance); + ConvertingPropertyAccessor propertyAccessor = new ConvertingPropertyAccessor<>(accessor, converter.getConversionService()); for (RelationalPersistentProperty p : entity) { @@ -129,8 +131,7 @@ public class EntityRowMapper implements BiFunction { private S createInstance(Row row, String prefix, RelationalPersistentEntity entity) { - RowParameterValueProvider rowParameterValueProvider = new RowParameterValueProvider(row, entity, - converter.getConversionService(), prefix); + RowParameterValueProvider rowParameterValueProvider = new RowParameterValueProvider(row, entity, converter, prefix); return converter.createInstance(entity, rowParameterValueProvider::getParameterValue); } @@ -140,7 +141,7 @@ public class EntityRowMapper implements BiFunction { private final @NonNull Row resultSet; private final @NonNull RelationalPersistentEntity entity; - private final @NonNull ConversionService conversionService; + private final @NonNull RelationalConverter converter; private final @NonNull String prefix; /* @@ -151,10 +152,13 @@ public class EntityRowMapper implements BiFunction { @Nullable public T getParameterValue(Parameter parameter) { - String column = prefix + entity.getRequiredPersistentProperty(parameter.getName()).getColumnName(); + RelationalPersistentProperty property = entity.getRequiredPersistentProperty(parameter.getName()); + String column = prefix + property.getColumnName(); try { - return conversionService.convert(resultSet.get(column), parameter.getType().getType()); + + Object value = converter.readValue(resultSet.get(column), property.getTypeInformation()); + return converter.getConversionService().convert(value, parameter.getType().getType()); } catch (Exception o_O) { throw new MappingException(String.format("Couldn't read column %s from Row.", column), o_O); } diff --git a/src/test/java/org/springframework/data/r2dbc/function/convert/EntityRowMapperUnitTests.java b/src/test/java/org/springframework/data/r2dbc/function/convert/EntityRowMapperUnitTests.java new file mode 100644 index 000000000..a8ba3da36 --- /dev/null +++ b/src/test/java/org/springframework/data/r2dbc/function/convert/EntityRowMapperUnitTests.java @@ -0,0 +1,79 @@ +package org.springframework.data.r2dbc.function.convert; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import io.r2dbc.spi.Row; +import io.r2dbc.spi.RowMetadata; +import lombok.RequiredArgsConstructor; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.data.r2dbc.dialect.PostgresDialect; +import org.springframework.data.r2dbc.function.DefaultReactiveDataAccessStrategy; +import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; + +/** + * Unit tests for {@link EntityRowMapper}. + * + * @author Mark Paluch + */ +@RunWith(MockitoJUnitRunner.class) +public class EntityRowMapperUnitTests { + + DefaultReactiveDataAccessStrategy strategy = new DefaultReactiveDataAccessStrategy(PostgresDialect.INSTANCE); + + Row rowMock = mock(Row.class); + RowMetadata metadata = mock(RowMetadata.class); + + @Test // gh-22 + public void shouldMapSimpleEntity() { + + EntityRowMapper mapper = getRowMapper(SimpleEntity.class); + when(rowMock.get("id")).thenReturn("foo"); + + SimpleEntity result = mapper.apply(rowMock, metadata); + assertThat(result.id).isEqualTo("foo"); + } + + @Test // gh-22 + public void shouldMapSimpleEntityWithConstructorCreation() { + + EntityRowMapper mapper = getRowMapper(SimpleEntityConstructorCreation.class); + when(rowMock.get("id")).thenReturn("foo"); + + SimpleEntityConstructorCreation result = mapper.apply(rowMock, metadata); + assertThat(result.id).isEqualTo("foo"); + } + + @Test // gh-22 + public void shouldApplyConversionWithConstructorCreation() { + + EntityRowMapper mapper = getRowMapper(ConversionWithConstructorCreation.class); + when(rowMock.get("id")).thenReturn((byte) 0x24); + + ConversionWithConstructorCreation result = mapper.apply(rowMock, metadata); + assertThat(result.id).isEqualTo(36L); + } + + private EntityRowMapper getRowMapper(Class type) { + RelationalPersistentEntity entity = (RelationalPersistentEntity) strategy.getMappingContext() + .getRequiredPersistentEntity(type); + return new EntityRowMapper<>(entity, strategy.getRelationalConverter()); + } + + static class SimpleEntity { + String id; + } + + @RequiredArgsConstructor + static class SimpleEntityConstructorCreation { + final String id; + } + + @RequiredArgsConstructor + static class ConversionWithConstructorCreation { + final long id; + } +}