天天看點

Spring Batch 2.1.8 中文文檔(七)

4.2 Confinguring a JobRepository

之前說過,JobRepository是基本的CRUD操作,用于持久化Spring Batch的領域對象(如JobExecution,StepExecution)。許多主要的架構元件(如JobLauncher,Job,Step)都需要使用JobRepositor。batch的命名空間中已經抽象走許多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列的長度,在sample schema scripts中用于存儲類似于exit code這些描述的字元。如果你不修改schema并且也不會使用多位元組編碼,那麼就不用修改它。

4.2.1 Transaction Configuration for the JobRepository

如果使用了namespace,repository會被自動加上事務控制,這是為了確定批處理操作中繼資料以及失敗後重新開機的狀态能夠被準确的持久化,如果repository的方法不是事務控制的,那麼架構的行為就不能夠被準确的定義。create*方法的隔離級别會被單獨指定,為了確定任務啟動時,如果兩個操作嘗試在同時啟動相同的任務,那麼隻有一個任務能夠被成功啟動。這種方法預設的隔離級别是SERIALIZABLE,這是相當激進的做法:READ_COMMITED能達到同樣效果;如果兩個操作不以這種方式沖突的話READ_UNCOMMITED也能很好工作。但是,由于調用create*方法是相當短暫的,隻要資料庫支援,就不會對性能産生太大影響。它也能被這樣覆寫:

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

如果factory的namespace沒有被使用,那麼可以使用AOP來配置repository的事務行為:

<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>
           

這個配置片段基本上可以不做修改直接使用。記住加上适當的namespace描述去確定spring-tx和spring-aop(或是整個spring)都在classpath中。

4.2.2 Changing the Table Prefix

JobRepository可以修改的另一個屬性是中繼資料表的表字首。預設是以BATCH_開頭,BATCH_JOB_EXECUTION和BATCH_STEP_EXECUTION就是兩個例子。但是,有一些潛在的原因可能需要修改這個字首。例如schema的名字需要被預置到表名中,或是不止一組的中繼資料表需要放在同一個schema中,那麼表字首就需要改變:

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

按照上面的修改配置,每一個中繼資料查詢都會帶上SYSTEM.TEST_的字首,BATCH_JOB_EXECUTION将會被更換為SYSTEM.TEST_JOB_EXECUTION。

備注:表名字首是可配置的,表名和列名是不可配置的。

4.2.3 In-Memory Repository

有的時候不想把你的領域對象持久化到資料庫中,可能是為了運作的更快速,因為每次送出都要開銷額外的時間;也可能并不需要為特定任務儲存狀态。那麼Spring Batch還提供了記憶體Map版本的job倉庫:

<bean id="jobRepository" 
  class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
    <property name="transactionManager" ref="transactionManager"/>
</bean>
           

需要注意的是記憶體Repository是輕量的并且不能在兩個Jvm執行個體間重新開機任務,也不能允許同時啟動帶有相同參數的任務,不适合在多線程或是一個本地分片任務的場景下使用。而使用資料庫版本的Repository則能夠擁有這些特性。

但是也需要定義一個事務管理器,因為倉庫需要復原語義,也因為商業邏輯要求事務性(類似于RDBMS通路)。經過測試許多人覺得

ResourcelessTransactionManager是很有用的。

4.2.4 Non-standard Database Types in Repository

如果使用的資料庫平台不在支援的平台清單中,在SQL類型類似的情況下你可以使用近似的資料庫類型。使用原生的

JobRepositoryFactoryBean來取代命名空間縮寫後設定一個相似的資料庫類型:

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

(如果沒有指定databaseType,

JobRepositoryFactoryBean會通過datasource自動檢測資料庫的類型).平台之間的主要不同之處在于主鍵的計算政策,也可能需要覆寫

incrementerFactory(使用Spring Framework提供的标準實作)。

如果它還不能工作,或是你不使用RDBMS,那麼唯一的選擇是讓SimpleJobRepository使用spring方式依賴并且綁定在手工實作的各種dao接口上。

4.3 Configuring a JobLauncher

JobLauncher最基本的實作是

SimpleJobLauncher,它唯一的依賴是通過

JobRepository擷取一個execution:

<bean id="jobLauncher"
      class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
    <property name="jobRepository" ref="jobRepository" />
</bean>
           

一旦擷取到

JobExecution,那麼可以通過執行Job的方法,最終将

JobExecution傳回給調用者:

Spring Batch 2.1.8 中文文檔(七)

從排程啟動時,整個序列能夠很好的直接工作,但是,從HTTP請求中啟動則會出現一些問題。在這種場景中,啟動任務需要異步操作,讓

SimpleJobLauncher能夠立刻傳回結果給調用者,如果讓HTTP請求一直等待很長時間知道批處理任務完成擷取到執行結果,是很糟糕的操作體驗。一個流程如下圖所示:

Spring Batch 2.1.8 中文文檔(七)

通過配置

TaskExecutor可以很容易的将

SimpleJobLauncher配置成異步操作:

<bean id="jobLauncher"
      class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
    <property name="jobRepository" ref="jobRepository" />
    <property name="taskExecutor">
        <bean class="org.springframework.core.task.SimpleAsyncTaskExecutor" />
    </property>
</bean>
           

TaskExecutor接口的任何實作都能夠用來控制job的異步執行。