Commit 36fb86a1 authored by Stephane Nicoll's avatar Stephane Nicoll

Update to core r2dbc support

This commit adapts the auto-configuration for the new core r2dbc support
in Spring Framework and provides auto-configuration for
R2dbcEntityOperations.

Closes gh-22708
parent 2b995324
...@@ -20,8 +20,6 @@ import java.util.ArrayList; ...@@ -20,8 +20,6 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import io.r2dbc.spi.ConnectionFactory;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
...@@ -34,15 +32,14 @@ import org.springframework.context.annotation.Configuration; ...@@ -34,15 +32,14 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.data.convert.CustomConversions; import org.springframework.data.convert.CustomConversions;
import org.springframework.data.r2dbc.convert.MappingR2dbcConverter; import org.springframework.data.r2dbc.convert.MappingR2dbcConverter;
import org.springframework.data.r2dbc.convert.R2dbcCustomConversions; import org.springframework.data.r2dbc.convert.R2dbcCustomConversions;
import org.springframework.data.r2dbc.core.DatabaseClient;
import org.springframework.data.r2dbc.core.DefaultReactiveDataAccessStrategy; import org.springframework.data.r2dbc.core.DefaultReactiveDataAccessStrategy;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.data.r2dbc.core.ReactiveDataAccessStrategy; import org.springframework.data.r2dbc.core.ReactiveDataAccessStrategy;
import org.springframework.data.r2dbc.dialect.DialectResolver; import org.springframework.data.r2dbc.dialect.DialectResolver;
import org.springframework.data.r2dbc.dialect.R2dbcDialect; import org.springframework.data.r2dbc.dialect.R2dbcDialect;
import org.springframework.data.r2dbc.mapping.R2dbcMappingContext; import org.springframework.data.r2dbc.mapping.R2dbcMappingContext;
import org.springframework.data.r2dbc.support.R2dbcExceptionSubclassTranslator;
import org.springframework.data.r2dbc.support.R2dbcExceptionTranslator;
import org.springframework.data.relational.core.mapping.NamingStrategy; import org.springframework.data.relational.core.mapping.NamingStrategy;
import org.springframework.r2dbc.core.DatabaseClient;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for {@link DatabaseClient}. * {@link EnableAutoConfiguration Auto-configuration} for {@link DatabaseClient}.
...@@ -52,24 +49,21 @@ import org.springframework.data.relational.core.mapping.NamingStrategy; ...@@ -52,24 +49,21 @@ import org.springframework.data.relational.core.mapping.NamingStrategy;
* @since 2.3.0 * @since 2.3.0
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnClass(DatabaseClient.class) @ConditionalOnClass({ DatabaseClient.class, R2dbcEntityTemplate.class })
@ConditionalOnMissingBean(DatabaseClient.class) @ConditionalOnSingleCandidate(DatabaseClient.class)
@ConditionalOnSingleCandidate(ConnectionFactory.class)
@AutoConfigureAfter(R2dbcAutoConfiguration.class) @AutoConfigureAfter(R2dbcAutoConfiguration.class)
public class R2dbcDataAutoConfiguration { public class R2dbcDataAutoConfiguration {
private final ConnectionFactory connectionFactory; private final DatabaseClient databaseClient;
public R2dbcDataAutoConfiguration(ConnectionFactory connectionFactory) { public R2dbcDataAutoConfiguration(DatabaseClient databaseClient) {
this.connectionFactory = connectionFactory; this.databaseClient = databaseClient;
} }
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public DatabaseClient r2dbcDatabaseClient(ReactiveDataAccessStrategy dataAccessStrategy, public R2dbcEntityTemplate r2dbcEntityTemplate(ReactiveDataAccessStrategy reactiveDataAccessStrategy) {
R2dbcExceptionTranslator exceptionTranslator) { return new R2dbcEntityTemplate(this.databaseClient, reactiveDataAccessStrategy);
return DatabaseClient.builder().connectionFactory(this.connectionFactory).dataAccessStrategy(dataAccessStrategy)
.exceptionTranslator(exceptionTranslator).build();
} }
@Bean @Bean
...@@ -87,13 +81,13 @@ public class R2dbcDataAutoConfiguration { ...@@ -87,13 +81,13 @@ public class R2dbcDataAutoConfiguration {
public ReactiveDataAccessStrategy reactiveDataAccessStrategy(R2dbcMappingContext mappingContext, public ReactiveDataAccessStrategy reactiveDataAccessStrategy(R2dbcMappingContext mappingContext,
R2dbcCustomConversions r2dbcCustomConversions) { R2dbcCustomConversions r2dbcCustomConversions) {
MappingR2dbcConverter converter = new MappingR2dbcConverter(mappingContext, r2dbcCustomConversions); MappingR2dbcConverter converter = new MappingR2dbcConverter(mappingContext, r2dbcCustomConversions);
return new DefaultReactiveDataAccessStrategy(DialectResolver.getDialect(this.connectionFactory), converter); return new DefaultReactiveDataAccessStrategy(getDialect(), converter);
} }
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public R2dbcCustomConversions r2dbcCustomConversions() { public R2dbcCustomConversions r2dbcCustomConversions() {
R2dbcDialect dialect = DialectResolver.getDialect(this.connectionFactory); R2dbcDialect dialect = getDialect();
List<Object> converters = new ArrayList<>(dialect.getConverters()); List<Object> converters = new ArrayList<>(dialect.getConverters());
converters.addAll(R2dbcCustomConversions.STORE_CONVERTERS); converters.addAll(R2dbcCustomConversions.STORE_CONVERTERS);
return new R2dbcCustomConversions( return new R2dbcCustomConversions(
...@@ -101,10 +95,8 @@ public class R2dbcDataAutoConfiguration { ...@@ -101,10 +95,8 @@ public class R2dbcDataAutoConfiguration {
Collections.emptyList()); Collections.emptyList());
} }
@Bean private R2dbcDialect getDialect() {
@ConditionalOnMissingBean return DialectResolver.getDialect(this.databaseClient.getConnectionFactory());
public R2dbcExceptionTranslator r2dbcExceptionTranslator() {
return new R2dbcExceptionSubclassTranslator();
} }
} }
...@@ -26,10 +26,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean ...@@ -26,10 +26,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.data.r2dbc.core.DatabaseClient;
import org.springframework.data.r2dbc.repository.R2dbcRepository; import org.springframework.data.r2dbc.repository.R2dbcRepository;
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories; import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
import org.springframework.data.r2dbc.repository.support.R2dbcRepositoryFactoryBean; import org.springframework.data.r2dbc.repository.support.R2dbcRepositoryFactoryBean;
import org.springframework.r2dbc.core.DatabaseClient;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data R2DBC Repositories. * {@link EnableAutoConfiguration Auto-configuration} for Spring Data R2DBC Repositories.
......
/*
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.r2dbc;
import io.r2dbc.spi.ConnectionFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.r2dbc.core.DatabaseClient;
/**
* Configuration of the R2DBC infrastructure based on a {@link ConnectionFactory}.
*
* @author Stephane Nicoll
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(DatabaseClient.class)
@ConditionalOnSingleCandidate(ConnectionFactory.class)
class ConnectionFactoryDependentConfiguration {
@Bean
@ConditionalOnMissingBean
DatabaseClient r2dbcDatabaseClient(ConnectionFactory connectionFactory) {
return DatabaseClient.builder().connectionFactory(connectionFactory).build();
}
}
...@@ -37,7 +37,8 @@ import org.springframework.context.annotation.Import; ...@@ -37,7 +37,8 @@ import org.springframework.context.annotation.Import;
@ConditionalOnClass(ConnectionFactory.class) @ConditionalOnClass(ConnectionFactory.class)
@AutoConfigureBefore(DataSourceAutoConfiguration.class) @AutoConfigureBefore(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(R2dbcProperties.class) @EnableConfigurationProperties(R2dbcProperties.class)
@Import({ ConnectionFactoryConfigurations.Pool.class, ConnectionFactoryConfigurations.Generic.class }) @Import({ ConnectionFactoryConfigurations.Pool.class, ConnectionFactoryConfigurations.Generic.class,
ConnectionFactoryDependentConfiguration.class })
public class R2dbcAutoConfiguration { public class R2dbcAutoConfiguration {
} }
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.autoconfigure.data.r2dbc; package org.springframework.boot.autoconfigure.r2dbc;
import io.r2dbc.spi.ConnectionFactory; import io.r2dbc.spi.ConnectionFactory;
...@@ -28,7 +28,7 @@ import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfigu ...@@ -28,7 +28,7 @@ import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfigu
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.data.r2dbc.connectionfactory.R2dbcTransactionManager; import org.springframework.r2dbc.connection.R2dbcTransactionManager;
import org.springframework.transaction.ReactiveTransactionManager; import org.springframework.transaction.ReactiveTransactionManager;
/** /**
......
...@@ -57,7 +57,6 @@ org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfigura ...@@ -57,7 +57,6 @@ org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfigura
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
...@@ -106,6 +105,7 @@ org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration,\ ...@@ -106,6 +105,7 @@ org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\ org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\ org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\ org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\ org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\ org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\ org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
......
...@@ -21,7 +21,7 @@ import org.junit.jupiter.api.Test; ...@@ -21,7 +21,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration; import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.data.r2dbc.core.DatabaseClient; import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
...@@ -36,8 +36,8 @@ class R2dbcDataAutoConfigurationTests { ...@@ -36,8 +36,8 @@ class R2dbcDataAutoConfigurationTests {
.withConfiguration(AutoConfigurations.of(R2dbcAutoConfiguration.class, R2dbcDataAutoConfiguration.class)); .withConfiguration(AutoConfigurations.of(R2dbcAutoConfiguration.class, R2dbcDataAutoConfiguration.class));
@Test @Test
void databaseClientExists() { void r2dbcEntityTemplateIsConfigured() {
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(DatabaseClient.class)); this.contextRunner.run((context) -> assertThat(context).hasSingleBean(R2dbcEntityTemplate.class));
} }
} }
...@@ -23,19 +23,21 @@ import reactor.test.StepVerifier; ...@@ -23,19 +23,21 @@ import reactor.test.StepVerifier;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage; import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage;
import org.springframework.boot.autoconfigure.data.r2dbc.city.City; import org.springframework.boot.autoconfigure.data.r2dbc.city.City;
import org.springframework.boot.autoconfigure.data.r2dbc.city.CityRepository; import org.springframework.boot.autoconfigure.data.r2dbc.city.CityRepository;
import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration; import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.data.r2dbc.connectionfactory.init.ResourceDatabasePopulator;
import org.springframework.data.r2dbc.core.DatabaseClient;
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories; import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
import org.springframework.data.r2dbc.repository.config.R2dbcRepositoryConfigurationExtension; import org.springframework.data.r2dbc.repository.config.R2dbcRepositoryConfigurationExtension;
import org.springframework.data.repository.Repository; import org.springframework.data.repository.Repository;
import org.springframework.r2dbc.connection.init.ResourceDatabasePopulator;
import org.springframework.r2dbc.core.DatabaseClient;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
...@@ -58,6 +60,7 @@ class R2dbcRepositoriesAutoConfigurationTests { ...@@ -58,6 +60,7 @@ class R2dbcRepositoriesAutoConfigurationTests {
@Test @Test
void backsOffWithNoDatabaseClientOperations() { void backsOffWithNoDatabaseClientOperations() {
this.contextRunner.withConfiguration(AutoConfigurations.of(R2dbcAutoConfiguration.class)) this.contextRunner.withConfiguration(AutoConfigurations.of(R2dbcAutoConfiguration.class))
.withClassLoader(new FilteredClassLoader("org.springframework.r2dbc"))
.withUserConfiguration(TestConfiguration.class).run((context) -> { .withUserConfiguration(TestConfiguration.class).run((context) -> {
assertThat(context).doesNotHaveBean(DatabaseClient.class); assertThat(context).doesNotHaveBean(DatabaseClient.class);
assertThat(context).doesNotHaveBean(R2dbcRepositoryConfigurationExtension.class); assertThat(context).doesNotHaveBean(R2dbcRepositoryConfigurationExtension.class);
...@@ -105,7 +108,7 @@ class R2dbcRepositoriesAutoConfigurationTests { ...@@ -105,7 +108,7 @@ class R2dbcRepositoriesAutoConfigurationTests {
ResourceLoader resourceLoader = new DefaultResourceLoader(); ResourceLoader resourceLoader = new DefaultResourceLoader();
Resource[] scripts = new Resource[] { resourceLoader.getResource("classpath:data-city-schema.sql"), Resource[] scripts = new Resource[] { resourceLoader.getResource("classpath:data-city-schema.sql"),
resourceLoader.getResource("classpath:city.sql") }; resourceLoader.getResource("classpath:city.sql") };
new ResourceDatabasePopulator(scripts).execute(connectionFactory).block(); new ResourceDatabasePopulator(scripts).populate(connectionFactory).block();
} }
} }
...@@ -117,6 +120,7 @@ class R2dbcRepositoriesAutoConfigurationTests { ...@@ -117,6 +120,7 @@ class R2dbcRepositoriesAutoConfigurationTests {
} }
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(EmptyDataPackage.class)
static class EmptyConfiguration { static class EmptyConfiguration {
} }
......
...@@ -39,6 +39,7 @@ import org.springframework.boot.test.context.FilteredClassLoader; ...@@ -39,6 +39,7 @@ import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.r2dbc.core.DatabaseClient;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
...@@ -240,6 +241,24 @@ class R2dbcAutoConfigurationTests { ...@@ -240,6 +241,24 @@ class R2dbcAutoConfigurationTests {
.doesNotHaveBean(DataSource.class)); .doesNotHaveBean(DataSource.class));
} }
@Test
void databaseClientIsConfigured() {
this.contextRunner.withPropertyValues("spring.r2dbc.url:r2dbc:h2:mem:///" + randomDatabaseName())
.run((context) -> {
assertThat(context).hasSingleBean(ConnectionFactory.class).hasSingleBean(DatabaseClient.class);
assertThat(context.getBean(DatabaseClient.class).getConnectionFactory())
.isSameAs(context.getBean(ConnectionFactory.class));
});
}
@Test
void databaseClientBacksOffIfSpringR2dbcIsNotAvailable() {
this.contextRunner.withClassLoader(new FilteredClassLoader("org.springframework.r2dbc"))
.withPropertyValues("spring.r2dbc.url:r2dbc:h2:mem:///" + randomDatabaseName())
.run((context) -> assertThat(context).hasSingleBean(ConnectionFactory.class)
.doesNotHaveBean(DatabaseClient.class));
}
private String randomDatabaseName() { private String randomDatabaseName() {
return "testdb-" + UUID.randomUUID(); return "testdb-" + UUID.randomUUID();
} }
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.autoconfigure.data.r2dbc; package org.springframework.boot.autoconfigure.r2dbc;
import io.r2dbc.spi.Connection; import io.r2dbc.spi.Connection;
import io.r2dbc.spi.ConnectionFactory; import io.r2dbc.spi.ConnectionFactory;
...@@ -27,7 +27,6 @@ import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfigu ...@@ -27,7 +27,6 @@ import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfigu
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.r2dbc.connectionfactory.R2dbcTransactionManager;
import org.springframework.transaction.ReactiveTransactionManager; import org.springframework.transaction.ReactiveTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
...@@ -39,7 +38,7 @@ import static org.mockito.BDDMockito.given; ...@@ -39,7 +38,7 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
/** /**
* Tests for {@link R2dbcTransactionManager}. * Tests for {@link R2dbcTransactionManagerAutoConfiguration}.
* *
* @author Mark Paluch * @author Mark Paluch
* @author Oliver Drotbohm * @author Oliver Drotbohm
......
/*
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.r2dbc;
import io.r2dbc.pool.ConnectionPool;
import io.r2dbc.spi.ConnectionFactory;
import org.springframework.boot.autoconfigure.r2dbc.SimpleConnectionFactoryProvider.SimpleTestConnectionFactory;
import org.springframework.r2dbc.core.binding.BindMarkersFactory;
import org.springframework.r2dbc.core.binding.BindMarkersFactoryResolver.BindMarkerFactoryProvider;
/**
* Simple {@link BindMarkerFactoryProvider} for {@link SimpleConnectionFactoryProvider}.
*
* @author Stephane Nicoll
*/
public class SimpleBindMarkerFactoryProvider implements BindMarkerFactoryProvider {
@Override
public BindMarkersFactory getBindMarkers(ConnectionFactory connectionFactory) {
if (unwrapIfNecessary(connectionFactory) instanceof SimpleTestConnectionFactory) {
return BindMarkersFactory.anonymous("?");
}
return null;
}
private ConnectionFactory unwrapIfNecessary(ConnectionFactory connectionFactory) {
if (connectionFactory instanceof ConnectionPool) {
return ((ConnectionPool) connectionFactory).unwrap();
}
return connectionFactory;
}
}
org.springframework.r2dbc.core.binding.BindMarkersFactoryResolver$BindMarkerFactoryProvider=org.springframework.boot.autoconfigure.r2dbc.SimpleBindMarkerFactoryProvider
...@@ -1972,7 +1972,7 @@ You can tune that behavior by setting `spring.datasource.continue-on-error`. ...@@ -1972,7 +1972,7 @@ You can tune that behavior by setting `spring.datasource.continue-on-error`.
=== Initialize a Database Using R2DBC === Initialize a Database Using R2DBC
If you are using R2DBC, the regular `DataSource` auto-configuration backs off so none of the options described above can be used. If you are using R2DBC, the regular `DataSource` auto-configuration backs off so none of the options described above can be used.
If you are using Spring Data R2DBC, you can initialize the database on startup using SQL scripts as shown in the following example: You can initialize the database on startup using SQL scripts as shown in the following example:
[source,java,indent=0] [source,java,indent=0]
---- ----
......
...@@ -4215,7 +4215,7 @@ If you want to make sure that each context has a separate embedded database, you ...@@ -4215,7 +4215,7 @@ If you want to make sure that each context has a separate embedded database, you
[[boot-features-r2dbc-using-database-client]] [[boot-features-r2dbc-using-database-client]]
==== Using DatabaseClient ==== Using DatabaseClient
Spring Data's `DatabaseClient` class is auto-configured, and you can `@Autowire` it directly into your own beans, as shown in the following example: A `DatabaseClient` bean is auto-configured, and you can `@Autowire` it directly into your own beans, as shown in the following example:
[source,java,indent=0] [source,java,indent=0]
---- ----
......
...@@ -23,7 +23,7 @@ import org.springframework.context.annotation.Configuration; ...@@ -23,7 +23,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.data.r2dbc.connectionfactory.init.ResourceDatabasePopulator; import org.springframework.r2dbc.connection.init.ResourceDatabasePopulator;
/** /**
* Example configuration for initializing a database using R2DBC. * Example configuration for initializing a database using R2DBC.
...@@ -41,7 +41,7 @@ public class R2dbcDatabaseInitializationExample { ...@@ -41,7 +41,7 @@ public class R2dbcDatabaseInitializationExample {
ResourceLoader resourceLoader = new DefaultResourceLoader(); ResourceLoader resourceLoader = new DefaultResourceLoader();
Resource[] scripts = new Resource[] { resourceLoader.getResource("classpath:schema.sql"), Resource[] scripts = new Resource[] { resourceLoader.getResource("classpath:schema.sql"),
resourceLoader.getResource("classpath:data.sql") }; resourceLoader.getResource("classpath:data.sql") };
new ResourceDatabasePopulator(scripts).execute(connectionFactory).block(); new ResourceDatabasePopulator(scripts).populate(connectionFactory).block();
} }
} }
......
...@@ -52,11 +52,11 @@ org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration ...@@ -52,11 +52,11 @@ org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
# AutoConfigureDataR2dbc auto-configuration imports # AutoConfigureDataR2dbc auto-configuration imports
org.springframework.boot.test.autoconfigure.data.r2dbc.AutoConfigureDataR2dbc=\ org.springframework.boot.test.autoconfigure.data.r2dbc.AutoConfigureDataR2dbc=\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\ org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\ org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\ org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
# AutoConfigureDataRedis auto-configuration imports # AutoConfigureDataRedis auto-configuration imports
......
...@@ -26,8 +26,8 @@ import org.springframework.context.ApplicationContext; ...@@ -26,8 +26,8 @@ import org.springframework.context.ApplicationContext;
import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.data.r2dbc.connectionfactory.init.ResourceDatabasePopulator; import org.springframework.r2dbc.connection.init.ResourceDatabasePopulator;
import org.springframework.data.r2dbc.core.DatabaseClient; import org.springframework.r2dbc.core.DatabaseClient;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
...@@ -50,7 +50,7 @@ class DataR2dbcTestIntegrationTests { ...@@ -50,7 +50,7 @@ class DataR2dbcTestIntegrationTests {
@Test @Test
void testDatabaseClient() { void testDatabaseClient() {
this.databaseClient.execute("SELECT * FROM example").fetch().all().as(StepVerifier::create).verifyComplete(); this.databaseClient.sql("SELECT * FROM example").fetch().all().as(StepVerifier::create).verifyComplete();
} }
@Test @Test
...@@ -72,7 +72,7 @@ class DataR2dbcTestIntegrationTests { ...@@ -72,7 +72,7 @@ class DataR2dbcTestIntegrationTests {
ResourceLoader resourceLoader = new DefaultResourceLoader(); ResourceLoader resourceLoader = new DefaultResourceLoader();
Resource[] scripts = new Resource[] { resourceLoader Resource[] scripts = new Resource[] { resourceLoader
.getResource("classpath:org/springframework/boot/test/autoconfigure/data/r2dbc/schema.sql") }; .getResource("classpath:org/springframework/boot/test/autoconfigure/data/r2dbc/schema.sql") };
new ResourceDatabasePopulator(scripts).execute(connectionFactory).block(); new ResourceDatabasePopulator(scripts).populate(connectionFactory).block();
} }
} }
......
...@@ -24,7 +24,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; ...@@ -24,7 +24,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.data.r2dbc.connectionfactory.init.ResourceDatabasePopulator; import org.springframework.r2dbc.connection.init.ResourceDatabasePopulator;
@SpringBootApplication @SpringBootApplication
public class SampleR2dbcApplication { public class SampleR2dbcApplication {
...@@ -37,7 +37,7 @@ public class SampleR2dbcApplication { ...@@ -37,7 +37,7 @@ public class SampleR2dbcApplication {
public ApplicationRunner initializeDatabase(ConnectionFactory connectionFactory, ResourceLoader resourceLoader) { public ApplicationRunner initializeDatabase(ConnectionFactory connectionFactory, ResourceLoader resourceLoader) {
return (arguments) -> { return (arguments) -> {
Resource[] scripts = new Resource[] { resourceLoader.getResource("classpath:database-init.sql") }; Resource[] scripts = new Resource[] { resourceLoader.getResource("classpath:database-init.sql") };
new ResourceDatabasePopulator(scripts).execute(connectionFactory).block(); new ResourceDatabasePopulator(scripts).populate(connectionFactory).block();
}; };
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment