2016-09-07 82 views
1

我是春季批次新手。我需要在春季批量實現的任務如下:春季批次:多個項目讀者在一個步驟

  1. 需要從數據庫中讀取一些元數據。
  2. 基於這個元數據,我需要讀取一些文件。
  3. 經過一些處理後,需要將這些值從文件寫入數據庫。

我的查詢有以下幾種:

一個。對於第一個要求,我需要將整個結果集映射到一個對象,其中與Person相關的數據位於一個表中,並且與寵物相關的數據位於另一個表中並通過人員ID加入。

public class PersonPetDetails { 

    private String personName; 
    private String personAddr; 

    private int personAge; 

    private List<Pet> pets; 

爲此,我編寫了一個擴展了JdbcCursorItemReader的自定義Item讀取器。

public class CustomJDBCCusrorItemReader<T> extends JdbcCursorItemReader<T> { 

    private ResultSetExtractor<T> resultSetExtractor; 


    public void setResultSetExtractor(ResultSetExtractor<T> resultSetExtractor) { 
     this.resultSetExtractor = resultSetExtractor; 
    } 

    @Override 
    public void afterPropertiesSet() throws Exception { 
     setVerifyCursorPosition(false); 
     Assert.notNull(getDataSource(), "DataSource must be provided"); 
     Assert.notNull(getSql(), "The SQL query must be provided"); 
     Assert.notNull(resultSetExtractor, "ResultSetExtractor must be provided"); 
    } 


    @Override 
    protected T readCursor(ResultSet rs, int currentRow) throws SQLException {  
     return resultSetExtractor.extractData(rs); 
    } 
} 

這是達到我的要求的正確方法嗎?或者有更好的方法嗎?

b。 AFAIK,在春季批次中,只有一個讀者,沒有一個作家,這是不可能的。因此,我不能在工作的另一個步驟中調用另一組讀者。那麼,我怎樣才能在一個步驟中調用多個閱讀器?

c。另外,基於某些條件,我可能需要調用第三套Reader。我如何有條件地在一個步驟中呼叫讀者?

感謝您閱讀我的文章。我知道它很長。任何幫助深表感謝。另外,我想一個示例代碼片段可以幫助我更好地理解這一點。 :)

+0

我的第一個建議是將你的問題分爲多個問題,因爲點a)b)和c)是完全不相關的。 a)可以使用擴展代理來解析 b)可以在某些情況下使用多個閱讀器(例如,http://stackoverflow.com/questions/21304364/spring-batch-job-read-from-multiple-database,例如) c)使用JobExecutionDecider解析SB中的條件 –

回答

1

我會建議如下

高級設計:

  1. 分區程序 它將處理人員的名單。注意:此時沒有任何寵物數據被拉出。

  2. 閱讀器 它會得到屬於一個人的寵物列表。注意:Reader只會返回一個Pet特定的列表。

  3. 處理器 基於Pet-Person,您將根據您的需求進行處理。

  4. 作家 根據您的要求寫入數據庫。

低級代碼片段:

  1. 分區程序

公共類PetPersonPartitioner實現分區程序{

@Autowired 
private PersonDAO personDAO; 

@Override 
public Map<String, ExecutionContext> partition(int gridSize) { 

    Map<String, ExecutionContext> queue = new HashMap<String, ExecutionContext>(); 

    List<Person> personList = this.personDAO.getAllPersons(); 
    for (Person person : personList) { 

     ExecutionContext ec = new ExecutionContext(); 
     ec.put("person", person); 
     ec.put("personId", person.getId()); 

     queue.put(person.getId(), ec); 
    } 

    return queue; 
} 

}

  • 讀卡器

    <bean id="petByPersonIdRowMapper" class="yourpackage.PetByPersonIdRowMapper" /> 
    
    <bean id="petByPesonIdStatementSetter" scope="step" 
         class="org.springframework.batch.core.resource.ListPreparedStatementSetter"> 
        <property name="parameters"> 
         <list> 
          <value>#{stepExecutionContext['personId']}</value> 
         </list> 
        </property> 
    </bean> 
    
  • public class PetByPersonIdRowMapper implements RowMapper<PersonPetDetails> { 
        @Override 
        public BillingFeeConfigEntity mapRow(ResultSet rs, int rowNum) throws SQLException { 
         PersonPetDetails record = new PersonPetDetails(); 
    
         record.setPersonId(rs.getLong("personId")); 
         record.setPetId(rs.getLong("petid"); 
         ... 
         ... 
    } 
    
  • 處理器 您可以繼續處理每個PersonPetDetails對象。
  • +0

    我想要一個PersonPetDetails對象並基於該對象,我將不得不在後續步驟中讀取多個文件。你認爲一個tasklet會更適合而不是分區器嗎? –

    +0

    分區程序帶來了多線程處理的好處。 –