#16 - Add abstract configuration class for R2DBC.
We now provide an abstract R2DBC configuration that registers beans required for R2DBC's DatabaseClient. Original pull request: #17.
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
package org.springframework.data.r2dbc.repository.config;
|
||||
|
||||
import io.r2dbc.spi.ConnectionFactory;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.r2dbc.function.DatabaseClient;
|
||||
import org.springframework.data.r2dbc.function.DefaultReactiveDataAccessStrategy;
|
||||
import org.springframework.data.r2dbc.function.ReactiveDataAccessStrategy;
|
||||
import org.springframework.data.r2dbc.support.R2dbcExceptionTranslator;
|
||||
import org.springframework.data.r2dbc.support.SqlErrorCodeR2dbcExceptionTranslator;
|
||||
import org.springframework.data.relational.core.conversion.BasicRelationalConverter;
|
||||
import org.springframework.data.relational.core.mapping.NamingStrategy;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
|
||||
/**
|
||||
* Base class for Spring Data R2DBC configuration containing bean declarations that must be registered for Spring Data
|
||||
* R2DBC to work.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see ConnectionFactory
|
||||
* @see DatabaseClient
|
||||
* @see EnableR2dbcRepositories
|
||||
*/
|
||||
@Configuration
|
||||
public abstract class AbstractR2dbcConfiguration {
|
||||
|
||||
/**
|
||||
* Return a R2DBC {@link ConnectionFactory}. Annotate with {@link Bean} in case you want to expose a
|
||||
* {@link ConnectionFactory} instance to the {@link org.springframework.context.ApplicationContext}.
|
||||
*
|
||||
* @return the configured {@link ConnectionFactory}.
|
||||
*/
|
||||
public abstract ConnectionFactory connectionFactory();
|
||||
|
||||
/**
|
||||
* Register a {@link DatabaseClient} using {@link #connectionFactory()} and {@link RelationalMappingContext}.
|
||||
*
|
||||
* @return must not be {@literal null}.
|
||||
*/
|
||||
@Bean
|
||||
public DatabaseClient databaseClient(ReactiveDataAccessStrategy dataAccessStrategy,
|
||||
R2dbcExceptionTranslator exceptionTranslator) {
|
||||
|
||||
return DatabaseClient.builder().connectionFactory(connectionFactory()).dataAccessStrategy(dataAccessStrategy)
|
||||
.exceptionTranslator(exceptionTranslator).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link RelationalMappingContext} and apply an optional {@link NamingStrategy}.
|
||||
*
|
||||
* @param namingStrategy optional {@link NamingStrategy}. Use {@link NamingStrategy#INSTANCE} as fallback.
|
||||
* @return must not be {@literal null}.
|
||||
*/
|
||||
@Bean
|
||||
public RelationalMappingContext r2dbcMappingContext(Optional<NamingStrategy> namingStrategy) {
|
||||
return new RelationalMappingContext(namingStrategy.orElse(NamingStrategy.INSTANCE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ReactiveDataAccessStrategy} using the configured {@link #r2dbcMappingContext(Optional)}.
|
||||
*
|
||||
* @param mappingContext the configured {@link RelationalMappingContext}.
|
||||
* @return must not be {@literal null}.
|
||||
* @see #r2dbcMappingContext(Optional)
|
||||
*/
|
||||
@Bean
|
||||
public ReactiveDataAccessStrategy reactiveDataAccessStrategy(RelationalMappingContext mappingContext) {
|
||||
return new DefaultReactiveDataAccessStrategy(new BasicRelationalConverter(mappingContext));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link R2dbcExceptionTranslator} using the configured {@link #connectionFactory()}.
|
||||
*
|
||||
* @return must not be {@literal null}.
|
||||
* @see #connectionFactory()
|
||||
*/
|
||||
@Bean
|
||||
public R2dbcExceptionTranslator exceptionTranslator() {
|
||||
return new SqlErrorCodeR2dbcExceptionTranslator(connectionFactory());
|
||||
}
|
||||
}
|
||||
@@ -32,10 +32,16 @@ import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.r2dbc.function.DatabaseClient;
|
||||
import org.springframework.data.r2dbc.function.DefaultReactiveDataAccessStrategy;
|
||||
import org.springframework.data.r2dbc.function.TransactionalDatabaseClient;
|
||||
import org.springframework.data.r2dbc.repository.config.AbstractR2dbcConfiguration;
|
||||
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
|
||||
import org.springframework.data.r2dbc.repository.query.Query;
|
||||
import org.springframework.data.r2dbc.repository.support.R2dbcRepositoryFactory;
|
||||
import org.springframework.data.r2dbc.testing.R2dbcIntegrationTestSupport;
|
||||
@@ -44,31 +50,39 @@ import org.springframework.data.relational.core.mapping.RelationalMappingContext
|
||||
import org.springframework.data.relational.core.mapping.Table;
|
||||
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link LegoSetRepository} using {@link R2dbcRepositoryFactory}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration
|
||||
public class R2dbcRepositoryIntegrationTests extends R2dbcIntegrationTestSupport {
|
||||
|
||||
private static RelationalMappingContext mappingContext = new RelationalMappingContext();
|
||||
|
||||
private ConnectionFactory connectionFactory;
|
||||
private DatabaseClient databaseClient;
|
||||
private LegoSetRepository repository;
|
||||
@Autowired private LegoSetRepository repository;
|
||||
private JdbcTemplate jdbc;
|
||||
|
||||
@Configuration
|
||||
@EnableR2dbcRepositories(considerNestedRepositories = true,
|
||||
includeFilters = @Filter(classes = LegoSetRepository.class, type = FilterType.ASSIGNABLE_TYPE))
|
||||
static class IntegrationTestConfiguration extends AbstractR2dbcConfiguration {
|
||||
|
||||
@Override
|
||||
public ConnectionFactory connectionFactory() {
|
||||
return createConnectionFactory();
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
|
||||
Hooks.onOperatorDebug();
|
||||
|
||||
this.connectionFactory = createConnectionFactory();
|
||||
this.databaseClient = DatabaseClient.builder().connectionFactory(connectionFactory)
|
||||
.dataAccessStrategy(new DefaultReactiveDataAccessStrategy(new BasicRelationalConverter(mappingContext)))
|
||||
.build();
|
||||
|
||||
this.jdbc = createJdbcTemplate(createDataSource());
|
||||
|
||||
String tableToCreate = "CREATE TABLE IF NOT EXISTS repo_legoset (\n" + " id SERIAL PRIMARY KEY,\n"
|
||||
@@ -76,8 +90,6 @@ public class R2dbcRepositoryIntegrationTests extends R2dbcIntegrationTestSupport
|
||||
|
||||
this.jdbc.execute("DROP TABLE IF EXISTS repo_legoset");
|
||||
this.jdbc.execute(tableToCreate);
|
||||
|
||||
this.repository = new R2dbcRepositoryFactory(databaseClient, mappingContext).getRepository(LegoSetRepository.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -136,7 +148,8 @@ public class R2dbcRepositoryIntegrationTests extends R2dbcIntegrationTestSupport
|
||||
@Test
|
||||
public void shouldInsertItemsTransactional() {
|
||||
|
||||
TransactionalDatabaseClient client = TransactionalDatabaseClient.builder().connectionFactory(connectionFactory)
|
||||
TransactionalDatabaseClient client = TransactionalDatabaseClient.builder()
|
||||
.connectionFactory(createConnectionFactory())
|
||||
.dataAccessStrategy(new DefaultReactiveDataAccessStrategy(new BasicRelationalConverter(mappingContext)))
|
||||
.build();
|
||||
|
||||
|
||||
@@ -17,20 +17,28 @@ package org.springframework.data.r2dbc.repository.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import io.r2dbc.spi.ConnectionFactory;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Hooks;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.r2dbc.function.DatabaseClient;
|
||||
import org.springframework.data.r2dbc.function.DefaultReactiveDataAccessStrategy;
|
||||
import org.springframework.data.r2dbc.function.convert.MappingR2dbcConverter;
|
||||
import org.springframework.data.r2dbc.repository.config.AbstractR2dbcConfiguration;
|
||||
import org.springframework.data.r2dbc.testing.R2dbcIntegrationTestSupport;
|
||||
import org.springframework.data.relational.core.conversion.BasicRelationalConverter;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
@@ -39,35 +47,39 @@ import org.springframework.data.relational.core.mapping.Table;
|
||||
import org.springframework.data.relational.repository.query.RelationalEntityInformation;
|
||||
import org.springframework.data.relational.repository.support.MappingRelationalEntityInformation;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Hooks;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link SimpleR2dbcRepository}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration
|
||||
public class SimpleR2dbcRepositoryIntegrationTests extends R2dbcIntegrationTestSupport {
|
||||
|
||||
private static RelationalMappingContext mappingContext = new RelationalMappingContext();
|
||||
@Autowired private DatabaseClient databaseClient;
|
||||
|
||||
@Autowired private RelationalMappingContext mappingContext;
|
||||
|
||||
private ConnectionFactory connectionFactory;
|
||||
private DatabaseClient databaseClient;
|
||||
private SimpleR2dbcRepository<LegoSet, Integer> repository;
|
||||
private JdbcTemplate jdbc;
|
||||
|
||||
@Configuration
|
||||
static class IntegrationTestConfiguration extends AbstractR2dbcConfiguration {
|
||||
|
||||
@Override
|
||||
public ConnectionFactory connectionFactory() {
|
||||
return createConnectionFactory();
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
|
||||
Hooks.onOperatorDebug();
|
||||
|
||||
this.connectionFactory = createConnectionFactory();
|
||||
this.databaseClient = DatabaseClient.builder().connectionFactory(connectionFactory)
|
||||
.dataAccessStrategy(new DefaultReactiveDataAccessStrategy(new BasicRelationalConverter(mappingContext)))
|
||||
.build();
|
||||
|
||||
RelationalEntityInformation<LegoSet, Integer> entityInformation = new MappingRelationalEntityInformation<>(
|
||||
(RelationalPersistentEntity<LegoSet>) mappingContext.getRequiredPersistentEntity(LegoSet.class));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user