Resolve MariaDB and MySQL dialects through DB query
Spring Data JDBC has deprecated its INSTANCE constants in its MariaDB and MySQL dialects as the required configuration for the dialect varies depending on the configuration of the DB. This commit adapts to this deprecation by changing Boot's DataJdbcDatabaseDialect to resolve the underlying dialect through a DB query for its MARIA and MYSQL values. Closes gh-46062
This commit is contained in:
parent
911578e560
commit
92fe4c55f7
|
@ -19,6 +19,7 @@ plugins {
|
|||
id "org.springframework.boot.auto-configuration"
|
||||
id "org.springframework.boot.configuration-properties"
|
||||
id "org.springframework.boot.deployed"
|
||||
id "org.springframework.boot.docker-test"
|
||||
id "org.springframework.boot.optional-dependencies"
|
||||
}
|
||||
|
||||
|
@ -31,6 +32,17 @@ dependencies {
|
|||
|
||||
optional(project(":core:spring-boot-autoconfigure"))
|
||||
|
||||
dockerTestImplementation(project(":core:spring-boot-test"))
|
||||
dockerTestImplementation(project(":test-support:spring-boot-docker-test-support"))
|
||||
dockerTestImplementation(testFixtures(project(":core:spring-boot-autoconfigure")))
|
||||
dockerTestImplementation("ch.qos.logback:logback-classic")
|
||||
dockerTestImplementation("org.testcontainers:mariadb")
|
||||
dockerTestImplementation("org.testcontainers:mysql")
|
||||
|
||||
dockerTestRuntimeOnly("com.mysql:mysql-connector-j")
|
||||
dockerTestRuntimeOnly("com.zaxxer:HikariCP")
|
||||
dockerTestRuntimeOnly("org.mariadb.jdbc:mariadb-java-client")
|
||||
|
||||
testImplementation(project(":core:spring-boot-test"))
|
||||
testImplementation(project(":test-support:spring-boot-test-support"))
|
||||
testImplementation(testFixtures(project(":core:spring-boot-autoconfigure")))
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright 2012-present 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.data.jdbc.autoconfigure;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.containers.JdbcDatabaseContainer;
|
||||
import org.testcontainers.containers.MariaDBContainer;
|
||||
import org.testcontainers.containers.MySQLContainer;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
|
||||
import org.springframework.boot.data.jdbc.domain.city.City;
|
||||
import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.jdbc.autoconfigure.DataSourceTransactionManagerAutoConfiguration;
|
||||
import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcMySqlDialect;
|
||||
import org.springframework.data.relational.core.dialect.Dialect;
|
||||
import org.springframework.data.relational.core.dialect.MariaDbDialect;
|
||||
import org.springframework.util.function.ThrowingConsumer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link DataJdbcRepositoriesAutoConfiguration} when the configured dialect
|
||||
* requires resolution using a database connection.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class DataJdbcRepositoriesAutoConfigurationDialectResolutionTests {
|
||||
|
||||
@Test
|
||||
void resolvesMariaDbDialect() {
|
||||
withContainer(MariaDBContainer.class, (runner) -> {
|
||||
runner.withPropertyValues("spring.data.jdbc.dialect=maria").run((context) -> {
|
||||
Dialect dialect = context.getBean(Dialect.class);
|
||||
assertThat(dialect).isInstanceOf(MariaDbDialect.class);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolvesMySqlDialect() {
|
||||
withContainer(MySQLContainer.class, (runner) -> {
|
||||
runner.withPropertyValues("spring.data.jdbc.dialect=mysql").run((context) -> {
|
||||
Dialect dialect = context.getBean(Dialect.class);
|
||||
assertThat(dialect).isInstanceOf(JdbcMySqlDialect.class);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private <C extends JdbcDatabaseContainer<?>> void withContainer(Class<C> containerType,
|
||||
ThrowingConsumer<ApplicationContextRunner> callback) {
|
||||
C container = TestImage.container(containerType);
|
||||
try {
|
||||
container.start();
|
||||
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
|
||||
DataJdbcRepositoriesAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
|
||||
DataSourceTransactionManagerAutoConfiguration.class))
|
||||
.withUserConfiguration(TestConfiguration.class)
|
||||
.withPropertyValues("spring.datasource.url=" + container.getJdbcUrl(),
|
||||
"spring.datasource.username=" + container.getUsername(),
|
||||
"spring.datasource.password=" + container.getPassword());
|
||||
callback.accept(contextRunner);
|
||||
}
|
||||
finally {
|
||||
container.close();
|
||||
}
|
||||
}
|
||||
|
||||
@TestAutoConfigurationPackage(City.class)
|
||||
static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -16,14 +16,20 @@
|
|||
|
||||
package org.springframework.boot.data.jdbc.autoconfigure;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.data.jdbc.core.dialect.DialectResolver;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcDb2Dialect;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcH2Dialect;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcHsqlDbDialect;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcMariaDbDialect;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcMySqlDialect;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcOracleDialect;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcPostgresDialect;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcSqlServerDialect;
|
||||
import org.springframework.data.relational.core.dialect.Dialect;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* List of database dialects that can be configured in Boot for use with Spring Data JDBC.
|
||||
|
@ -49,16 +55,16 @@ public enum DataJdbcDatabaseDialect {
|
|||
HSQL(JdbcHsqlDbDialect.INSTANCE),
|
||||
|
||||
/**
|
||||
* Provides an instance of {@link JdbcMySqlDialect}.
|
||||
* Resolves an instance of {@link JdbcMariaDbDialect} by querying the database
|
||||
* configuration.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
MARIA(JdbcMySqlDialect.INSTANCE),
|
||||
MARIA(JdbcMariaDbDialect.class),
|
||||
|
||||
/**
|
||||
* Provides an instance of {@link JdbcMySqlDialect}.
|
||||
* Resolves an instance of {@link JdbcMySqlDialect} by querying the database
|
||||
* configuration.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
MYSQL(JdbcMySqlDialect.INSTANCE),
|
||||
MYSQL(JdbcMySqlDialect.class),
|
||||
|
||||
/**
|
||||
* Provides an instance of {@link JdbcOracleDialect}.
|
||||
|
@ -75,14 +81,22 @@ public enum DataJdbcDatabaseDialect {
|
|||
*/
|
||||
SQL_SERVER(JdbcSqlServerDialect.INSTANCE);
|
||||
|
||||
private final Dialect dialect;
|
||||
private final Function<JdbcOperations, Dialect> dialectResolver;
|
||||
|
||||
DataJdbcDatabaseDialect(Dialect dialect) {
|
||||
this.dialect = dialect;
|
||||
DataJdbcDatabaseDialect(Class<? extends Dialect> dialectType) {
|
||||
this.dialectResolver = (jdbc) -> {
|
||||
Dialect dialect = DialectResolver.getDialect(jdbc);
|
||||
Assert.isInstanceOf(dialectType, dialect);
|
||||
return dialect;
|
||||
};
|
||||
}
|
||||
|
||||
final Dialect getDialect() {
|
||||
return this.dialect;
|
||||
DataJdbcDatabaseDialect(Dialect dialect) {
|
||||
this.dialectResolver = (jdbc) -> dialect;
|
||||
}
|
||||
|
||||
Dialect getDialect(JdbcOperations jdbc) {
|
||||
return this.dialectResolver.apply(jdbc);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -147,7 +147,8 @@ public final class DataJdbcRepositoriesAutoConfiguration {
|
|||
@ConditionalOnMissingBean
|
||||
public Dialect jdbcDialect(NamedParameterJdbcOperations operations) {
|
||||
DataJdbcDatabaseDialect dialect = this.properties.getDialect();
|
||||
return (dialect != null) ? dialect.getDialect() : super.jdbcDialect(operations);
|
||||
return (dialect != null) ? dialect.getDialect(operations.getJdbcOperations())
|
||||
: super.jdbcDialect(operations);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,7 +38,9 @@ dependencies {
|
|||
optional("org.testcontainers:junit-jupiter")
|
||||
optional("org.testcontainers:kafka")
|
||||
optional("org.testcontainers:ldap")
|
||||
optional("org.testcontainers:mariadb")
|
||||
optional("org.testcontainers:mongodb")
|
||||
optional("org.testcontainers:mysql")
|
||||
optional("org.testcontainers:neo4j")
|
||||
optional("org.testcontainers:oracle-xe")
|
||||
optional("org.testcontainers:oracle-free")
|
||||
|
|
|
@ -30,7 +30,9 @@ import org.testcontainers.activemq.ArtemisContainer;
|
|||
import org.testcontainers.cassandra.CassandraContainer;
|
||||
import org.testcontainers.containers.Container;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.containers.MariaDBContainer;
|
||||
import org.testcontainers.containers.MongoDBContainer;
|
||||
import org.testcontainers.containers.MySQLContainer;
|
||||
import org.testcontainers.containers.Neo4jContainer;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
import org.testcontainers.containers.PulsarContainer;
|
||||
|
@ -149,7 +151,7 @@ public enum TestImage {
|
|||
/**
|
||||
* A container image suitable for testing MariaDB.
|
||||
*/
|
||||
MARIADB("mariadb", "10.10"),
|
||||
MARIADB("mariadb", "10.10", () -> MariaDBContainer.class),
|
||||
|
||||
/**
|
||||
* A container image suitable for testing MongoDB.
|
||||
|
@ -168,7 +170,7 @@ public enum TestImage {
|
|||
/**
|
||||
* A container image suitable for testing MySQL.
|
||||
*/
|
||||
MYSQL("mysql", "8.0"),
|
||||
MYSQL("mysql", "8.0", () -> MySQLContainer.class),
|
||||
|
||||
/**
|
||||
* A container image suitable for testing Neo4j.
|
||||
|
|
Loading…
Reference in New Issue