diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index 81a2c9e6..40d7c91a 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -174,7 +174,7 @@ Other strategies can also be put in place (if there is demand). [[mapping.custom.object.construction]] === Customized Object Construction -The mapping subsystem allows the customization of the object construction by annotating a constructor with the `@PersistenceConstructor` annotation. The values to be used for the constructor parameters are resolved in the following way: +The mapping subsystem allows the customization of the object construction by annotating a constructor with the `@PersistenceConstructor` annotation.The values to be used for the constructor parameters are resolved in the following way: * If a parameter is annotated with the `@Value` annotation, the given expression is evaluated, and the result is used as the parameter value. * If the Java type has a property whose name matches the given field of the input row, then its property information is used to select the appropriate constructor parameter to which to pass the input field value. @@ -212,7 +212,8 @@ To selectively handle the conversion yourself, register one or more one or more You can use the `r2dbcCustomConversions` method in `AbstractR2dbcConfiguration` to configure converters. The examples <> show how to perform the configuration with Java. -NOTE: Custom top-level entity conversion requires asymmetric types for conversion.Inbound data is extracted from R2DBC's `Row`. +NOTE: Custom top-level entity conversion requires asymmetric types for conversion. +Inbound data is extracted from R2DBC's `Row`. Outbound data (to be used with `INSERT`/`UPDATE` statements) is represented as `OutboundRow` and later assembled to a statement. The following example of a Spring Converter implementation converts from a `Row` to a `Person` POJO: diff --git a/src/main/asciidoc/reference/r2dbc-repositories.adoc b/src/main/asciidoc/reference/r2dbc-repositories.adoc index fb9a55b5..b962036b 100644 --- a/src/main/asciidoc/reference/r2dbc-repositories.adoc +++ b/src/main/asciidoc/reference/r2dbc-repositories.adoc @@ -391,7 +391,7 @@ When working with multiple, potentially different databases, your application wi The provided `AbstractR2dbcConfiguration` support class assumes a single `ConnectionFactory` from which the `Dialect` gets derived. That being said, you need to define a few beans yourself to configure Spring Data R2DBC to work with multiple databases. -R2DBC repositories require either a `DatabaseClient` and `ReactiveDataAccessStrategy` or `R2dbcEntityOperations` to implement repositories. +R2DBC repositories require `R2dbcEntityOperations` to implement repositories. A simple configuration to scan for repositories without using `AbstractR2dbcConfiguration` looks like: [source,java] @@ -409,13 +409,9 @@ static class MySQLConfiguration { @Bean public R2dbcEntityOperations mysqlR2dbcEntityOperations(@Qualifier("mysql") ConnectionFactory connectionFactory) { - DefaultReactiveDataAccessStrategy strategy = new DefaultReactiveDataAccessStrategy(MySqlDialect.INSTANCE); - DatabaseClient databaseClient = DatabaseClient.builder() - .connectionFactory(connectionFactory) - .dataAccessStrategy(strategy) - .build(); + DatabaseClient databaseClient = DatabaseClient.create(connectionFactory); - return new R2dbcEntityTemplate(databaseClient, strategy); + return new R2dbcEntityTemplate(databaseClient, MySqlDialect.INSTANCE); } } ---- diff --git a/src/main/java/org/springframework/data/r2dbc/core/R2dbcEntityOperations.java b/src/main/java/org/springframework/data/r2dbc/core/R2dbcEntityOperations.java index f0cb4505..2a11107d 100644 --- a/src/main/java/org/springframework/data/r2dbc/core/R2dbcEntityOperations.java +++ b/src/main/java/org/springframework/data/r2dbc/core/R2dbcEntityOperations.java @@ -20,6 +20,7 @@ import reactor.core.publisher.Mono; import org.springframework.dao.DataAccessException; import org.springframework.dao.TransientDataAccessResourceException; +import org.springframework.data.r2dbc.convert.R2dbcConverter; import org.springframework.data.relational.core.query.Query; import org.springframework.data.relational.core.query.Update; import org.springframework.r2dbc.core.DatabaseClient; @@ -49,9 +50,20 @@ public interface R2dbcEntityOperations extends FluentR2dbcOperations { * @return the underlying {@link ReactiveDataAccessStrategy}. * @see ReactiveDataAccessStrategy * @since 1.1.3 + * @deprecated use {@link #getConverter()} instead as {@link ReactiveDataAccessStrategy} will be removed in a future + * release. */ + @Deprecated ReactiveDataAccessStrategy getDataAccessStrategy(); + /** + * Return the underlying {@link R2dbcConverter}. + * + * @return the underlying {@link R2dbcConverter}. + * @since 1.2 + */ + R2dbcConverter getConverter(); + // ------------------------------------------------------------------------- // Methods dealing with org.springframework.data.r2dbc.query.Query // ------------------------------------------------------------------------- diff --git a/src/main/java/org/springframework/data/r2dbc/core/R2dbcEntityTemplate.java b/src/main/java/org/springframework/data/r2dbc/core/R2dbcEntityTemplate.java index 82575cd7..14a985f2 100644 --- a/src/main/java/org/springframework/data/r2dbc/core/R2dbcEntityTemplate.java +++ b/src/main/java/org/springframework/data/r2dbc/core/R2dbcEntityTemplate.java @@ -50,6 +50,7 @@ import org.springframework.data.mapping.callback.ReactiveEntityCallbacks; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.projection.ProjectionInformation; import org.springframework.data.projection.SpelAwareProxyProjectionFactory; +import org.springframework.data.r2dbc.convert.R2dbcConverter; import org.springframework.data.r2dbc.dialect.R2dbcDialect; import org.springframework.data.r2dbc.mapping.OutboundRow; import org.springframework.data.r2dbc.mapping.event.AfterConvertCallback; @@ -122,6 +123,20 @@ public class R2dbcEntityTemplate implements R2dbcEntityOperations, BeanFactoryAw this(databaseClient, getDataAccessStrategy(databaseClient)); } + /** + * Create a new {@link R2dbcEntityTemplate} given {@link DatabaseClient}, {@link R2dbcDialect} and + * {@link R2dbcConverter}. + * + * @param databaseClient must not be {@literal null}. + * @param dialect the dialect to use, must not be {@literal null}. + * @param converter the dialect to use, must not be {@literal null}. + * @since 1.2 + */ + public R2dbcEntityTemplate(org.springframework.r2dbc.core.DatabaseClient databaseClient, R2dbcDialect dialect, + R2dbcConverter converter) { + this(databaseClient, new DefaultReactiveDataAccessStrategy(dialect, converter)); + } + /** * Create a new {@link R2dbcEntityTemplate} given {@link DatabaseClient} and {@link ReactiveDataAccessStrategy}. * @@ -170,6 +185,15 @@ public class R2dbcEntityTemplate implements R2dbcEntityOperations, BeanFactoryAw return this.dataAccessStrategy; } + /* + * (non-Javadoc) + * @see org.springframework.data.r2dbc.core.R2dbcEntityOperations#getConverter() + */ + @Override + public R2dbcConverter getConverter() { + return this.dataAccessStrategy.getConverter(); + } + /* * (non-Javadoc) * @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory) diff --git a/src/main/java/org/springframework/data/r2dbc/core/ReactiveDataAccessStrategy.java b/src/main/java/org/springframework/data/r2dbc/core/ReactiveDataAccessStrategy.java index b35cac98..c91ec6fc 100644 --- a/src/main/java/org/springframework/data/r2dbc/core/ReactiveDataAccessStrategy.java +++ b/src/main/java/org/springframework/data/r2dbc/core/ReactiveDataAccessStrategy.java @@ -37,7 +37,10 @@ import org.springframework.r2dbc.core.PreparedOperation; * * @author Mark Paluch * @see org.springframework.r2dbc.core.PreparedOperation + * @deprecated since 1.2 in favor of using direct usage of {@link StatementMapper}, + * {@link org.springframework.data.r2dbc.query.UpdateMapper} and {@link R2dbcConverter}. */ +@Deprecated public interface ReactiveDataAccessStrategy { /** diff --git a/src/main/java/org/springframework/data/r2dbc/repository/config/EnableR2dbcRepositories.java b/src/main/java/org/springframework/data/r2dbc/repository/config/EnableR2dbcRepositories.java index 50ab2937..7b327c73 100644 --- a/src/main/java/org/springframework/data/r2dbc/repository/config/EnableR2dbcRepositories.java +++ b/src/main/java/org/springframework/data/r2dbc/repository/config/EnableR2dbcRepositories.java @@ -122,8 +122,10 @@ public @interface EnableR2dbcRepositories { * * @return * @see #entityOperationsRef() + * @deprecated since 1.2, in favor of {@link #entityOperationsRef()}. */ - String databaseClientRef() default "r2dbcDatabaseClient"; + @Deprecated + String databaseClientRef() default ""; /** * Configures the name of the {@link org.springframework.data.r2dbc.core.R2dbcEntityOperations} bean to be used with @@ -134,7 +136,7 @@ public @interface EnableR2dbcRepositories { * @return * @since 1.1.3 */ - String entityOperationsRef() default ""; + String entityOperationsRef() default "r2dbcEntityTemplate"; /** * Configures whether nested repository-interfaces (e.g. defined as inner classes) should be discovered by the diff --git a/src/main/java/org/springframework/data/r2dbc/repository/config/R2dbcRepositoryConfigurationExtension.java b/src/main/java/org/springframework/data/r2dbc/repository/config/R2dbcRepositoryConfigurationExtension.java index dbd818d9..a4efda79 100644 --- a/src/main/java/org/springframework/data/r2dbc/repository/config/R2dbcRepositoryConfigurationExtension.java +++ b/src/main/java/org/springframework/data/r2dbc/repository/config/R2dbcRepositoryConfigurationExtension.java @@ -98,12 +98,12 @@ public class R2dbcRepositoryConfigurationExtension extends RepositoryConfigurati AnnotationAttributes attributes = config.getAttributes(); - String entityOperationsRef = attributes.getString("entityOperationsRef"); - if (StringUtils.hasText(entityOperationsRef)) { - builder.addPropertyReference("entityOperations", entityOperationsRef); - } else { + String databaseClientRef = attributes.getString("databaseClientRef"); + if (StringUtils.hasText(databaseClientRef)) { builder.addPropertyReference("databaseClient", attributes.getString("databaseClientRef")); builder.addPropertyReference("dataAccessStrategy", "reactiveDataAccessStrategy"); + } else { + builder.addPropertyReference("entityOperations", attributes.getString("entityOperationsRef")); } } diff --git a/src/test/java/org/springframework/data/r2dbc/repository/config/R2dbcRepositoriesRegistrarTests.java b/src/test/java/org/springframework/data/r2dbc/repository/config/R2dbcRepositoriesRegistrarTests.java index 82ef0bd4..cd22cf3c 100644 --- a/src/test/java/org/springframework/data/r2dbc/repository/config/R2dbcRepositoriesRegistrarTests.java +++ b/src/test/java/org/springframework/data/r2dbc/repository/config/R2dbcRepositoriesRegistrarTests.java @@ -50,8 +50,10 @@ public class R2dbcRepositoriesRegistrarTests { static class EnableWithDatabaseClient { @Bean - public DatabaseClient r2dbcDatabaseClient() { - return mock(DatabaseClient.class); + public R2dbcEntityTemplate r2dbcEntityTemplate() { + R2dbcEntityTemplate template = mock(R2dbcEntityTemplate.class); + when(template.getDataAccessStrategy()).thenReturn(reactiveDataAccessStrategy()); + return template; } @Bean