DATAJDBC-395 - AbstractJdbcConfiguration no longer registers a bean of type DataAccessStrategy.

This avoids having multiple beans of that type in an ApplicationContext when a custom DataAccessStrategy needs to be provided.

Original pull request: #160.
This commit is contained in:
Jens Schauder
2019-07-11 09:36:15 +02:00
committed by Oliver Drotbohm
parent 275f1a13b9
commit b7ee1bbbb0
2 changed files with 54 additions and 21 deletions

View File

@@ -17,6 +17,7 @@ package org.springframework.data.jdbc.repository.config;
import java.util.Optional;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -51,6 +52,8 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
@Configuration
public abstract class AbstractJdbcConfiguration {
private DefaultDataAccessStrategy defaultDataAccessStrategy = null;
/**
* Register a {@link RelationalMappingContext} and apply an optional {@link NamingStrategy}.
*
@@ -76,17 +79,28 @@ public abstract class AbstractJdbcConfiguration {
*/
@Bean
public JdbcConverter jdbcConverter(RelationalMappingContext mappingContext, NamedParameterJdbcOperations operations,
@Lazy RelationResolver relationResolver) {
ObjectProvider<RelationResolver> relationResolverProvider, Optional<NamingStrategy> namingStrategy,
JdbcConverter jdbcConverter) {
return new BasicJdbcConverter(mappingContext, relationResolver, jdbcCustomConversions(),
new DefaultJdbcTypeFactory(operations.getJdbcOperations()));
RelationResolver relationResolver = relationResolverProvider.getIfAvailable(() -> dataAccessStrategy( //
operations, //
jdbcConverter, //
jdbcMappingContext(namingStrategy)) //
);
return new BasicJdbcConverter( //
mappingContext, //
relationResolver, //
jdbcCustomConversions(), //
new DefaultJdbcTypeFactory(operations.getJdbcOperations()) //
);
}
/**
* Register custom {@link Converter}s in a {@link JdbcCustomConversions} object if required. These
* {@link JdbcCustomConversions} will be registered with the
* {@link #jdbcConverter(RelationalMappingContext, NamedParameterJdbcOperations, RelationResolver)}. Returns an empty
* {@link JdbcCustomConversions} instance by default.
* {@link #jdbcConverter(RelationalMappingContext, NamedParameterJdbcOperations, ObjectProvider, Optional, JdbcConverter)}.
* Returns an empty {@link JdbcCustomConversions} instance by default.
*
* @return must not be {@literal null}.
*/
@@ -106,26 +120,45 @@ public abstract class AbstractJdbcConfiguration {
*/
@Bean
public JdbcAggregateTemplate jdbcAggregateTemplate(ApplicationEventPublisher publisher,
RelationalMappingContext context, JdbcConverter converter, DataAccessStrategy dataAccessStrategy) {
RelationalMappingContext context, JdbcConverter converter,
ObjectProvider<DataAccessStrategy> dataAccessStrategyProvider, NamedParameterJdbcOperations operations,
Optional<NamingStrategy> namingStrategy, @Lazy JdbcConverter jdbcConverter) {
return new JdbcAggregateTemplate(publisher, context, converter, dataAccessStrategy);
DataAccessStrategy dataAccessStrategy = dataAccessStrategyProvider.getIfAvailable(() -> dataAccessStrategy( //
operations, //
jdbcConverter, //
jdbcMappingContext(namingStrategy)) //
);
return new JdbcAggregateTemplate( //
publisher, //
context, //
converter, //
dataAccessStrategy //
);
}
/**
* Register a {@link DataAccessStrategy} as a bean for reuse in the {@link JdbcAggregateOperations} and the
* {@link RelationalConverter}.
* Create a {@link DataAccessStrategy} for reuse in the {@link JdbcAggregateOperations} and the
* {@link RelationalConverter}. It will return the same instance if called multiple times, regardless of the arguments
* provided. Register a bean of type {@link DataAccessStrategy} if your use case requires a more specialized
* DataAccessStrategy.
*
* @param operations
* @param namingStrategy
* @param jdbcConverter
* @return
* @return Guaranteed to be not {@literal null}.
*/
@Bean
public DataAccessStrategy dataAccessStrategy(NamedParameterJdbcOperations operations,
Optional<NamingStrategy> namingStrategy, JdbcConverter jdbcConverter) {
private DataAccessStrategy dataAccessStrategy(NamedParameterJdbcOperations operations, JdbcConverter jdbcConverter,
JdbcMappingContext context) {
JdbcMappingContext context = jdbcMappingContext(namingStrategy);
return new DefaultDataAccessStrategy(new SqlGeneratorSource(context), context, jdbcConverter, operations);
if (defaultDataAccessStrategy == null) {
defaultDataAccessStrategy = new DefaultDataAccessStrategy( //
new SqlGeneratorSource(context), //
context, //
jdbcConverter, //
operations //
);
}
return defaultDataAccessStrategy;
}
}

View File

@@ -153,16 +153,16 @@ References between those should be encoded as simple `id` values, which should m
[[jdbc.entity-persistence.custom-converters]]
=== Custom converters
Custom converters can be registered, for types that are not supported by default, by inheriting your configuration from `JdbcConfiguration` and overwriting the method `jdbcCustomConversions()`.
Custom converters can be registered, for types that are not supported by default, by inheriting your configuration from `AbstractJdbcConfiguration` and overwriting the method `jdbcCustomConversions()`.
====
[source, java]
----
@Configuration
public class DataJdbcConfiguration extends JdbcConfiguration {
public class DataJdbcConfiguration extends AbstractJdbcConfiguration {
@Override
protected JdbcCustomConversions jdbcCustomConversions() {
public JdbcCustomConversions jdbcCustomConversions() {
return new JdbcCustomConversions(Collections.singletonList(TimestampTzToDateConverter.INSTANCE));