90735


複数のDBに接続するアプリーションの開発中です。  
UTでJunit4を使っており、H２でMysqlのDBを立てています。  
Mysqlの方にテーブル定義のsqlを読み込ませたいのですが、schema.sqlと言うファイルをsrc/test/resources配下に置いて、application.ymlで読み込ませるように記述してもテーブルの作成がされておらずテストが途中で失敗します。

下記の書き方で間違いがあるんでしょうか？

application.yml

[code]

    spring:
      datasource:
        mysql:
          url: jdbc:h2:mem:testdb
          password: hoge
          username: hgoe
          driver-class-name: com.mysql.cj.jdbc.Driver
        oracle:
          url: hoge
          username: hoge
          password: hoge
          driver-class-name: hoge
      sql:
        init:
          schema-locations: classpath*:schema.sql
    
[/code]


CC BY-SA 4.0
2022-08-24T08:33:11.890
90730
2022-08-24T11:47:50.287
30328
question
java spring spring-boot kotlin junit
H2にてschema定義のsqlを読み込ませる方法


まず、H2への接続なのでドライバもH2用のもの `org.h2.Driver` を用いる必要があります:

[code]

    spring:
      datasource:
        mysql:
          url: jdbc:h2:mem:testdb
          password: hoge
          username: hgoe
          driver-class-name: org.h2.Driver
    
[/code]

その上で、複数のデータソースが存在する状態で `schema.sql` が自動で適用されるのは `@Primary` として定義されているものだけです。

  * [17.8.2. Configure Two DataSources](https://docs.spring.io/spring-boot/docs/2.7.3/reference/htmlsingle/#howto.data-access.configure-two-datasources)

> `firstDataSourceProperties` has to be flagged as `@Primary` so that the
> database initializer feature uses your copy (if you use the initializer).

こちらで詳しく解説されています:

  * [Spring Boot: 複数DB利用時に初期化が期待通りに行われない問題と解決法 - Rhythm & Biology](https://mythosil.hatenablog.com/entry/2019/07/28/181613)

対応としては、上記リンク先にもありますが、自前で `DataSourceInitializer` bean を定義すれば良いです。  
今回はテストコード向けなので、 `src/test/java` 配下のクラスとして次のような実装を行うことになるでしょう:

[code]

    import javax.sql.DataSource;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.jdbc.datasource.init.DataSourceInitializer;
    import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
    
    @Configuration
    public class MyTestConfig {
    
        // mysqlDataSource は、実際にはあなたが定義したH2データソースbean名
        @Bean
        public DataSourceInitializer mysqlDataSourceInitializer(@Qualifier("mysqlDataSource") final DataSource datasource) {
            final ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();
            resourceDatabasePopulator.addScript(new ClassPathResource("schema.sql"));
            // resourceDatabasePopulator.addScript(new ClassPathResource("data.sql"));
    
            final DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
            dataSourceInitializer.setDataSource(datasource);
            dataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);
            return dataSourceInitializer;
        }
    
    }
    
[/code]


CC BY-SA 4.0
2022-08-24T11:47:50.287
90735
2022-08-24T11:47:50.287
2808
90730
answer