You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

开启Spring延迟初始化后嵌入式H2数据库未初始化问题

解决Spring Boot开启懒加载后H2初始化脚本不执行的问题

基于Spring Boot v2.7.18 + H2 v2.2.220的测试环境,开启spring.main.lazy-initialization=true后,test-schema.sql未执行,导致@Sql注解执行test-data.sql时提示表不存在。

问题根源

全局懒加载开启后,Spring Boot负责执行SQL初始化脚本的核心Bean(DataSourceScriptDatabaseInitializer,Spring Boot 2.5+引入)会被延迟初始化。而测试中的@Sql脚本执行时机(BEFORE_TEST_METHOD)早于该Bean的初始化,导致表还未创建就执行删除/插入操作,抛出表不存在异常。

可行解决方案

1. 精准排除SQL初始化相关Bean的懒加载

之前的排除列表遗漏了关键的DataSourceScriptDatabaseInitializer类,这是执行spring.sql.init配置脚本的核心Bean。修改你的LazyInitializationExcludeFilter,添加该类:

@Bean
public static LazyInitializationExcludeFilter integrationLazyInitializationExcludeFilter() {
    return LazyInitializationExcludeFilter.forBeanTypes(
            DataSource.class,
            DataSourceScriptDatabaseInitializer.class, // 核心:负责执行SQL初始化脚本
            DataSourceInitializer.class, // 兼容旧版本的初始化Bean
            H2ConsoleAutoConfiguration.class,
            EmbeddedDataSourceConfiguration.class,
            DataSourceAutoConfiguration.class,
            DatabasePopulator.class,
            DataSourceHealthContributorAutoConfiguration.class,
            DataSourcePoolMetadataProvidersConfiguration.class,
            JdbcTemplateAutoConfiguration.class
    );
}

2. 在测试类中强制提前初始化Schema

如果不想修改全局排除规则,可以在测试类的@BeforeAll阶段手动执行test-schema.sql,确保表在测试前创建:

import org.springframework.jdbc.datasource.init.ScriptUtils;
import org.springframework.core.io.ClassPathResource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

@SpringBootTest
public class MyTests {

    @Autowired
    private DataSource dataSource;

    @BeforeAll
    void initSchema() {
        try (Connection conn = dataSource.getConnection()) {
            ScriptUtils.executeSqlScript(conn, new ClassPathResource("test-schema.sql"));
        } catch (SQLException e) {
            throw new RuntimeException("Schema初始化失败", e);
        }
    }

    @Sql(scripts = {"classpath:test-data.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
    @Test
    void myTest() {
        // 测试逻辑
    }
}

3. 调整SQL初始化模式

将spring.sql.init.mode从embedded改为always,确保无论数据源类型如何,初始化脚本都会执行(虽然嵌入式环境下embedded本应生效,但懒加载可能干扰了触发条件):

spring:
  sql:
    init:
      mode: always
      data-locations:
        - classpath:test-schema.sql

验证注意事项

  • 确保test-schema.sql文件路径正确,且在测试类的classpath下
  • 检查H2数据库URL中的DB_CLOSE_DELAY=-1配置是否保留,避免数据库提前关闭

内容的提问来源于stack exchange,提问作者nonzaprej

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 19:33:12