配置 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 方式手動進行裝配。