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

Spring Boot Test中如何用通配符配置@Sql注解的脚本文件?

解决@Sql注解无法通过通配符批量执行SQL文件的问题

问题原因

使用@Sql(scripts = "/folder/*.sql")时触发以下错误:

org.springframework.jdbc.datasource.init.CannotReadScriptException:
无法从类路径资源读取SQL脚本 [folder/.sql]; 嵌套异常为java.io.FileNotFoundException: 类路径资源
[folder/
.sql] 无法打开,因为它不存在

这是因为@Sql注解本身不支持通配符路径匹配,它会将*.sql视为具体文件名去查找,导致找不到对应资源。

解决方案

方案1:通过SpEL+ResourcePatternResolver动态加载脚本

借助Spring的ResourcePatternResolver扫描指定路径下的所有SQL文件,通过SpEL表达式在@SqlGroup中注入脚本路径:

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.jdbc.SqlGroup;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.util.Arrays;
import java.util.stream.Collectors;

public class BatchSqlTest {

    private static final ResourcePatternResolver RESOLVER = new PathMatchingResourcePatternResolver();

    @Test
    @SqlGroup({
            @Sql(scripts = "#{T(com.example.BatchSqlTest).getAllSqlScripts()}")
    })
    void executeAllSqlScripts() {
        // 测试逻辑
    }

    public static String[] getAllSqlScripts() throws IOException {
        Resource[] resources = RESOLVER.getResources("classpath:/folder/*.sql");
        return Arrays.stream(resources)
                .map(resource -> {
                    try {
                        return resource.getURL().toString().replaceFirst("file:", "");
                    } catch (IOException e) {
                        throw new RuntimeException("Failed to resolve SQL script path", e);
                    }
                })
                .toArray(String[]::new);
    }
}

方案2:合并SQL脚本到单个文件

将目标文件夹下的所有SQL内容合并到一个总脚本(如all_scripts.sql),直接用常规@Sql引用:

@Sql(scripts = "/folder/all_scripts.sql")
@Test
void executeMergedSqlScript() {
    // 测试逻辑
}

该方式简单直接,适合无需单独维护单个SQL文件的场景。

方案3:自定义TestExecutionListener

实现Spring Test的TestExecutionListener,在测试方法执行前自动扫描并执行指定路径下的所有SQL文件:

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.init.ScriptUtils;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;

import javax.sql.DataSource;
import java.io.IOException;

public class BatchSqlListener extends AbstractTestExecutionListener {

    @Override
    public void beforeTestMethod(TestContext testContext) throws IOException {
        DataSource dataSource = testContext.getApplicationContext().getBean(DataSource.class);
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources("classpath:/folder/*.sql");
        
        for (Resource resource : resources) {
            ScriptUtils.executeSqlScript(dataSource.getConnection(), resource);
        }
    }
}

在测试类上注册该监听器:

import org.springframework.test.context.TestExecutionListeners;
import org.junit.jupiter.api.Test;

@TestExecutionListeners(listeners = BatchSqlListener.class, mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS)
public class BatchSqlTest {

    @Test
    void executeAllSqlScripts() {
        // 测试逻辑
    }
}

内容的提问来源于stack exchange,提问作者mvn.2047

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 02:20:53