配置JobRepository

如前所述,JobRepository 用于Spring Batch中各种持久化领域对象的CRUD操作,例如JobExecutionStepExecution。许多主要的框架特性都需要它,例如JobLauncherJobStep

  • Java

  • XML

使用@EnableBatchProcessing时,会为您提供一个JobRepository。本节介绍如何自定义它。作业存储库的配置选项可以通过@EnableBatchProcessing注解的属性指定,如下例所示:

Java 配置
@Configuration
@EnableBatchProcessing(
		dataSourceRef = "batchDataSource",
		transactionManagerRef = "batchTransactionManager",
		tablePrefix = "BATCH_",
		maxVarCharLength = 1000,
		isolationLevelForCreate = "SERIALIZABLE")
public class MyJobConfiguration {

   // job definition

}

此处列出的配置选项都不是必需的。如果未设置,则使用前面显示的默认值。最大varchar长度默认为2500,这是示例模式脚本中长VARCHAR列的长度。

批处理命名空间抽象了许多JobRepository实现及其协作者的实现细节。但是,仍然有一些可用的配置选项,如下例所示:

XML配置
<job-repository id="jobRepository"
    data-source="dataSource"
    transaction-manager="transactionManager"
    isolation-level-for-create="SERIALIZABLE"
    table-prefix="BATCH_"
	max-varchar-length="1000"/>

除了id之外,前面列出的配置选项都不是必需的。如果未设置,则使用前面显示的默认值。max-varchar-length默认为2500,这是示例模式脚本中长VARCHAR列的长度。

JobRepository的事务配置

如果使用命名空间或提供的FactoryBean,则会自动在存储库周围创建事务性建议。这是为了确保批处理元数据(包括故障后重启所需的状态)能够正确持久化。如果存储库方法不是事务性的,框架的行为将无法很好地定义。create*方法属性中的隔离级别是单独指定的,以确保在启动作业时,如果两个进程试图同时启动同一个作业,只有一个进程会成功。该方法的默认隔离级别是SERIALIZABLE,这相当严格。READ_COMMITTED通常也能很好地工作。如果两个进程不太可能以这种方式发生冲突,则READ_UNCOMMITTED是可以的。但是,由于对create*方法的调用非常短,因此只要数据库平台支持,SERIALIZED不太可能造成问题。但是,您可以覆盖此设置。

  • Java

  • XML

以下示例显示如何在Java中覆盖隔离级别:

Java 配置
@Configuration
@EnableBatchProcessing(isolationLevelForCreate = "ISOLATION_REPEATABLE_READ")
public class MyJobConfiguration {

   // job definition

}

以下示例显示如何在XML中覆盖隔离级别:

XML配置
<job-repository id="jobRepository"
                isolation-level-for-create="REPEATABLE_READ" />

如果不使用命名空间,则还必须使用AOP配置存储库的事务行为。

  • Java

  • XML

以下示例显示如何在Java中配置存储库的事务行为:

Java 配置
@Bean
public TransactionProxyFactoryBean baseProxy() {
	TransactionProxyFactoryBean transactionProxyFactoryBean = new TransactionProxyFactoryBean();
	Properties transactionAttributes = new Properties();
	transactionAttributes.setProperty("*", "PROPAGATION_REQUIRED");
	transactionProxyFactoryBean.setTransactionAttributes(transactionAttributes);
	transactionProxyFactoryBean.setTarget(jobRepository());
	transactionProxyFactoryBean.setTransactionManager(transactionManager());
	return transactionProxyFactoryBean;
}

以下示例显示如何在XML中配置存储库的事务行为:

XML配置
<aop:config>
    <aop:advisor
           pointcut="execution(* org.springframework.batch.core..*Repository+.*(..))"/>
    <advice-ref="txAdvice" />
</aop:config>

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="*" />
    </tx:attributes>
</tx:advice>

您可以几乎原样使用前面的片段,几乎无需任何更改。还记得包含适当的命名空间声明,并确保spring-txspring-aop(或整个Spring)都在类路径上。

更改表前缀

JobRepository的另一个可修改属性是元数据表的表前缀。默认情况下,它们都以BATCH_开头。BATCH_JOB_EXECUTIONBATCH_STEP_EXECUTION是两个例子。但是,可能有理由修改此前缀。如果需要将模式名称添加到表名前缀,或者如果需要在同一个模式中使用多个元数据表,则需要更改表前缀。

  • Java

  • XML

以下示例显示如何在Java中更改表前缀:

Java 配置
@Configuration
@EnableBatchProcessing(tablePrefix = "SYSTEM.TEST_")
public class MyJobConfiguration {

   // job definition

}

以下示例显示如何在XML中更改表前缀:

XML配置
<job-repository id="jobRepository"
                table-prefix="SYSTEM.TEST_" />

鉴于之前的更改,对元数据表的每个查询都以SYSTEM.TEST_为前缀。BATCH_JOB_EXECUTION被称为SYSTEM.TEST_JOB_EXECUTION

只有表前缀是可配置的。表名和列名不可配置。

存储库中的非标准数据库类型

如果您使用的数据库平台不在受支持的平台列表中,如果SQL变体足够接近,则您可以使用其中一种受支持的类型。为此,您可以使用原始的JobRepositoryFactoryBean而不是命名空间快捷方式,并使用它将数据库类型设置为最接近的匹配项。

  • Java

  • XML

以下示例演示如何在Java中使用JobRepositoryFactoryBean将数据库类型设置为最接近的匹配项。

Java 配置
@Bean
public JobRepository jobRepository() throws Exception {
    JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
    factory.setDataSource(dataSource);
    factory.setDatabaseType("db2");
    factory.setTransactionManager(transactionManager);
    return factory.getObject();
}

以下示例演示如何在XML中使用JobRepositoryFactoryBean将数据库类型设置为最接近的匹配项。

XML配置
<bean id="jobRepository" class="org...JobRepositoryFactoryBean">
    <property name="databaseType" value="db2"/>
    <property name="dataSource" ref="dataSource"/>
</bean>

如果未指定数据库类型,则JobRepositoryFactoryBean会尝试从DataSource自动检测数据库类型。平台之间的主要区别主要在于递增主键的策略,因此通常还需要覆盖incrementerFactory(通过使用Spring框架中的标准实现之一)。

如果即使那样也不起作用,或者您没有使用RDBMS,那么唯一的选择可能是实现SimpleJobRepository依赖的各种Dao接口,并以普通的Spring方式手动连接一个。