Spring Boot集成测试中schema.sql未执行问题求助
解决方案
方法1:自定义EmbeddedPostgres初始化逻辑
zonkyio的embedded-postgres支持通过Builder自定义启动逻辑,你可以在Postgres启动后,先连接默认的postgres库执行schema.sql里的前置操作,再让Liquibase跑迁移:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.datasource.DriverManagerDataSource; import ru.yandex.qatools.embed.postgresql.EmbeddedPostgres; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.sql.Connection; import java.sql.Statement; import java.util.stream.Collectors; @Configuration public class EmbeddedPostgresConfig { @Bean(destroyMethod = "stop") public EmbeddedPostgres embeddedPostgres() throws IOException { EmbeddedPostgres pg = EmbeddedPostgres.start(); // 连接默认postgres库执行前置SQL DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setUrl(pg.getJdbcUrl("postgres", "postgres")); dataSource.setUsername("postgres"); dataSource.setPassword(""); try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement()) { // 读取schema.sql内容 String sql = new BufferedReader( new InputStreamReader(new ClassPathResource("schema.sql").getInputStream())) .lines().collect(Collectors.joining("\n")); // 拆分语句执行(跳过空行) for (String statement : sql.split(";")) { if (!statement.trim().isEmpty()) { stmt.execute(statement); } } } catch (Exception e) { throw new RuntimeException("执行前置schema.sql失败", e); } return pg; } }
这样Postgres启动后会先执行schema.sql里的建库、建角色操作,之后Liquibase再连接目标库执行迁移。
方法2:Spring Boot项目调整初始化顺序
如果是Spring Boot项目,可通过配置强制让schema.sql在Liquibase之前执行:
- 在
application-test.properties中关闭自动执行schema.sql:
spring.sql.init.mode=never
- 自定义初始化Bean,用
@DependsOn注解确保Liquibase等待前置操作完成再启动:
import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.core.io.ClassPathResource; import liquibase.integration.spring.SpringLiquibase; import javax.sql.DataSource; @Configuration public class PreLiquibaseConfig { @Bean public DataSourceScriptDatabaseInitializer preLiquibaseInitializer(DataSource dataSource) { DataSourceScriptDatabaseInitializer initializer = new DataSourceScriptDatabaseInitializer(dataSource); initializer.setScripts(new ClassPathResource("schema.sql")); return initializer; } // 让Liquibase依赖前置初始化Bean,确保先执行schema.sql @Bean @DependsOn("preLiquibaseInitializer") public SpringLiquibase springLiquibase(DataSource dataSource) { SpringLiquibase liquibase = new SpringLiquibase(); liquibase.setDataSource(dataSource); liquibase.setChangeLog("classpath:db/changelog/db.changelog-master.xml"); // 添加你的其他Liquibase配置 return liquibase; } }
方法3:将schema.sql直接引入Liquibase变更日志
如果schema.sql中的语句兼容Liquibase语法,可直接在主变更日志中优先引入它:
<?xml version="1.0" encoding="UTF-8"?> <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.9.xsd"> <!-- 先执行schema.sql中的内容 --> <include file="classpath:schema.sql" relativeToChangelogFile="false"/> <!-- 你的其他迁移变更集 --> <changeSet id="1" author="your-name"> <!-- 具体迁移内容 --> </changeSet> </databaseChangeLog>
注意:如果schema.sql包含建库、建角色语句,需确保Liquibase使用拥有超级权限的用户(如postgres)连接数据库。
内容的提问来源于stack exchange,提问作者enccne
相关产品推荐
相关产品推荐

