【SpringBatch】メタテーブルを利用したくないとき

# 概要

- spring-batchではデフォルトでメタテーブルを使用し、ジョブの管理をしてくれる
- が、そのメタテーブルを利用したくない時の設定方法をまとめた

:::note info
SpringBoot3(SpringBatch5)については[こちら](https://hirabay.net/?p=610)をご覧ください🙇‍♂️
:::

https://hirabay.net/?p=610

# 実装方法

`BasicBatchConfigurer`を継承したクラスをBean登録してあげるだけ！

```java:NoMetaTableConfigurer.java
@Component
public class NoMetaTableConfigurer extends BasicBatchConfigurer {
    private final JobRepository jobRepository;
    private final JobExplorer jobExplorer;

    /**
     * constructor
     */
    public NoMetaTableConfigurer(
            BatchProperties properties,
            DataSource dataSource,
            TransactionManagerCustomizers transactionManagerCustomizers) {
        super(properties, dataSource, transactionManagerCustomizers);

        MapJobRepositoryFactoryBean repoFactory = new MapJobRepositoryFactoryBean(new ResourcelessTransactionManager());
        repoFactory.afterPropertiesSet();
        this.jobRepository = repoFactory.getObject();

        MapJobExplorerFactoryBean explFactory = new MapJobExplorerFactoryBean(repoFactory);
        explFactory.afterPropertiesSet();
        this.jobExplorer = explFactory.getObject();
    }

    /**
     * メタテーブルを使用しないようにするためにcreateJobRepositoryを独自に定義.
     */
    @Override
    protected JobRepository createJobRepository() {
        return this.jobRepository;
    }

    /**
     * メタテーブルを使用しないようにするためにcreateJobExplorerを独自に定義.
     */
    @Override
    public JobExplorer createJobExplorer() {
        return this.jobExplorer;
    }
}
```

`ResourcelessTransactionManager`と`MapJobRepositoryFactoryBean`,`MapJobExplorerFactoryBean`を使えばOK！

少し補足すると、
SpringBatchは`BatchConfigurer`の実装クラスによって動作を変えられるのですが、
デフォルトでは`BasicBatchConfigurer`を使用しているようでした。

そのため、BasicBatchConfigurerを継承し、メタテーブルを利用しなくする設定だけしてみました

# 実装方法（H2Db利用）

※2021/05追記

https://spring.pleiades.io/spring-batch/docs/current/api/org/springframework/batch/core/repository/support/MapJobRepositoryFactoryBean.html

> MapJobRepositoryFactoryBean
> 使用すべきではありません。

とのことなので、H2DBにメタデータを登録する方向性も検討してみました😇

ひとまずH2DBを依存に追加

```groovy:build.gradle
dependencies {
    ...
    runtimeOnly 'com.h2database:h2'
}
```

実装の方は、バッチ処理で使用するDataSourceとは別に、
メタデータ用のDataSourceを`@BatchDataSource`をつけてBean登録してあげればOK！

```java
@Configuration
public class MetadataConfiguration {
    @Bean
    @BatchDataSource
    public HikariDataSource metaDatasource() {
        var config = new HikariConfig();
        config.setJdbcUrl( "jdbc:h2:./h2db/meta" );
        config.setUsername("sa");
        config.setDriverClassName("org.h2.Driver");
        return new HikariDataSource( config );
    }

    @Bean
    @Primary
    public HikariDataSource dataSource(DataSourceProperties properties) {
        HikariDataSource dataSource = properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
        if (StringUtils.hasText(properties.getName())) {
            dataSource.setPoolName(properties.getName());
        }
        return dataSource;
    }
}
```

あ、メタテーブルの初期化の設定もお忘れなく

```yaml:application.yml
spring:
  batch:
    jdbc:
      initialize-schema: always
```

kubernetes等のコンテナで起動する類のバッチだと、毎回H2DBが初期構築されるはずなので、
`initialize-schema: always`で問題ないはず！
（もちろん永続化の要件がない前提）


# 自問自答QA

Q. どうしてメタテーブルを利用したくないの？

A. 利用したくないというよりも、利用できない…

> DBの権限でアプリケーションユーザーではテーブル作成をできなくしているのと、
spring-batchのバージョンアップ等でテーブルの変更があったときについていくのが大変

Q. じゃあspring-batchじゃなくてもよくない？

A. pushgatewayにメトリクス送信してくれる機能は使いたいのです😇

> 参考： [Pushgatewayを使ってSpringBatchのメトリクス収集](https://qiita.com/rhirabay/items/1982ac8d250e8b38f6b7)