Spring Boot整合H2内存数据库启动时无法自动执行SQL脚本排查
Spring Boot集成H2内存数据库启动时无法自动执行初始化SQL脚本
问题描述
- 集成H2内存数据库的Spring Boot应用需要在启动时自动执行SQL脚本创建数据表,脚本手动执行可正常运行,但始终无法实现启动自动执行的效果。
- 已知将SQL脚本放在classpath对应
src/main/resources目录下即可被框架自动执行,参考公开的各类解决方案逐一尝试后,本地环境均未生效。
环境配置
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>2.6.3</version> <relativePath/> </parent> <groupId>...</groupId> <artifactId>...</artifactId> <version>0.0.1-SNAPSHOT</version> <name>...</name> <description>...</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.3.6</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.4.193</version> </dependency> <!-- 从Spring Boot 2.x默认的HikariCP切换回Tomcat JDBC,用于后续Heroku部署配置 --> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/resources</directory> <excludes> <exclude>app/**</exclude> </excludes> </resource> </resources> <plugins> <plugin> <groupId>com.heroku.sdk</groupId> <artifactId>heroku-maven-plugin</artifactId> <version>2.0.8</version> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> </plugins> </build> </project>
application.properties基础配置
spring.h2.console.enabled=true spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=admin spring.datasource.password=admin spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.jpa.hibernate.ddl-auto=none
已尝试的无效方案
- 尝试在配置文件中添加各类脚本路径配置,均未生效:
# 配置1 spring.datasource.schema=classpath:data.sql # 配置2 spring.sql.init.schema-locations=classpath:data.sql # 配置3 spring.datasource.data=classpath:data.sql # 配置4 spring.sql.init.data-locations=classpath:data.sql
- 尝试自定义DataSource Bean手动执行脚本,配置后日志仅输出H2控制台启动信息,仍未执行初始化脚本:
2022-06-25 18:46:25.826 INFO 5303 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. 2022-06-25 18:46:25.840 INFO 5303 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 8 ms. Found 0 JPA repository interfaces. 2022-06-25 18:46:26.413 INFO 5303 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8081 (http) 2022-06-25 18:46:26.419 INFO 5303 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2022-06-25 18:46:26.419 INFO 5303 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.56] 2022-06-25 18:46:26.467 INFO 5303 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2022-06-25 18:46:26.467 INFO 5303 --- [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1335 ms 2022-06-25 18:46:26.568 INFO 5303 --- [ restartedMain] o.s.b.a.h2.H2ConsoleAutoConfiguration : H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:testdb' 2022-06-25 18:46:26.725 INFO 5303 --- [ restartedMain] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default] 2022-06-25 18:46:26.747 INFO 5303 --- [ restartedMain] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.6.4.Final 2022-06-25 18:46:26.857 INFO 5303 --- [ restartedMain] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final} 2022-06-25 18:46:26.906 INFO 5303 --- [ restartedMain] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect 2022-06-25 18:46:26.993 INFO 5303 --- [ restartedMain] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
对应的自定义DataSource Bean代码如下:
@Bean public DriverManagerDataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("org.h2.Driver"); dataSource.setUrl("jdbc:h2:mem:testdb"); dataSource.setUsername("admin"); dataSource.setPassword("admin"); // 初始化schema Resource initSchema = new ClassPathResource("data.sql"); DatabasePopulator databasePopulator = new ResourceDatabasePopulator(initSchema); DatabasePopulatorUtils.execute(databasePopulator, dataSource); return dataSource; }
问题根因与解决方案
问题根因:项目引入tomcat-jdbc依赖后,Spring Boot默认的连接池HikariCP未正常启动,导致框架内置的SQL初始化机制无法触发。
手动将HikariDataSource注册为Spring Bean即可解决问题,代码如下:
@Bean public HikariDataSource createHikariConfig() { HikariConfig hikariConfig = new HikariConfig(); hikariConfig.setDriverClassName("org.h2.Driver"); hikariConfig.setJdbcUrl("jdbc:h2:mem:testdb"); hikariConfig.setUsername("admin"); hikariConfig.setPassword("admin"); return new HikariDataSource(hikariConfig); }
配置完成后HikariPool正常启动,应用会自动执行src/main/resources目录下的schema.sql初始化脚本,问题解决。
内容的提问来源于stack exchange,提问作者Ruthless
相关产品推荐
相关产品推荐

