@@ -30,6 +30,7 @@
|
||||
<r2dbc-h2.version>1.0.0.RELEASE</r2dbc-h2.version>
|
||||
<r2dbc-mariadb.version>1.1.3</r2dbc-mariadb.version>
|
||||
<r2dbc-mssql.version>1.0.0.RELEASE</r2dbc-mssql.version>
|
||||
<r2dbc-mysql.version>1.0.0</r2dbc-mysql.version>
|
||||
<oracle-r2dbc.version>1.0.0</oracle-r2dbc.version>
|
||||
<r2dbc-spi.version>1.0.0.RELEASE</r2dbc-spi.version>
|
||||
<reactive-streams.version>1.0.4</reactive-streams.version>
|
||||
@@ -204,6 +205,13 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>${mysql-connector-java.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.oracle.database.jdbc</groupId>
|
||||
<artifactId>ojdbc11</artifactId>
|
||||
@@ -241,6 +249,13 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.asyncer</groupId>
|
||||
<artifactId>r2dbc-mysql</artifactId>
|
||||
<version>${r2dbc-mysql.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.oracle.database.r2dbc</groupId>
|
||||
<artifactId>oracle-r2dbc</artifactId>
|
||||
|
||||
@@ -2,6 +2,8 @@ package org.springframework.data.r2dbc.dialect;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import io.asyncer.r2dbc.mysql.MySqlConnectionConfiguration;
|
||||
import io.asyncer.r2dbc.mysql.MySqlConnectionFactory;
|
||||
import io.r2dbc.h2.H2ConnectionConfiguration;
|
||||
import io.r2dbc.h2.H2ConnectionFactory;
|
||||
import io.r2dbc.postgresql.PostgresqlConnectionConfiguration;
|
||||
@@ -30,7 +32,7 @@ import org.springframework.r2dbc.core.binding.BindMarkersFactory;
|
||||
*/
|
||||
public class DialectResolverUnitTests {
|
||||
|
||||
@Test // gh-20, gh-104
|
||||
@Test // GH-20, GH-104, GH-1475
|
||||
void shouldResolveDatabaseType() {
|
||||
|
||||
PostgresqlConnectionFactory postgres = new PostgresqlConnectionFactory(PostgresqlConnectionConfiguration.builder()
|
||||
@@ -38,10 +40,13 @@ public class DialectResolverUnitTests {
|
||||
H2ConnectionFactory h2 = new H2ConnectionFactory(H2ConnectionConfiguration.builder().inMemory("mem").build());
|
||||
MariadbConnectionFactory mariadb = new MariadbConnectionFactory(
|
||||
MariadbConnectionConfiguration.builder().socket("/foo").username("bar").build());
|
||||
MySqlConnectionFactory mysql = MySqlConnectionFactory
|
||||
.from(MySqlConnectionConfiguration.builder().host("foo").username("bar").build());
|
||||
|
||||
assertThat(DialectResolver.getDialect(postgres)).isEqualTo(PostgresDialect.INSTANCE);
|
||||
assertThat(DialectResolver.getDialect(h2)).isEqualTo(H2Dialect.INSTANCE);
|
||||
assertThat(DialectResolver.getDialect(mariadb)).isEqualTo(MySqlDialect.INSTANCE);
|
||||
assertThat(DialectResolver.getDialect(mysql)).isEqualTo(MySqlDialect.INSTANCE);
|
||||
}
|
||||
|
||||
@Test // gh-20, gh-104
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2019-2023 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.data.r2dbc.repository;
|
||||
|
||||
import io.r2dbc.spi.ConnectionFactory;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration;
|
||||
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
|
||||
import org.springframework.data.r2dbc.repository.support.R2dbcRepositoryFactory;
|
||||
import org.springframework.data.r2dbc.testing.ExternalDatabase;
|
||||
import org.springframework.data.r2dbc.testing.MySqlDbTestSupport;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link LegoSetRepository} using {@link R2dbcRepositoryFactory} against MySQL.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration
|
||||
public class MySqlR2dbcRepositoryIntegrationTests extends AbstractR2dbcRepositoryIntegrationTests {
|
||||
|
||||
@RegisterExtension public static final ExternalDatabase database = MySqlDbTestSupport.database();
|
||||
|
||||
@Configuration
|
||||
@EnableR2dbcRepositories(considerNestedRepositories = true,
|
||||
includeFilters = @Filter(classes = MySqlLegoSetRepository.class, type = FilterType.ASSIGNABLE_TYPE))
|
||||
static class IntegrationTestConfiguration extends AbstractR2dbcConfiguration {
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public ConnectionFactory connectionFactory() {
|
||||
return MySqlDbTestSupport.createConnectionFactory(database);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataSource createDataSource() {
|
||||
return MySqlDbTestSupport.createDataSource(database);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConnectionFactory createConnectionFactory() {
|
||||
return MySqlDbTestSupport.createConnectionFactory(database);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCreateTableStatement() {
|
||||
return MySqlDbTestSupport.CREATE_TABLE_LEGOSET_WITH_ID_GENERATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<? extends LegoSetRepository> getRepositoryInterfaceType() {
|
||||
return MySqlLegoSetRepository.class;
|
||||
}
|
||||
|
||||
interface MySqlLegoSetRepository extends LegoSetRepository {
|
||||
|
||||
@Override
|
||||
@Query("SELECT name FROM legoset")
|
||||
Flux<Named> findAsProjection();
|
||||
|
||||
@Override
|
||||
@Query("SELECT * FROM legoset WHERE manual = :manual")
|
||||
Mono<LegoSet> findByManual(int manual);
|
||||
|
||||
@Override
|
||||
@Query("SELECT id FROM legoset")
|
||||
Flux<Integer> findAllIds();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright 2019-2023 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.data.r2dbc.testing;
|
||||
|
||||
import io.asyncer.r2dbc.mysql.MySqlConnectionFactoryProvider;
|
||||
import io.r2dbc.spi.ConnectionFactory;
|
||||
import io.r2dbc.spi.ConnectionFactoryOptions;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.data.r2dbc.testing.ExternalDatabase.ProvidedDatabase;
|
||||
import org.testcontainers.containers.MySQLContainer;
|
||||
|
||||
import com.mysql.cj.jdbc.MysqlDataSource;
|
||||
|
||||
/**
|
||||
* Utility class for testing against MySQL.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
public class MySqlDbTestSupport {
|
||||
|
||||
private static ExternalDatabase testContainerDatabase;
|
||||
|
||||
public static final String CREATE_TABLE_LEGOSET = "CREATE TABLE legoset (\n" //
|
||||
+ " id integer PRIMARY KEY,\n" //
|
||||
+ " name varchar(255) NOT NULL,\n" //
|
||||
+ " manual integer NULL\n," //
|
||||
+ " cert varbinary(255) NULL\n" //
|
||||
+ ") ENGINE=InnoDB;";
|
||||
|
||||
public static final String CREATE_TABLE_LEGOSET_WITH_ID_GENERATION = "CREATE TABLE legoset (\n" //
|
||||
+ " id integer AUTO_INCREMENT PRIMARY KEY,\n" //
|
||||
+ " name varchar(255) NOT NULL,\n" //
|
||||
+ " flag boolean NOT NULL,\n" //
|
||||
+ " manual integer NULL\n" //
|
||||
+ ") ENGINE=InnoDB;";
|
||||
|
||||
public static final String CREATE_TABLE_LEGOSET_WITH_MIXED_CASE_NAMES = "CREATE TABLE `LegoSet` (\n" //
|
||||
+ " `Id` integer AUTO_INCREMENT PRIMARY KEY,\n" //
|
||||
+ " `Name` varchar(255) NOT NULL,\n" //
|
||||
+ " `Manual` integer NULL\n" //
|
||||
+ ") ENGINE=InnoDB;";
|
||||
|
||||
public static final String DROP_TABLE_LEGOSET_WITH_MIXED_CASE_NAMES = "DROP TABLE `LegoSet`";
|
||||
|
||||
/**
|
||||
* Returns a database either hosted locally at {@code localhost:3306/mysql} or running inside Docker.
|
||||
*
|
||||
* @return information about the database. Guaranteed to be not {@literal null}.
|
||||
*/
|
||||
public static ExternalDatabase database() {
|
||||
|
||||
if (Boolean.getBoolean("spring.data.r2dbc.test.preferLocalDatabase")) {
|
||||
|
||||
return getFirstWorkingDatabase( //
|
||||
MySqlDbTestSupport::local, //
|
||||
MySqlDbTestSupport::testContainer //
|
||||
);
|
||||
} else {
|
||||
|
||||
return getFirstWorkingDatabase( //
|
||||
MySqlDbTestSupport::testContainer, //
|
||||
MySqlDbTestSupport::local //
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
private static ExternalDatabase getFirstWorkingDatabase(Supplier<ExternalDatabase>... suppliers) {
|
||||
|
||||
return Stream.of(suppliers).map(Supplier::get) //
|
||||
.filter(ExternalDatabase::checkValidity) //
|
||||
.findFirst() //
|
||||
.orElse(ExternalDatabase.unavailable());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a locally provided database .
|
||||
*/
|
||||
private static ExternalDatabase local() {
|
||||
|
||||
return ProvidedDatabase.builder() //
|
||||
.hostname("localhost") //
|
||||
.port(3306) //
|
||||
.database("mysql") //
|
||||
.username("root") //
|
||||
.password("my-secret-pw") //
|
||||
.jdbcUrl("jdbc:mysql://localhost:3306/mysql") //
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a database provided via Testcontainers.
|
||||
*/
|
||||
private static ExternalDatabase testContainer() {
|
||||
|
||||
if (testContainerDatabase == null) {
|
||||
|
||||
try {
|
||||
|
||||
var container = new MySQLContainer<>("mysql:8.0.32").withUsername("test").withPassword("test")
|
||||
.withConfigurationOverride("");
|
||||
|
||||
container.start();
|
||||
|
||||
testContainerDatabase = ProvidedDatabase.builder(container) //
|
||||
.username("root") //
|
||||
.database(container.getDatabaseName()) //
|
||||
.build();
|
||||
} catch (IllegalStateException ise) {
|
||||
// docker not available.
|
||||
testContainerDatabase = ExternalDatabase.unavailable();
|
||||
}
|
||||
}
|
||||
|
||||
return testContainerDatabase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new R2DBC MySQL {@link ConnectionFactory} configured from the {@link ExternalDatabase}.
|
||||
*/
|
||||
public static ConnectionFactory createConnectionFactory(ExternalDatabase database) {
|
||||
|
||||
ConnectionFactoryOptions options = ConnectionUtils.createOptions("mysql", database);
|
||||
return new MySqlConnectionFactoryProvider().create(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link DataSource} configured from the {@link ExternalDatabase}.
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static DataSource createDataSource(ExternalDatabase database) {
|
||||
|
||||
MysqlDataSource dataSource = new MysqlDataSource();
|
||||
|
||||
dataSource.setUser(database.getUsername());
|
||||
dataSource.setPassword(database.getPassword());
|
||||
dataSource.setUrl(
|
||||
String.format("jdbc:mysql://%s:%d/%s?", database.getHostname(), database.getPort(), database.getDatabase()));
|
||||
|
||||
return dataSource;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user