配置 JobRepository

如前所述,JobRepository 用於對 Spring Batch 中各種持久化的領域物件(例如 JobExecutionStepExecution)執行基本的 CRUD 操作。許多主要的框架特性,如 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,這是示例 schema 指令碼中長 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,這是示例 schema 指令碼中長 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 是兩個示例。但是,修改此字首可能有以下原因。如果需要將 schema 名稱新增到表名稱前,或者在同一個 schema 中需要多組元資料表,則需要更改表字首。

  • 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 Framework 中的標準實現之一)。

如果即使這樣也不奏效,或者如果你沒有使用 RDBMS,唯一的選擇可能是實現 SimpleJobRepository 依賴的各種 Dao 介面,並以正常的 Spring 方式手動進行裝配。