kagamihogeの日記

kagamihogeの日記です。

spring-batchのMapJobRepositoryFactoryBeanがDeprecated

従来、メタテーブルを永続化しなくするためにMapJobRepositoryFactoryBeanを使う事があったがspring-batch v5.0で削除予定になったようだ。

 * @deprecated as of v4.3 in favor or using the {@link JobRepositoryFactoryBean}
 * with an in-memory database. Scheduled for removal in v5.0.
 */
@Deprecated
public class MapJobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean {

その対策は上記javadocにある通りインメモリDB使ってね、て事らしい。他にデータソースが無ければ以下のようにH2などの依存性追加するだけでよい。springアプリケーションと共にH2も終了するので事実上永続化はしない。

  runtimeOnly 'com.h2database:h2'

複数データソースがある場合、というか、大抵はメタデータ用とメイン用の2つ以上のデータソースがあると思われる。この場合は、これまでの複数データソースの場合と同様、メタデータ用のH2データソースとそれ以外を用意すればよい。メタデータ用のデータソースには@BatchDataSourceを付与する。

import javax.sql.DataSource;

import org.h2.jdbcx.JdbcDataSource;
import org.springframework.boot.autoconfigure.batch.BatchDataSource;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration
public class DatasourceConfig {
    
    @Bean
    @Primary
    public DataSource primaryDs() {
        return DataSourceBuilder
                .create()
                .url("jdbc:oracle:thin:system/oracle@localhost:11521/XEPDB1")
                .username("system")
                .password("oracle")
                .build();
    }

    @BatchDataSource
    @Bean
    public DataSource dataSource() {
        JdbcDataSource ds = new JdbcDataSource();
        ds.setURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE");
        ds.setUser("sa");
        ds.setPassword("");
        return ds;
    }
}

上記はインメモリモードで起動しているが、ファイルモードも選択肢になると思う。コンテナ破棄でファイルも削除が最近は多いだろうし、インメモリで持ちたく無ければファイルもありだろうか?

ただ、常時起動の場合にはインメモリと言えどその影響が気になる。メモリ容量の圧迫もだが、デフォルトのDDLはインデックスを張らないので速度低下も懸念される。もっとも、相当貯めこまないと目に見える影響は出てこないだろうし、再起動という運用で回避も十分現実的と思う。

でまぁ、以下は完全に思いつきでマッタク検証してないのだけど。どうせメタデータ使わないならジョブ実行後に削除で良いんでないかな、と。

    @Bean
    public JobExecutionListener list(DataSource ds) {
        JdbcTemplate t = new JdbcTemplate(ds);
        
        return new JobExecutionListener() {
            
            @Override
            public void beforeJob(JobExecution jobExecution) {
            }
            
            @Override
            public void afterJob(JobExecution jobExecution) {
                // 他テーブルは省略
                t.update("delete from BATCH_JOB_EXECUTION_CONTEXT   where JOB_EXECUTION_ID  = " + jobExecution.getId());
            }
        };
    }