springboot 啓動時初始化數據庫

問題描述

在spring-boot啓動時,但願能執行相應的sql文件來初始化數據庫。java

使用配置文件初始化數據庫

能夠在spring-boot的配置文件application.yml中設置要初始化的sql文件。這是最簡單的方法,只須要添加屬性就能夠實現。mysql

首先設置spring.datasource.initialization-mode=always表示任何類型數據庫都進行數據庫初始化,默認狀況下,spring-boot會自動加載data.sqldata-${platform}.sql文件來初始化數據庫。能夠經過設置不一樣的數據庫平臺來改變啓動的腳本名稱。spring

例如設置spring.datasource.platform=mysql,就會加載data-mysql.sql的數據庫腳本。把數據庫腳本文件放在resources路徑下便可。sql

若是項目使用的是flyway管理數據庫的話,能夠直接在flyway路徑下添加一個新版本的sql文件,flyway也會自動執行sql文件並記錄版本信息。數據庫

經過代碼初始化數據庫

若是經過配置文件不能知足需求,能夠經過代碼來初始化數據庫。
只須要提供DataSourceInitializer這個bean,spring-boot啓動時就會根據DataSourceInitializer來初始化數據庫了。app

@Bean
public DataSourceInitializer dataSourceInitializer(final DataSource dataSource) {
    ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();
    resourceDatabasePopulator.addScript(new ClassPathResource("/data.sql"));
    DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
    dataSourceInitializer.setDataSource(dataSource);
    dataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);
    return dataSourceInitializer;
}

在此基礎上,咱們能夠自定義註解,經過獲取註解上的sql文件路徑,來達到經過註解初始化數據庫目的,這樣更方便簡潔。
首先定義註解InitDataSource:ide

/**  
 * 用於補充:Hibernate沒法自動建立視圖的缺陷。  
  * 系統啓動時(hibernate根據entity建立完基本的數據表後),開始執行本註解下的sql文件中的SQL語言。  
 * 使用方法:  
 * @InitDataSource("sql文件路徑(相對於resources路徑下)")  ---- 註解到對應的類上  
 * 好比:@InitDataSource("db/view/createView.sql)")  
 * 使用示例請參見:ResourceApplication.java  
 * 預瞭解詳細的實現過程請參考:WebConfig.java 的 dataSourceInitializer方法  
  * @author huangtingxiang  
 */
@Target({ElementType.TYPE})     // 該註解用於類上  
@Retention(RetentionPolicy.RUNTIME) // 在運行時起做用  
@Component  
public @interface InitDataSource {  
    String\[\] value();  
}

而後經過ClassPathScanningCandidateComponentProvider這個類來掃描spring組件上InitDataSource註解的值,將值取出,添加到DataSourceInitializer的初始化腳本中:spring-boot

@Bean  
public DataSourceInitializer dataSourceInitializer(final DataSource dataSource) {  
    ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();  
    // 掃描com.mengyunzhi.measurement 包 找到InitDataSource註解的類(註解需使用到實現類上)  
  ClassPathScanningCandidateComponentProvider provider  
            = new ClassPathScanningCandidateComponentProvider(false);  
    provider.addIncludeFilter(new AnnotationTypeFilter(InitDataSource.class)); //添加包含的過濾信息  
  for (BeanDefinition beanDef : provider.findCandidateComponents("com.mengyunzhi.measurement")) {  
        Class<?> cl = null;  
        try {  
            cl = Class.forName(beanDef.getBeanClassName());  
            InitDataSource initDataSource = cl.getAnnotation(InitDataSource.class);  
            String\[\] sqlFiles = initDataSource.value();  
            for (String sql: sqlFiles) {  
                // 若是sql文件存在 加入數據庫初始化中 不然拋出異常終止執行  
  ClassPathResource resource = new ClassPathResource("/" + sql);  
                if (resource.exists()) {  
                    resourceDatabasePopulator.addScript(resource);  
                } else {  
                    throw new DataSourceInitializerException("未找到資源文件:" + sql, cl);  
                }  
            }  
        } catch (ClassNotFoundException e) {  
            e.printStackTrace();  
        }  
    }  
    DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();  
    dataSourceInitializer.setDataSource(dataSource);  
    dataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);  
    return dataSourceInitializer;  
}

這樣一來,只須要在spring-boot類上使用@InitDataSource({"data.sql"})註解,就能夠自動進行數據庫的初始化操做了。hibernate

參考文章:
Spring boot. Run SQL scripts and get data on application startupcode

相關文章
相關標籤/搜索