本篇解決 Spring 執行SQL腳本(文件)的問題。java
場景描述能夠不看。git
場景描述:github
我在運行單測的時候,也就是 Spring 工程啓動的時候,Spring 會去執行 classpath:schema.sql(後面會解釋),我想利用這一點,解決一個問題:spring
一次運行多個測試文件,每一個文件前後獨立運行,而上一個文件建立的數據,會對下一個文件運行時形成影響,因此我要在每一個文件執行完成以後,重置數據庫,不僅僅是把數據刪掉,而 schema.sql 裏面有 drop table 和create table。sql
解決方法:數據庫
//Schema 處理器 @Component public class SchemaHandler { private final String SCHEMA_SQL = "classpath:schema.sql"; @Autowired private DataSource datasource; @Autowired private SpringContextGetter springContextGetter; public void execute() throws Exception { Resource resource = springContextGetter.getApplicationContext().getResource(SCHEMA_SQL); ScriptUtils.executeSqlScript(datasource.getConnection(), resource); } } // 獲取 ApplicationContext @Component public class SpringContextGetter implements ApplicationContextAware { private ApplicationContext applicationContext; public ApplicationContext getApplicationContext() { return applicationContext; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
備註:app
關於爲什麼 Spring 會去執行 classpath:schema.sql,能夠參考源碼ide
org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer#runSchemaScriptsspring-boot
private void runSchemaScripts() { List<Resource> scripts = getScripts("spring.datasource.schema", this.properties.getSchema(), "schema"); if (!scripts.isEmpty()) { String username = this.properties.getSchemaUsername(); String password = this.properties.getSchemaPassword(); runScripts(scripts, username, password); try { this.applicationContext .publishEvent(new DataSourceInitializedEvent(this.dataSource)); // The listener might not be registered yet, so don't rely on it. if (!this.initialized) { runDataScripts(); this.initialized = true; } } catch (IllegalStateException ex) { logger.warn("Could not send event to complete DataSource initialization (" + ex.getMessage() + ")"); } } } /** * 默認拿 classpath*:schema-all.sql 和 classpath*:schema.sql */ private List<Resource> getScripts(String propertyName, List<String> resources, String fallback) { if (resources != null) { return getResources(propertyName, resources, true); } String platform = this.properties.getPlatform(); List<String> fallbackResources = new ArrayList<String>(); fallbackResources.add("classpath*:" + fallback + "-" + platform + ".sql"); fallbackResources.add("classpath*:" + fallback + ".sql"); return getResources(propertyName, fallbackResources, false); }
參考:https://github.com/spring-pro...測試