#30 - Add custom conversion support.

We now support custom conversions via R2dbcCustomConversions.
Custom conversions introduces simple types that depend on the used dialect.
Custom conversions and simple types are held in RelationalConverter and MappingContext.

Simple types and conversions are used by DatabaseClient and repository support to properly apply registered converters and support native types such as array-columns.

Related tickets: #22, #26.
Original pull request: #31.
This commit is contained in:
Mark Paluch
2018-12-03 17:39:07 +01:00
committed by Jens Schauder
parent 06c2a3a246
commit c357e5b543
14 changed files with 334 additions and 40 deletions

View File

@@ -2,7 +2,11 @@ package org.springframework.data.r2dbc.dialect;
import static org.assertj.core.api.Assertions.*;
import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.springframework.data.mapping.model.SimpleTypeHolder;
/**
* Unit tests for {@link PostgresDialect}.
@@ -22,4 +26,21 @@ public class PostgresDialectUnitTests {
assertThat(first.getPlaceholder()).isEqualTo("$1");
assertThat(second.getPlaceholder()).isEqualTo("$2");
}
@Test // gh-30
public void shouldConsiderCollectionTypesAsSimple() {
SimpleTypeHolder holder = PostgresDialect.INSTANCE.getSimpleTypeHolder();
assertThat(holder.isSimpleType(List.class)).isTrue();
assertThat(holder.isSimpleType(Collection.class)).isTrue();
}
@Test // gh-30
public void shouldConsiderStringArrayTypeAsSimple() {
SimpleTypeHolder holder = PostgresDialect.INSTANCE.getSimpleTypeHolder();
assertThat(holder.isSimpleType(String[].class)).isTrue();
}
}

View File

@@ -2,7 +2,10 @@ package org.springframework.data.r2dbc.dialect;
import static org.assertj.core.api.Assertions.*;
import java.util.UUID;
import org.junit.Test;
import org.springframework.data.mapping.model.SimpleTypeHolder;
/**
* Unit tests for {@link SqlServerDialect}.
@@ -22,4 +25,12 @@ public class SqlServerDialectUnitTests {
assertThat(first.getPlaceholder()).isEqualTo("@P0");
assertThat(second.getPlaceholder()).isEqualTo("@P1_foobar");
}
@Test // gh-30
public void shouldConsiderUuidAsSimple() {
SimpleTypeHolder holder = SqlServerDialect.INSTANCE.getSimpleTypeHolder();
assertThat(holder.isSimpleType(UUID.class)).isTrue();
}
}

View File

@@ -8,9 +8,12 @@ import io.r2dbc.spi.Statement;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import org.springframework.data.r2dbc.dialect.PostgresDialect;
import org.springframework.data.r2dbc.function.convert.SettableValue;
/**
* Unit tests for {@link DefaultReactiveDataAccessStrategy}.
@@ -101,4 +104,38 @@ public class DefaultReactiveDataAccessStrategyUnitTests {
operation.bindId(statement, "bar");
assertThat(operation.toQuery()).isEqualTo("DELETE FROM table WHERE id IN ($1, $2)");
}
@Test // gh-22
public void shouldUpdateArray() {
Map<String, SettableValue> columnsToUpdate = strategy
.getColumnsToUpdate(new WithCollectionTypes(new String[] { "one", "two" }, null));
Object stringArray = columnsToUpdate.get("string_array").getValue();
assertThat(stringArray).isInstanceOf(String[].class);
assertThat((String[]) stringArray).hasSize(2).contains("one", "two");
}
@Test // gh-22
public void shouldConvertListToArray() {
Map<String, SettableValue> columnsToUpdate = strategy
.getColumnsToUpdate(new WithCollectionTypes(null, Arrays.asList("one", "two")));
Object stringArray = columnsToUpdate.get("string_collection").getValue();
assertThat(stringArray).isInstanceOf(String[].class);
assertThat((String[]) stringArray).hasSize(2).contains("one", "two");
}
static class WithCollectionTypes {
String[] stringArray;
List<String> stringCollection;
WithCollectionTypes(String[] stringArray, List<String> stringCollection) {
this.stringArray = stringArray;
this.stringCollection = stringCollection;
}
}
}

View File

@@ -7,6 +7,8 @@ import io.r2dbc.spi.Row;
import io.r2dbc.spi.RowMetadata;
import lombok.RequiredArgsConstructor;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@@ -57,6 +59,17 @@ public class EntityRowMapperUnitTests {
assertThat(result.id).isEqualTo(36L);
}
@Test // gh-30
public void shouldConvertArrayToCollection() {
EntityRowMapper<EntityWithCollection> mapper = getRowMapper(EntityWithCollection.class);
when(rowMock.get("ids")).thenReturn((new String[] { "foo", "bar" }));
EntityWithCollection result = mapper.apply(rowMock, metadata);
assertThat(result.ids).contains("foo", "bar");
}
@SuppressWarnings("unchecked")
private <T> EntityRowMapper<T> getRowMapper(Class<T> type) {
RelationalPersistentEntity<T> entity = (RelationalPersistentEntity<T>) strategy.getMappingContext()
.getRequiredPersistentEntity(type);
@@ -76,4 +89,8 @@ public class EntityRowMapperUnitTests {
static class ConversionWithConstructorCreation {
final long id;
}
static class EntityWithCollection {
List<String> ids;
}
}