mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-07-15 01:07:30 +08:00
Fix appending of JDBC parameters to SQL Server JDBC URL
Fixes gh-41146
This commit is contained in:
parent
43cd24102f
commit
126e87e44d
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -68,20 +68,33 @@ public class JdbcUrlBuilder {
|
|||||||
|
|
||||||
private String urlFor(RunningService service, String database) {
|
private String urlFor(RunningService service, String database) {
|
||||||
Assert.notNull(service, "Service must not be null");
|
Assert.notNull(service, "Service must not be null");
|
||||||
String parameters = getParameters(service);
|
|
||||||
StringBuilder url = new StringBuilder("jdbc:%s://%s:%d".formatted(this.driverProtocol, service.host(),
|
StringBuilder url = new StringBuilder("jdbc:%s://%s:%d".formatted(this.driverProtocol, service.host(),
|
||||||
service.ports().get(this.containerPort)));
|
service.ports().get(this.containerPort)));
|
||||||
if (StringUtils.hasLength(database)) {
|
if (StringUtils.hasLength(database)) {
|
||||||
url.append("/");
|
url.append("/");
|
||||||
url.append(database);
|
url.append(database);
|
||||||
}
|
}
|
||||||
url.append(parameters);
|
String parameters = getParameters(service);
|
||||||
|
if (StringUtils.hasLength(parameters)) {
|
||||||
|
appendParameters(url, parameters);
|
||||||
|
}
|
||||||
return url.toString();
|
return url.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends to the given {@code url} the given {@code parameters}.
|
||||||
|
* <p>
|
||||||
|
* The default implementation appends a {@code ?} followed by the {@code parameters}.
|
||||||
|
* @param url the url
|
||||||
|
* @param parameters the parameters
|
||||||
|
* @since 3.2.7
|
||||||
|
*/
|
||||||
|
protected void appendParameters(StringBuilder url, String parameters) {
|
||||||
|
url.append("?").append(parameters);
|
||||||
|
}
|
||||||
|
|
||||||
private String getParameters(RunningService service) {
|
private String getParameters(RunningService service) {
|
||||||
String parameters = service.labels().get(PARAMETERS_LABEL);
|
return service.labels().get(PARAMETERS_LABEL);
|
||||||
return (StringUtils.hasLength(parameters)) ? "?" + parameters : "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -47,7 +47,7 @@ class SqlServerJdbcDockerComposeConnectionDetailsFactory
|
|||||||
static class SqlServerJdbcDockerComposeConnectionDetails extends DockerComposeConnectionDetails
|
static class SqlServerJdbcDockerComposeConnectionDetails extends DockerComposeConnectionDetails
|
||||||
implements JdbcConnectionDetails {
|
implements JdbcConnectionDetails {
|
||||||
|
|
||||||
private static final JdbcUrlBuilder jdbcUrlBuilder = new JdbcUrlBuilder("sqlserver", 1433);
|
private static final JdbcUrlBuilder jdbcUrlBuilder = new SqlServerJdbcUrlBuilder("sqlserver", 1433);
|
||||||
|
|
||||||
private final SqlServerEnvironment environment;
|
private final SqlServerEnvironment environment;
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ class SqlServerJdbcDockerComposeConnectionDetailsFactory
|
|||||||
SqlServerJdbcDockerComposeConnectionDetails(RunningService service) {
|
SqlServerJdbcDockerComposeConnectionDetails(RunningService service) {
|
||||||
super(service);
|
super(service);
|
||||||
this.environment = new SqlServerEnvironment(service.env());
|
this.environment = new SqlServerEnvironment(service.env());
|
||||||
this.jdbcUrl = disableEncryptionIfNecessary(jdbcUrlBuilder.build(service, ""));
|
this.jdbcUrl = disableEncryptionIfNecessary(jdbcUrlBuilder.build(service));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String disableEncryptionIfNecessary(String jdbcUrl) {
|
private String disableEncryptionIfNecessary(String jdbcUrl) {
|
||||||
@ -86,6 +86,19 @@ class SqlServerJdbcDockerComposeConnectionDetailsFactory
|
|||||||
return this.jdbcUrl;
|
return this.jdbcUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class SqlServerJdbcUrlBuilder extends JdbcUrlBuilder {
|
||||||
|
|
||||||
|
private SqlServerJdbcUrlBuilder(String driverProtocol, int containerPort) {
|
||||||
|
super(driverProtocol, containerPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void appendParameters(StringBuilder url, String parameters) {
|
||||||
|
url.append(";").append(parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -67,6 +67,20 @@ class JdbcUrlBuilderTests {
|
|||||||
assertThat(url).isEqualTo("jdbc:mydb://myhost:456/mydb?foo=bar");
|
assertThat(url).isEqualTo("jdbc:mydb://myhost:456/mydb?foo=bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void buildWithCustomAppendParametersWhenHasParamsLabelBuildsUrl() {
|
||||||
|
RunningService service = mockService(456, Map.of("org.springframework.boot.jdbc.parameters", "foo=bar"));
|
||||||
|
String url = new JdbcUrlBuilder("mydb", 1234) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void appendParameters(StringBuilder url, String parameters) {
|
||||||
|
url.append(";").append(parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
}.build(service, "mydb");
|
||||||
|
assertThat(url).isEqualTo("jdbc:mydb://myhost:456/mydb;foo=bar");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void buildWhenServiceIsNullThrowsException() {
|
void buildWhenServiceIsNullThrowsException() {
|
||||||
assertThatIllegalArgumentException().isThrownBy(() -> this.builder.build(null, "mydb"))
|
assertThatIllegalArgumentException().isThrownBy(() -> this.builder.build(null, "mydb"))
|
||||||
|
@ -40,13 +40,27 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
disabledReason = "The SQL server image has no ARM support")
|
disabledReason = "The SQL server image has no ARM support")
|
||||||
class SqlServerJdbcDockerComposeConnectionDetailsFactoryIntegrationTests {
|
class SqlServerJdbcDockerComposeConnectionDetailsFactoryIntegrationTests {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@DockerComposeTest(composeFile = "mssqlserver-compose.yaml", image = TestImage.SQL_SERVER)
|
@DockerComposeTest(composeFile = "mssqlserver-compose.yaml", image = TestImage.SQL_SERVER)
|
||||||
void runCreatesConnectionDetailsThatCanBeUsedToAccessDatabase(JdbcConnectionDetails connectionDetails)
|
void runCreatesConnectionDetailsThatCanBeUsedToAccessDatabase(JdbcConnectionDetails connectionDetails)
|
||||||
throws ClassNotFoundException, LinkageError {
|
throws ClassNotFoundException, LinkageError {
|
||||||
assertThat(connectionDetails.getUsername()).isEqualTo("SA");
|
assertThat(connectionDetails.getUsername()).isEqualTo("SA");
|
||||||
assertThat(connectionDetails.getPassword()).isEqualTo("verYs3cret");
|
assertThat(connectionDetails.getPassword()).isEqualTo("verYs3cret");
|
||||||
assertThat(connectionDetails.getJdbcUrl()).startsWith("jdbc:sqlserver://");
|
assertThat(connectionDetails.getJdbcUrl()).startsWith("jdbc:sqlserver://");
|
||||||
|
checkDatabaseAccess(connectionDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DockerComposeTest(composeFile = "mssqlserver-with-jdbc-parameters-compose.yaml", image = TestImage.SQL_SERVER)
|
||||||
|
void runWithJdbcParametersCreatesConnectionDetailsThatCanBeUsedToAccessDatabase(
|
||||||
|
JdbcConnectionDetails connectionDetails) throws ClassNotFoundException {
|
||||||
|
assertThat(connectionDetails.getUsername()).isEqualTo("SA");
|
||||||
|
assertThat(connectionDetails.getPassword()).isEqualTo("verYs3cret");
|
||||||
|
assertThat(connectionDetails.getJdbcUrl()).startsWith("jdbc:sqlserver://")
|
||||||
|
.contains(";sendStringParametersAsUnicode=false;");
|
||||||
|
checkDatabaseAccess(connectionDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private void checkDatabaseAccess(JdbcConnectionDetails connectionDetails) throws ClassNotFoundException {
|
||||||
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
|
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
|
||||||
dataSource.setUrl(connectionDetails.getJdbcUrl());
|
dataSource.setUrl(connectionDetails.getJdbcUrl());
|
||||||
dataSource.setUsername(connectionDetails.getUsername());
|
dataSource.setUsername(connectionDetails.getUsername());
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
services:
|
||||||
|
database:
|
||||||
|
image: '{imageName}'
|
||||||
|
ports:
|
||||||
|
- '1433'
|
||||||
|
environment:
|
||||||
|
- 'MSSQL_PID=express'
|
||||||
|
- 'MSSQL_SA_PASSWORD=verYs3cret'
|
||||||
|
- 'ACCEPT_EULA=yes'
|
||||||
|
labels:
|
||||||
|
org.springframework.boot.jdbc.parameters: sendStringParametersAsUnicode=false
|
Loading…
Reference in New Issue
Block a user