在 Spring Boot 测试中,我们经常使用 @Sql 注解来执行 SQL 脚本,以便在测试前准备数据或在测试后清理数据。 通常的用法如下:
@Sql(scripts = "/folder/my_favourite_script.sql")
@Test
public void myTest() {
// 测试逻辑
}然而,当需要执行大量 SQL 文件时,例如一个目录中有 1000 个 SQL 文件,直接在 @Sql 注解中列出所有文件显得非常繁琐。 期望能够使用文件掩码,例如 /folder/*.sql,来一次性指定所有 SQL 文件。 不幸的是,@Sql 注解本身并不支持这种文件掩码的功能。
那么,该如何解决这个问题呢? 目前主要有两种方案:
1. 使用编程方式执行 SQL 脚本 (适用于 PostgreSQL 等数据库)
由于 @Sql 注解不支持文件掩码,我们可以通过编程的方式读取 SQL 文件并执行。 这需要我们注入 DataSource 对象,并使用它来执行 SQL 脚本。
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.datasource.init.ScriptUtils; import javax.sql.DataSource; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.sql.Connection; import java.sql.SQLException; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @Autowired private DataSource dataSource; public void executeSqlScripts(String folderPath) throws SQLException, IOException { try (Connection connection = dataSource.getConnection()) { List
sqlFiles = Files.list(Paths.get(folderPath)) .filter(path -> path.toString().endsWith(".sql")) .collect(Collectors.toList()); for (Path sqlFile : sqlFiles) { ScriptUtils.executeSqlScript(connection, new org.springframework.core.io.FileSystemResource(sqlFile.toFile())); } } } @Test public void myTest() throws SQLException, IOException { executeSqlScripts("src/test/resources/folder"); // 替换为你的 SQL 文件目录 // 测试逻辑 }
注意事项:
2. 使用 H2 数据库的 RUNSCRIPT 命令
如果测试中使用的是 H2 数据库,可以利用其 RUNSCRIPT 命令来批量执行 SQL 文件。 首先,创建一个名为 scripts.sql 的文件,并将所有需要执行的 SQL 文件路径写入其中,每行一个 RUNSCRIPT 命令。
-- scripts.sql RUNSCRIPT FROM 'file1.sql'; RUNSCRIPT FROM 'file2.sql'; RUNSCRIPT FROM 'file3.sql'; -- ...
然后,在 @Sql 注解中指定该 scripts.sql 文件。
@Sql("scripts.sql")
@Test
public void myTest() {
// 测试逻辑
}注意事项:
总结
虽然 @Sql 注解本身不支持文件掩码,但我们可以通过编程方式或利用数据库特定的命令来实现批量执行 SQL 文件的目的。 选择哪种方案取决于所使用的数据库和具体的测试需求。 如果使用 PostgreSQL 等数据库,推荐使用编程方式,灵活性更高; 如果使用 H2 数据库,则可以使用 RUNSCRIPT 命令,更加简洁。