Configuring a JobRepository

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

Java

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

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

   // job definition

}

此处列出的配置选项均不是必需的。如果未设置,则使用前面显示的默认值。最大 varchar 长度默认为 2500,这是 sample schema scripts 中的长 VARCHAR 列的长度

XML

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

XML Configuration
<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,这是 sample schema scripts 中的长 VARCHAR 列的长度。

Transaction Configuration for the JobRepository

如果使用命名空间或提供的 FactoryBean,则会自动在存储库周围创建事务劝告。这是为了确保批处理元数据(包括故障后重新启动所必需的状态)被正确地持久化。如果存储库方法不是事务性的,框架的行为没有明确定义。create* 方法属性中的隔离级别被单独指定,以确保在启动作业时,如果两个进程同时尝试启动同一个作业,则只有其中一个会成功。该方法的默认隔离级别为 SERIALIZABLE,这是非常激进的。READ_COMMITTED 通常效果一样好。如果两个进程不太可能以这种方式发生冲突,则 READ_UNCOMMITTED 就行了。然而,因为对 create* 方法的调用相当短,只要数据库平台支持它,SERIALIZED 就不太可能引起问题。然而,你可以覆盖此设置。

Java

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

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

   // job definition

}
XML

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

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

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

Java

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

Java Configuration
@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 中配置存储库的事务行为:

XML Configuration
<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)在类路径中。

Changing the Table Prefix

JobRepository 的其它可修改属性是元数据表的表前缀。默认情况下,它们都以 BATCH_ 为前缀。BATCH_JOB_EXECUTIONBATCH_STEP_EXECUTION 是两个示例。但是,有一些潜在原因可以修改此前缀。如果架构名称需要添加为表名称的前缀,或者同一个架构内需要多个元数据表集合,则需要更改表前缀。

Java

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

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

   // job definition

}
XML

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

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

考虑到上述更改,对元数据表的每个查询都以 SYSTEM.TEST_ 为前缀。BATCH_JOB_EXECUTION 被称为 SYSTEM.TEST_JOB_EXECUTION

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

Non-standard Database Types in a Repository

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

Java

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

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

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

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

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

如果即使这样还不奏效,或者你没有使用 RDBMS,则唯一的选项可能是实现 SimpleJobRepository 所依赖的各种 Dao 接口,并通过正常的 Spring 方式手动连接一个。