#447 - Deprecate ReactiveDataAccessStrategy.

ReactiveDataAccessStrategy is now deprecated in favor of using StatementMapper, UpdateMapper, and R2dbcConverter directly. The access strategy interface was introduced to allow pluggable access strategies in DatabaseClient. With moving DatabaseClient into Spring Framework, this approach is no longer required.
This commit is contained in:
Mark Paluch
2020-09-08 09:58:07 +02:00
parent 28edf271ad
commit a1081bbbb2
8 changed files with 57 additions and 17 deletions

View File

@@ -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 <<mapping.configuration, at the beginning of this chapter>> 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:

View File

@@ -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);
}
}
----

View File

@@ -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
// -------------------------------------------------------------------------

View File

@@ -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)

View File

@@ -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 {
/**

View File

@@ -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

View File

@@ -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"));
}
}

View File

@@ -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