配置 JobRepository
如前所述,JobRepository
用于对 Spring Batch 中各种持久化的领域对象(例如 JobExecution
和 StepExecution
)执行基本的 CRUD 操作。许多主要的框架特性,如 JobLauncher
、Job
和 Step
都需要它。
-
Java
-
XML
使用 @EnableBatchProcessing
时,会为你提供一个 JobRepository
。本节介绍如何自定义它。可以通过 @EnableBatchProcessing
注解的属性来指定作业仓库的配置选项,如以下示例所示:
@Configuration
@EnableBatchProcessing(
dataSourceRef = "batchDataSource",
transactionManagerRef = "batchTransactionManager",
tablePrefix = "BATCH_",
maxVarCharLength = 1000,
isolationLevelForCreate = "SERIALIZABLE")
public class MyJobConfiguration {
// job definition
}
此处列出的所有配置选项都不是必需的。如果未设置,则使用前面显示的默认值。最大 varchar
长度默认为 2500
,这是示例 schema 脚本中长 VARCHAR
列的长度。
批处理命名空间抽象了 JobRepository
实现及其协作者的许多实现细节。但是,仍然有一些配置选项可用,如以下示例所示:
<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
,这是示例 schema 脚本中长 VARCHAR
列的长度。
JobRepository 的事务配置
如果使用命名空间或提供的 FactoryBean
,则会在仓库周围自动创建事务通知。这是为了确保批处理元数据(包括故障后重启所需的状态)能够正确持久化。如果仓库方法不是事务性的,框架的行为将是不确定的。create*
方法属性中的隔离级别是单独指定的,以确保当作业启动时,如果两个进程试图同时启动同一个作业,只有一个会成功。该方法的默认隔离级别是 SERIALIZABLE
,这相当严格。READ_COMMITTED
通常效果一样好。如果两个进程不太可能以这种方式发生冲突,则 READ_UNCOMMITTED
也是可以的。但是,由于对 create*
方法的调用非常短暂,只要数据库平台支持,SERIALIZED
不太可能引起问题。但是,你可以覆盖此设置。
-
Java
-
XML
以下示例演示如何在 Java 中覆盖隔离级别:
@Configuration
@EnableBatchProcessing(isolationLevelForCreate = "ISOLATION_REPEATABLE_READ")
public class MyJobConfiguration {
// job definition
}
以下示例演示如何在 XML 中覆盖隔离级别:
<job-repository id="jobRepository"
isolation-level-for-create="REPEATABLE_READ" />
如果未使用命名空间,则还必须使用 AOP 配置仓库的事务行为。
-
Java
-
XML
以下示例演示如何在 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 中配置仓库的事务行为:
<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-tx
和 spring-aop
(或整个 Spring)。
更改表前缀
JobRepository
的另一个可修改属性是元数据表的表前缀。默认情况下,它们都以前缀 BATCH_
开头。BATCH_JOB_EXECUTION
和 BATCH_STEP_EXECUTION
是两个示例。但是,修改此前缀可能有以下原因。如果需要将 schema 名称添加到表名称前,或者在同一个 schema 中需要多组元数据表,则需要更改表前缀。
-
Java
-
XML
以下示例演示如何在 Java 中更改表前缀:
@Configuration
@EnableBatchProcessing(tablePrefix = "SYSTEM.TEST_")
public class MyJobConfiguration {
// job definition
}
以下示例演示如何在 XML 中更改表前缀:
<job-repository id="jobRepository"
table-prefix="SYSTEM.TEST_" />
考虑到上述更改,对元数据表的每个查询都将以 SYSTEM.TEST_
为前缀。BATCH_JOB_EXECUTION
将被称为 SYSTEM.TEST_JOB_EXECUTION
。
只有表前缀是可配置的。表名和列名不可配置。 |
仓库中的非标准数据库类型
如果你使用的数据库平台不在支持的平台列表中,如果 SQL 变体足够接近,你可能可以使用其中一种受支持的类型。为此,你可以使用原始的 JobRepositoryFactoryBean
,而不是命名空间快捷方式,并用它将数据库类型设置为最接近的匹配项。
-
Java
-
XML
以下示例演示如何在 Java 中使用 JobRepositoryFactoryBean
将数据库类型设置为最接近的匹配项:
@Bean
public JobRepository jobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource);
factory.setDatabaseType("db2");
factory.setTransactionManager(transactionManager);
return factory.getObject();
}
以下示例演示如何在 XML 中使用 JobRepositoryFactoryBean
将数据库类型设置为最接近的匹配项:
<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 方式手动进行装配。