2017-03-20 134 views
0

我爲spring批處理使用java配置(spring-boot)。我有一個員工ID列表,對於每個ID,我需要運行一個查詢(如下圖),然後處理數據。使用JdbcCursorItemReader進行動態SQL查詢

select * from history where employee_id = ? 

我知道我們可以使用reader.setPreparedStatementSetter來動態設置上述SQL中的參數。但是,我不確定如何重複列表中每個員工ID的批處理過程。即使我將reader()標記爲@StepScope,讀者也只會被調用一次。 (即),批次只運行一次。任何幫助表示讚賞。

List employeeIds = new ArrayList(); 
    employeeIds.add(1); 
    employeeIds.add(2); 

    @Bean 
    @StepScope 
    public ItemReader<History> reader() { 
     JdbcCursorItemReader<History> databaseReader = new JdbcCursorItemReader<>(); 
     databaseReader.setSql("select * from history where employee_id = ?"); 
     databaseReader.setPreparedStatementSetter(..); 
     .... 

     return databaseReader; 
    } 


    @Bean 
    public Step step(StepBuilder stepBuilder){ 
     return stepBuilderFactory.get("sample"). 
       .reader(reader()) 
       .processor(processor()) 
       .writer(writer()) 
       .build(); 
    } 
+0

這是一種常見模式(http://docs.spring.io/spring-batch/reference/html/patterns.html#drivingQueryBasedItemReaders)。您的閱讀器從ID列表中返回ID,並且您當前的閱讀器必須轉換爲處理器 –

+0

嗯,可以將一個ItemReader映射到多個ItemProcessor嗎?因爲我希望ItemProcessor爲原始列表中的每個ID運行。 –

+0

是的,使用複合物品處理器(http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/item/support/CompositeItemProcessor.html) –

回答

2

所以首先,我不建議你這樣做。從理論上講,幾乎總是在實踐中,打開單個遊標比每次單獨查詢都更有效率。

「更好」的方法是將ID列表插入登臺表/驅動表(通常在先前的步驟中,每當您從原始源獲取該ID列表時),然後將查詢更改爲類似:

select * from history where employee_id in (select id from driving_table) 

或者,你可以在最低限度,至少你的查詢更改爲:

select * from history where employee_id in (?) 

和ID到它的列表傳遞(注意這裏一些數據庫限制查詢中的參數數量)。如果您的列表可能會超過此限制,則需要打開一個新的光標,並在列表中進行有效分頁。

+0

謝謝。該列表包含大約200000條記錄 - 因此「IN」不起作用。我可以使用JOIN來代替。 –

+0

絕對做加入。它將比將數據拉回僅僅是爲了再次查詢並且將減少不必要的I/O更好。 –