Skip to content

Commit 63adda6

Browse files
committed
Merge branch '3.3.x' into 3.4.x
Closes gh-45002
2 parents e107e11 + 3e9dddb commit 63adda6

File tree

5 files changed

+114
-17
lines changed

5 files changed

+114
-17
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java

+17-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
3333
import org.springframework.boot.jdbc.DatabaseDriver;
3434
import org.springframework.context.annotation.Bean;
3535
import org.springframework.context.annotation.Configuration;
36+
import org.springframework.core.env.Environment;
3637
import org.springframework.util.StringUtils;
3738

3839
/**
@@ -50,10 +51,17 @@ abstract class DataSourceConfiguration {
5051
@SuppressWarnings("unchecked")
5152
private static <T> T createDataSource(JdbcConnectionDetails connectionDetails, Class<? extends DataSource> type,
5253
ClassLoader classLoader) {
53-
return (T) DataSourceBuilder.create(classLoader)
54-
.type(type)
55-
.driverClassName(connectionDetails.getDriverClassName())
56-
.url(connectionDetails.getJdbcUrl())
54+
return createDataSource(connectionDetails, type, classLoader, true);
55+
}
56+
57+
@SuppressWarnings("unchecked")
58+
private static <T> T createDataSource(JdbcConnectionDetails connectionDetails, Class<? extends DataSource> type,
59+
ClassLoader classLoader, boolean applyDriverClassName) {
60+
DataSourceBuilder<? extends DataSource> builder = DataSourceBuilder.create(classLoader).type(type);
61+
if (applyDriverClassName) {
62+
builder.driverClassName(connectionDetails.getDriverClassName());
63+
}
64+
return (T) builder.url(connectionDetails.getJdbcUrl())
5765
.username(connectionDetails.getUsername())
5866
.password(connectionDetails.getPassword())
5967
.build();
@@ -113,9 +121,11 @@ static HikariJdbcConnectionDetailsBeanPostProcessor jdbcConnectionDetailsHikariB
113121

114122
@Bean
115123
@ConfigurationProperties(prefix = "spring.datasource.hikari")
116-
HikariDataSource dataSource(DataSourceProperties properties, JdbcConnectionDetails connectionDetails) {
124+
HikariDataSource dataSource(DataSourceProperties properties, JdbcConnectionDetails connectionDetails,
125+
Environment environment) {
126+
String dataSourceClassName = environment.getProperty("spring.datasource.hikari.data-source-class-name");
117127
HikariDataSource dataSource = createDataSource(connectionDetails, HikariDataSource.class,
118-
properties.getClassLoader());
128+
properties.getClassLoader(), dataSourceClassName == null);
119129
if (StringUtils.hasText(properties.getName())) {
120130
dataSource.setPoolName(properties.getName());
121131
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java

+12-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2024 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -171,6 +171,15 @@ public void setDriverClassName(String driverClassName) {
171171
* @since 1.4.0
172172
*/
173173
public String determineDriverClassName() {
174+
String driverClassName = findDriverClassName();
175+
if (!StringUtils.hasText(driverClassName)) {
176+
throw new DataSourceBeanCreationException("Failed to determine a suitable driver class", this,
177+
this.embeddedDatabaseConnection);
178+
}
179+
return driverClassName;
180+
}
181+
182+
String findDriverClassName() {
174183
if (StringUtils.hasText(this.driverClassName)) {
175184
Assert.state(driverClassIsLoadable(), () -> "Cannot load driver class: " + this.driverClassName);
176185
return this.driverClassName;
@@ -182,10 +191,6 @@ public String determineDriverClassName() {
182191
if (!StringUtils.hasText(driverClassName)) {
183192
driverClassName = this.embeddedDatabaseConnection.getDriverClassName();
184193
}
185-
if (!StringUtils.hasText(driverClassName)) {
186-
throw new DataSourceBeanCreationException("Failed to determine a suitable driver class", this,
187-
this.embeddedDatabaseConnection);
188-
}
189194
return driverClassName;
190195
}
191196

@@ -277,7 +282,7 @@ public String determineUsername() {
277282
if (StringUtils.hasText(this.username)) {
278283
return this.username;
279284
}
280-
if (EmbeddedDatabaseConnection.isEmbedded(determineDriverClassName(), determineUrl())) {
285+
if (EmbeddedDatabaseConnection.isEmbedded(findDriverClassName(), determineUrl())) {
281286
return "sa";
282287
}
283288
return null;
@@ -305,7 +310,7 @@ public String determinePassword() {
305310
if (StringUtils.hasText(this.password)) {
306311
return this.password;
307312
}
308-
if (EmbeddedDatabaseConnection.isEmbedded(determineDriverClassName(), determineUrl())) {
313+
if (EmbeddedDatabaseConnection.isEmbedded(findDriverClassName(), determineUrl())) {
309314
return "";
310315
}
311316
return null;

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/HikariJdbcConnectionDetailsBeanPostProcessor.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ protected Object processDataSource(HikariDataSource dataSource, JdbcConnectionDe
4141
dataSource.setPassword(connectionDetails.getPassword());
4242
String driverClassName = connectionDetails.getDriverClassName();
4343
if (driverClassName != null) {
44-
dataSource.setDriverClassName(connectionDetails.getDriverClassName());
44+
dataSource.setDriverClassName(driverClassName);
4545
}
4646
return dataSource;
4747
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/PropertiesJdbcConnectionDetails.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/HikariDataSourceConfigurationTests.java

+83-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,12 @@
1616

1717
package org.springframework.boot.autoconfigure.jdbc;
1818

19+
import java.io.PrintWriter;
20+
import java.sql.Connection;
21+
import java.sql.SQLException;
22+
import java.sql.SQLFeatureNotSupportedException;
23+
import java.util.logging.Logger;
24+
1925
import javax.sql.DataSource;
2026

2127
import com.zaxxer.hikari.HikariDataSource;
@@ -28,12 +34,15 @@
2834
import org.springframework.boot.jdbc.DataSourceBuilder;
2935
import org.springframework.boot.jdbc.HikariCheckpointRestoreLifecycle;
3036
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
37+
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
3138
import org.springframework.boot.testsupport.classpath.ClassPathOverrides;
3239
import org.springframework.context.annotation.Bean;
3340
import org.springframework.context.annotation.Configuration;
3441
import org.springframework.jdbc.datasource.DelegatingDataSource;
3542

3643
import static org.assertj.core.api.Assertions.assertThat;
44+
import static org.assertj.core.api.Assertions.assertThatNoException;
45+
import static org.mockito.Mockito.mock;
3746

3847
/**
3948
* Tests for {@link DataSourceAutoConfiguration} with Hikari.
@@ -80,7 +89,33 @@ void testDataSourceGenericPropertiesOverridden() {
8089
HikariDataSource ds = context.getBean(HikariDataSource.class);
8190
assertThat(ds.getDataSourceProperties().getProperty("dataSourceClassName"))
8291
.isEqualTo("org.h2.JDBCDataSource");
92+
});
93+
}
94+
95+
@Test
96+
@SuppressWarnings("resource")
97+
@ClassPathExclusions({ "h2-*.jar", "hsqldb-*.jar" })
98+
void configureDataSourceClassNameWithNoEmbeddedDatabaseAvailable() {
99+
this.contextRunner
100+
.withPropertyValues("spring.datasource.url=jdbc:example//",
101+
"spring.datasource.hikari.data-source-class-name=" + MockDataSource.class.getName())
102+
.run((context) -> {
103+
HikariDataSource ds = context.getBean(HikariDataSource.class);
104+
assertThat(ds.getDataSourceClassName()).isEqualTo(MockDataSource.class.getName());
105+
assertThatNoException().isThrownBy(() -> ds.getConnection().close());
106+
});
107+
}
83108

109+
@Test
110+
@SuppressWarnings("resource")
111+
void configureDataSourceClassNameToOverrideUseOfAnEmbeddedDatabase() {
112+
this.contextRunner
113+
.withPropertyValues("spring.datasource.url=jdbc:example//",
114+
"spring.datasource.hikari.data-source-class-name=" + MockDataSource.class.getName())
115+
.run((context) -> {
116+
HikariDataSource ds = context.getBean(HikariDataSource.class);
117+
assertThat(ds.getDataSourceClassName()).isEqualTo(MockDataSource.class.getName());
118+
assertThatNoException().isThrownBy(() -> ds.getConnection().close());
84119
});
85120
}
86121

@@ -201,4 +236,51 @@ DataSource dataSource() {
201236

202237
}
203238

239+
public static class MockDataSource implements DataSource {
240+
241+
@Override
242+
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
243+
return null;
244+
}
245+
246+
@Override
247+
public <T> T unwrap(Class<T> iface) throws SQLException {
248+
return null;
249+
}
250+
251+
@Override
252+
public boolean isWrapperFor(Class<?> iface) throws SQLException {
253+
return false;
254+
}
255+
256+
@Override
257+
public Connection getConnection() throws SQLException {
258+
return mock(Connection.class);
259+
}
260+
261+
@Override
262+
public Connection getConnection(String username, String password) throws SQLException {
263+
return getConnection();
264+
}
265+
266+
@Override
267+
public PrintWriter getLogWriter() throws SQLException {
268+
return null;
269+
}
270+
271+
@Override
272+
public void setLogWriter(PrintWriter out) throws SQLException {
273+
}
274+
275+
@Override
276+
public void setLoginTimeout(int seconds) throws SQLException {
277+
}
278+
279+
@Override
280+
public int getLoginTimeout() throws SQLException {
281+
return -1;
282+
}
283+
284+
}
285+
204286
}

0 commit comments

Comments
 (0)