diff --git a/src/main/java/org/springframework/data/r2dbc/config/AbstractR2dbcConfiguration.java b/src/main/java/org/springframework/data/r2dbc/config/AbstractR2dbcConfiguration.java index 8e1ea70..55ccbe1 100644 --- a/src/main/java/org/springframework/data/r2dbc/config/AbstractR2dbcConfiguration.java +++ b/src/main/java/org/springframework/data/r2dbc/config/AbstractR2dbcConfiguration.java @@ -17,7 +17,9 @@ package org.springframework.data.r2dbc.config; import io.r2dbc.spi.ConnectionFactory; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Optional; import org.springframework.beans.BeansException; @@ -174,7 +176,11 @@ public abstract class AbstractR2dbcConfiguration implements ApplicationContextAw protected StoreConversions getStoreConversions() { R2dbcDialect dialect = getDialect(lookupConnectionFactory()); - return StoreConversions.of(dialect.getSimpleTypeHolder(), dialect.getConverters(), R2dbcCustomConversions.STORE_CONVERTERS); + + List converters = new ArrayList<>(dialect.getConverters()); + converters.addAll(R2dbcCustomConversions.STORE_CONVERTERS); + + return StoreConversions.of(dialect.getSimpleTypeHolder(), converters); } /** diff --git a/src/main/java/org/springframework/data/r2dbc/core/DefaultReactiveDataAccessStrategy.java b/src/main/java/org/springframework/data/r2dbc/core/DefaultReactiveDataAccessStrategy.java index e36698e..ecf3303 100644 --- a/src/main/java/org/springframework/data/r2dbc/core/DefaultReactiveDataAccessStrategy.java +++ b/src/main/java/org/springframework/data/r2dbc/core/DefaultReactiveDataAccessStrategy.java @@ -82,13 +82,23 @@ public class DefaultReactiveDataAccessStrategy implements ReactiveDataAccessStra this(dialect, createConverter(dialect, converters)); } + /** + * Creates a new {@link R2dbcConverter} given {@link R2dbcDialect} and custom {@code converters}. + * + * @param dialect must not be {@literal null}. + * @param converters must not be {@literal null}. + * @return the {@link R2dbcConverter}. + */ public static R2dbcConverter createConverter(R2dbcDialect dialect, Collection converters) { Assert.notNull(dialect, "Dialect must not be null"); Assert.notNull(converters, "Converters must not be null"); + List storeConverters = new ArrayList<>(dialect.getConverters()); + storeConverters.addAll(R2dbcCustomConversions.STORE_CONVERTERS); + R2dbcCustomConversions customConversions = new R2dbcCustomConversions( - StoreConversions.of(dialect.getSimpleTypeHolder(), R2dbcCustomConversions.STORE_CONVERTERS), converters); + StoreConversions.of(dialect.getSimpleTypeHolder(), storeConverters), storeConverters); RelationalMappingContext context = new RelationalMappingContext(); context.setSimpleTypeHolder(customConversions.getSimpleTypeHolder()); diff --git a/src/main/java/org/springframework/data/r2dbc/dialect/MySqlDialect.java b/src/main/java/org/springframework/data/r2dbc/dialect/MySqlDialect.java index 3259e9e..4768525 100644 --- a/src/main/java/org/springframework/data/r2dbc/dialect/MySqlDialect.java +++ b/src/main/java/org/springframework/data/r2dbc/dialect/MySqlDialect.java @@ -18,7 +18,6 @@ package org.springframework.data.r2dbc.dialect; import java.net.InetAddress; import java.net.URI; import java.net.URL; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -26,6 +25,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.UUID; + import org.springframework.core.convert.converter.Converter; /** @@ -45,19 +45,11 @@ public class MySqlDialect extends org.springframework.data.relational.core.diale public static final MySqlDialect INSTANCE = new MySqlDialect(); private static final BindMarkersFactory ANONYMOUS = BindMarkersFactory.anonymous("?"); - + /** - * MySql specific converters. + * MySQL specific converters. */ - public static final List CONVERTERS; - - static { - List converters = new ArrayList<>(); - - converters.add(ByteToBooleanConverter.INSTANCE); - - CONVERTERS = Collections.unmodifiableList(converters); - } + private static final List CONVERTERS = Collections.singletonList(ByteToBooleanConverter.INSTANCE); /* * (non-Javadoc) @@ -76,7 +68,7 @@ public class MySqlDialect extends org.springframework.data.relational.core.diale public Collection> getSimpleTypes() { return SIMPLE_TYPES; } - + /* * (non-Javadoc) * @see org.springframework.data.r2dbc.dialect.R2dbcDialect#getConverters() @@ -85,11 +77,10 @@ public class MySqlDialect extends org.springframework.data.relational.core.diale public Collection getConverters() { return CONVERTERS; } - + /** - * Simple singleton to convert {@link Byte}s to their {@link Boolean} - * representation. MySQL does not have a built in boolean type by default, - * so relies on using a byte instead. Non-zero values represent true. + * Simple singleton to convert {@link Byte}s to their {@link Boolean} representation. MySQL does not have a built-in + * boolean type by default, so relies on using a byte instead. Non-zero values represent {@literal true}. * * @author Michael Berry */ @@ -99,9 +90,11 @@ public class MySqlDialect extends org.springframework.data.relational.core.diale @Override public Boolean convert(Byte s) { + if (s == null) { return null; } + return s != 0; } } diff --git a/src/main/java/org/springframework/data/r2dbc/dialect/R2dbcDialect.java b/src/main/java/org/springframework/data/r2dbc/dialect/R2dbcDialect.java index b1b420d..9a28b6c 100644 --- a/src/main/java/org/springframework/data/r2dbc/dialect/R2dbcDialect.java +++ b/src/main/java/org/springframework/data/r2dbc/dialect/R2dbcDialect.java @@ -14,6 +14,7 @@ import org.springframework.data.relational.core.dialect.Dialect; * * @author Mark Paluch * @author Jens Schauder + * @author Michael Berry */ public interface R2dbcDialect extends Dialect { @@ -51,7 +52,7 @@ public interface R2dbcDialect extends Dialect { /** * Return a collection of converters for this dialect. - * + * * @return a collection of converters for this dialect. */ default Collection getConverters() { diff --git a/src/test/java/org/springframework/data/r2dbc/core/MySqlDatabaseClientIntegrationTests.java b/src/test/java/org/springframework/data/r2dbc/core/MySqlDatabaseClientIntegrationTests.java index 415ad36..a6eb8ec 100644 --- a/src/test/java/org/springframework/data/r2dbc/core/MySqlDatabaseClientIntegrationTests.java +++ b/src/test/java/org/springframework/data/r2dbc/core/MySqlDatabaseClientIntegrationTests.java @@ -15,14 +15,22 @@ */ package org.springframework.data.r2dbc.core; +import static org.assertj.core.api.Assertions.*; + import io.r2dbc.spi.ConnectionFactory; +import lombok.Data; +import reactor.test.StepVerifier; import javax.sql.DataSource; import org.junit.ClassRule; +import org.junit.Test; +import org.springframework.dao.DataAccessException; import org.springframework.data.r2dbc.testing.ExternalDatabase; import org.springframework.data.r2dbc.testing.MySqlTestSupport; +import org.springframework.data.relational.core.mapping.Table; +import org.springframework.jdbc.core.JdbcTemplate; /** * Integration tests for {@link DatabaseClient} against MySQL. @@ -47,4 +55,42 @@ public class MySqlDatabaseClientIntegrationTests extends AbstractDatabaseClientI protected String getCreateTableStatement() { return MySqlTestSupport.CREATE_TABLE_LEGOSET; } + + @Test // gh-166 + public void considersBuiltInConverters() { + + ConnectionFactory connectionFactory = createConnectionFactory(); + JdbcTemplate jdbc = createJdbcTemplate(createDataSource()); + + try { + jdbc.execute("DROP TABLE boolean_mapping"); + } catch (DataAccessException e) {} + jdbc.execute("CREATE TABLE boolean_mapping (id int, flag1 TINYINT, flag2 TINYINT)"); + + BooleanMapping mapping = new BooleanMapping(); + mapping.setId(42); + mapping.setFlag1(true); + + DatabaseClient databaseClient = DatabaseClient.create(connectionFactory); + + databaseClient.insert().into(BooleanMapping.class).using(mapping).then() // + .as(StepVerifier::create) // + .verifyComplete(); + + databaseClient.select().from(BooleanMapping.class).fetch().first() // + .as(StepVerifier::create) // + .consumeNextWith(actual -> assertThat(actual.isFlag1()).isTrue()) // + .verifyComplete(); + } + + @Table("boolean_mapping") + @Data + static class BooleanMapping { + + int id; + boolean flag1; + boolean flag2; + + } + }