配置 JobRepository
如前文所述,JobRepository 用於對 Spring Batch 中各種持久化領域物件(如 JobExecution 和 StepExecution)執行基本的 CRUD 操作。它是許多主要框架特性(如 JobOperator、Job 和 Step)所必需的。
配置無資源 JobRepository
JobRepository 介面最簡單的實現是 ResourcelessJobRepository。此實現不使用或儲存批處理元資料。它適用於不需要可重新啟動性且不以任何方式涉及執行上下文的用例(例如透過執行上下文在步驟之間共享資料,或分割槽元資料透過執行上下文在管理器和工作器之間共享的分割槽步驟等)。此實現持有執行單個作業(即 1 個作業例項 + 1 個作業執行 + N 個步驟執行)的最小狀態。它適用於在自己的 JVM 中執行的一次性作業。此作業倉庫支援事務性步驟和非事務性步驟(與 ResourcelessTransactionManager 結合使用)。
| 此實現是非執行緒安全的,並且不應在任何併發環境中使用。 |
預設情況下,當使用 @EnableBatchProcessing 或 DefaultBatchConfiguration 時,會為您提供一個 ResourcelessJobRepository。
配置 JDBC JobRepository
-
Java
-
XML
當使用 @EnableBatchProcessing 時,會為您提供一個 ResourcelessJobRepository。本節介紹如何自定義它。Spring Batch 提供了兩個基於資料庫的 JobRepository 介面實現:一個 JDBC 實現(可與任何 JDBC 相容資料庫一起使用)和一個 MongoDB 實現。這兩個實現分別由 @EnableJdbcJobRepository 和 @EnableMongoJobRepository 註解提供。
以下示例展示瞭如何透過 @EnableJdbcJobRepository 註解的屬性自定義基於 JDBC 的作業倉庫
@Configuration
@EnableBatchProcessing
@EnableJdbcJobRepository(
dataSourceRef = "batchDataSource",
transactionManagerRef = "batchTransactionManager",
tablePrefix = "BATCH_",
maxVarCharLength = 1000,
isolationLevelForCreate = "SERIALIZABLE")
public class MyJobConfiguration {
// job definition
}
此處列出的所有配置選項都不是必需的。如果未設定,則使用前面顯示的預設值。最大 varchar 長度預設為 2500,這是示例模式指令碼中長 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,這是示例模式指令碼中長 VARCHAR 列的長度。
配置 MongoDB JobRepository
與基於 JDBC 的 JobRepository 類似,基於 MongoDB 的 JobRepository 需要一些集合來儲存批處理元資料。這些集合定義在 spring-batch-core jar 的 org/springframework/batch/core/schema-mongodb.jsonl 中。與基於 JDBC 的 JobRepository 一樣,您需要在執行任何作業之前在 MongoDB 資料庫中建立這些集合。
此外,由於在 MongoDB 文件的欄位名中使用 . 是不建議的,您需要自定義 MongoJobRepositoryFactoryBean 使用的 MongoTemplate,以將欄位名中的 . 替換為另一個字元(例如 _)。您可以透過自定義 MongoTemplate 使用的 MappingMongoConverter 來實現。以下示例展示瞭如何在 Java 配置中進行此操作
@Bean
public MongoTemplate mongoTemplate(MongoDatabaseFactory mongoDatabaseFactory) {
MongoTemplate template = new MongoTemplate(mongoDatabaseFactory);
MappingMongoConverter converter = (MappingMongoConverter) template.getConverter();
converter.setMapKeyDotReplacement("_");
return template;
}
JobRepository 的事務配置
如果使用名稱空間或提供的 FactoryBean,則會自動在倉庫周圍建立事務性通知。這是為了確保批處理元資料(包括故障後重新啟動所需的狀態)正確持久化。如果倉庫方法不是事務性的,框架的行為將不明確。create* 方法屬性中的隔離級別單獨指定,以確保在啟動作業時,如果有兩個程序同時嘗試啟動同一個作業,只有一個能成功。該方法的預設隔離級別是 SERIALIZABLE,這非常激進。READ_COMMITTED 通常效果同樣好。如果兩個程序不太可能以這種方式發生衝突,READ_UNCOMMITTED 也可以。然而,由於對 create* 方法的呼叫非常短,只要資料庫平臺支援,SERIALIZED 不太可能引起問題。但是,您可以覆蓋此設定。
-
Java
-
XML
以下示例展示瞭如何在 Java 中覆蓋隔離級別
@Configuration
@EnableBatchProcessing
@EnableJdbcJobRepository(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 是兩個例子。但是,修改此字首可能有一些原因。如果需要將模式名稱前置到表名,或者在同一個模式中需要多組元資料表,則需要更改表字首。
-
Java
-
XML
以下示例展示瞭如何在 Java 中更改表字首
@Configuration
@EnableBatchProcessing
@EnableJdbcJobRepository(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 變體足夠接近,您可以使用其中一種受支援的型別。為此,您可以使用原始的 JdbcJobRepositoryFactoryBean 而不是名稱空間快捷方式,並將其用於將資料庫型別設定為最接近的匹配項。
-
Java
-
XML
以下示例展示瞭如何在 Java 中使用 JdbcJobRepositoryFactoryBean 將資料庫型別設定為最接近的匹配項
@Bean
public JobRepository jobRepository() throws Exception {
JdbcJobRepositoryFactoryBean factory = new JdbcJobRepositoryFactoryBean();
factory.setDataSource(dataSource);
factory.setDatabaseType("db2");
factory.setTransactionManager(transactionManager);
return factory.getObject();
}
以下示例展示瞭如何在 XML 中使用 JdbcJobRepositoryFactoryBean 將資料庫型別設定為最接近的匹配項
<bean id="jobRepository" class="org...JdbcJobRepositoryFactoryBean">
<property name="databaseType" value="db2"/>
<property name="dataSource" ref="dataSource"/>
</bean>
如果未指定資料庫型別,JdbcJobRepositoryFactoryBean 會嘗試從 DataSource 自動檢測資料庫型別。不同平臺之間的主要區別主要體現在主鍵遞增策略上,因此通常還需要覆蓋 incrementerFactory(透過使用 Spring Framework 中的標準實現之一)。
如果即使那樣也不起作用,或者如果您不使用 RDBMS,唯一的選擇可能是實現 SimpleJobRepository 所依賴的各種 Dao 介面,並以正常的 Spring 方式手動連線一個。