Spring Boot为何忽略application.properties中H2数据库的spring.datasource.url配置?
我有一个Spring Boot应用,会创建H2数据库并加载测试数据,希望通过H2控制台查看数据。application.properties配置如下:
spring.h2.console.enabled=true spring.h2.console.path=/h2-console spring.datasource.url=jdbc:h2:file:D:/ProgrammingStuff/wiktionaries/wiktdb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password= spring.jpa.hibernate.ddl-auto=create-drop
注释掉spring.datasource.url时,Spring Boot使用默认内存库jdbc:h2:mem:testdb,能正常通过H2控制台连接查看数据。但指定自定义URL后,控制台日志仍显示:
2023-12-29T10:23:56.665+01:00 INFO 9904 --- [ restartedMain] o.s.b.a.h2.H2ConsoleAutoConfiguration : H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:testdb'
且只能通过jdbc:h2:mem:testdb连接,自定义URL无法使用。application.properties路径正确,位于src/main/resources/application.properties。
相关文件
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.1</version> <relativePath /> <!-- lookup parent from repository --> </parent> <groupId>com.pux12</groupId> <artifactId>dictionarycreator</artifactId> <version>0.0.1-SNAPSHOT</version> <name>dictionarycreator</name> <description>Demo project for Spring Boot</description> <properties> <java.version>21</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <version>3.2.1</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20231013</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.jsonschema2pojo</groupId> <artifactId>jsonschema2pojo-maven-plugin</artifactId> <version>1.2.1</version> <configuration> <sourceDirectory>${basedir}/src/main/resources/wiktionary</sourceDirectory> <targetPackage>com.example.types</targetPackage> </configuration> <executions> <execution> <goals> <goal>generate</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
SpringJdbcConfig.java
package com.pux12.dictionarycreator; import javax.sql.DataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; @Configuration @ComponentScan("com.pux12.dictionarycreator") public class SpringJdbcConfig { @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) .addScript("classpath:jdbc/schema.sql") .addScript("classpath:jdbc/data.sql").build(); } }
Spring Boot日志
:: Spring Boot :: (v3.2.1) 2023-12-29T10:49:54.327+01:00 INFO 14272 --- [ restartedMain] c.p.d.DictionarycreatorApplication : Starting DictionarycreatorApplication using Java 21.0.1 with PID 14272 (C:\Users\hanne\Documents\Programme\dictionarycreator\target\classes started by hanne in C:\Users\hanne\Documents\Programme\dictionarycreator) 2023-12-29T10:49:54.332+01:00 INFO 14272 --- [ restartedMain] c.p.d.DictionarycreatorApplication : No active profile set, falling back to 1 default profile: "default" 2023-12-29T10:49:54.418+01:00 INFO 14272 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable 2023-12-29T10:49:54.418+01:00 INFO 14272 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' 2023-12-29T10:49:56.425+01:00 INFO 14272 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http) 2023-12-29T10:49:56.456+01:00 INFO 14272 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2023-12-29T10:49:56.458+01:00 INFO 14272 --- [ restartedMain] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.17] 2023-12-29T10:49:56.555+01:00 INFO 14272 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2023-12-29T10:49:56.558+01:00 INFO 14272 --- [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2137 ms 2023-12-29T10:49:56.589+01:00 INFO 14272 --- [ restartedMain] o.s.j.d.e.EmbeddedDatabaseFactory : Starting embedded database: url='jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa' 2023-12-29T10:49:56.860+01:00 INFO 14272 --- [ restartedMain] o.s.b.a.h2.H2ConsoleAutoConfiguration : H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:testdb' 2023-12-29T10:49:57.775+01:00 INFO 14272 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729 2023-12-29T10:49:57.834+01:00 INFO 14272 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '' 2023-12-29T10:49:57.853+01:00 INFO 14272 --- [ restartedMain] c.p.d.DictionarycreatorApplication : Started DictionarycreatorApplication in 4.008 seconds (process running for 4.663)
环境:Windows 10、Spring Boot 3.2.1、安装Java扩展的VS Code
问题核心是SpringJdbcConfig.java中自定义的DataSource Bean覆盖了Spring Boot的自动配置。这个Bean通过EmbeddedDatabaseBuilder强制创建了内存型H2数据库,完全忽略了application.properties里的配置参数。
有两种解决方式:
方式一:移除自定义DataSource配置
直接删除SpringJdbcConfig.java文件,或者注释掉其中的dataSource() Bean方法。Spring Boot会自动读取application.properties中的配置生成数据源,同时默认会自动执行classpath下的schema.sql和data.sql脚本,无需额外配置。
方式二:修改自定义DataSource,读取配置文件参数
如果需要保留自定义配置结构,修改dataSource()方法,读取配置文件中的数据库参数,同时保留脚本加载逻辑:
package com.pux12.dictionarycreator; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.jdbc.datasource.init.DataSourceInitializer; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; @Configuration @ComponentScan("com.pux12.dictionarycreator") public class SpringJdbcConfig { @Value("${spring.datasource.url}") private String dbUrl; @Value("${spring.datasource.username}") private String dbUsername; @Value("${spring.datasource.password}") private String dbPassword; @Value("${spring.datasource.driverClassName}") private String dbDriver; @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(dbDriver); dataSource.setUrl(dbUrl); dataSource.setUsername(dbUsername); dataSource.setPassword(dbPassword); return dataSource; } @Bean public DataSourceInitializer dataSourceInitializer(DataSource dataSource) { ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); populator.addScript(new org.springframework.core.io.ClassPathResource("jdbc/schema.sql")); populator.addScript(new org.springframework.core.io.ClassPathResource("jdbc/data.sql")); DataSourceInitializer initializer = new DataSourceInitializer(); initializer.setDataSource(dataSource); initializer.setDatabasePopulator(populator); return initializer; } }
修改后重启应用,日志会显示使用自定义的文件型H2数据库URL,此时就能通过H2控制台用jdbc:h2:file:D:/ProgrammingStuff/wiktionaries/wiktdb连接查看数据。
内容的提问来源于stack exchange,提问作者Pux

