https://start.spring.io/ を使用して適当なプロジェクトを作成する。複数DBとしてmysqlとpostgresqlに接続するのでそれら関連の依存性を追加する。
build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.2'
id 'io.spring.dependency-management' version '1.1.6'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
runtimeOnly 'com.mysql:mysql-connector-j'
runtimeOnly 'org.postgresql:postgresql'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.boot:spring-boot-testcontainers'
testImplementation 'org.testcontainers:junit-jupiter'
testImplementation 'org.testcontainers:mysql'
testImplementation 'org.testcontainers:postgresql'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}
テストコードを作成する。
import javax.sql.DataSource;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@SpringBootTest
@Testcontainers
@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)
class AppTest {
@Container
static MySQLContainer<?> mysql = new MySQLContainer<>("mysql:5.7.34");
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine");
@DynamicPropertySource
static void registerProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.mysql.url", () -> mysql.getJdbcUrl());
registry.add("spring.datasource.mysql.username", () -> mysql.getUsername());
registry.add("spring.datasource.mysql.password", () -> mysql.getPassword());
registry.add("spring.datasource.postgres.url", () -> postgres.getJdbcUrl());
registry.add("spring.datasource.postgres.username", () -> postgres.getUsername());
registry.add("spring.datasource.postgres.password", () -> postgres.getPassword());
}
@TestConfiguration
static class TestConfig {
@Bean
@ConfigurationProperties("spring.datasource.mysql")
public DataSourceProperties mysqlDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@ConfigurationProperties("spring.datasource.postgres")
public DataSourceProperties postgresDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
public DataSource mysqlDataSource() {
return mysqlDataSourceProperties()
.initializeDataSourceBuilder()
.build();
}
@Bean
public DataSource postgresDataSource() {
return postgresDataSourceProperties()
.initializeDataSourceBuilder()
.build();
}
}
@Test
void test(
@Qualifier("mysqlDataSource") DataSource mysqlDataSource,
@Qualifier("postgresDataSource") DataSource postgresDataSource) {
Integer v1 = JdbcClient.create(mysqlDataSource).sql("select cast('1' AS unsigned)")
.query(Integer.class).single();
System.out.println("mysql:" + v1);
Integer v2 = JdbcClient.create(postgresDataSource).sql("select cast('1' AS int)")
.query(Integer.class).single();
System.out.println("postgres:" + v2);
}
}
スマートなやり方が分からなかったので、@DynamicPropertySource
で動的にデータソース関連プロパティを単純に書き換えている。@ServiceConnection
が使用できそうな気もするけど、auto-configを見ると単一DBにしか対応してないのかな……という感じもしたが良く分からない。springのConnectionDetails
の仕組みを利用しているので、これをもう少し調べれば何とかなるかな……という気もする。これ以上は調べきれなかったので一旦これで投稿してしまう。