2017-05-08 161 views
2

我正在使用一個應用程序,我需要將各種CSV文件轉換爲SQL數據庫。不同的CSV文件可能包含可變數量的列,但前三個文件之間始終保持一致。使用Spring Batch根據字段值將csv記錄寫入不同的SQL表

正在讀取文件,並且在拾取CSV之前創建新的數據庫表格,因爲我知道可能值的組合。然而,當涉及到作者(我正在使用JdbcBatchItemWriter)時,我需要根據這些列中的值引用新創建的表名,以確定數據對應的表 - 我不知道哪一行對應直到我看到每一行。

一些代碼來說明這一點:

public JdbcBatchItemWriter<Form> writer(@Value("#{jobParameters}") Map<String,Object> jobParameters) { 
    JdbcBatchItemWriter<Form> writer = new JdbcBatchItemWriter<Form>(); 
    ... 
    String parameters = getParameters(); 
    writer.setSql(String.format("INSERT INTO tableName VALUES (%s)", parameters.toString())); 

基本上,「表名」需要更新用於被處理的每一行。

似乎ItemSqlParameterSourceProvider和ItemPreparedStatementSetter是爲填充SQL查詢字符串中的值而設計的,但是我沒有找到任何可以獲取表名作爲參數的東西。因爲我無法訪問作者定義級別的每個項目,所以在準備好的語句放在一起之前,我無法替換該值。

我已經考慮過濾項目,但它們對於可能需要從CSV中輸入的未知數量的表格來說太亂了。有任何想法嗎?

+0

加上一個自定義的分類器A ClassifierCompositeItemWriter應配合您的需求 –

+0

謝謝 - 選擇使用這個並獲得更好的結果! – MattSteel

回答

0

寫你自己的作家,保持作家的地圖。每次出現新的表名時,您都可以實例化新的作者並將其存儲在此地圖中。

即時實例化一個JdbcBatchItemWriter沒什麼大不了的(它不一定是Spring bean)。

public static <T> ItemWriter<T> createDbItemWriter(DataSource ds, String sql, ItemPreparedStatementSetter<T> psSetter) { 
    JdbcBatchItemWriter<T> writer = new JdbcBatchItemWriter<>(); 

    writer.setDataSource(ds); 
    writer.setSql(sql); 
    writer.setItemPreparedStatementSetter(psSetter); 

    writer.afterPropertiesSet(); 
    return writer; 
} 

你的作家將不得不尋找某種方式魔神這個(注:此代碼沒有經過測試,它只是在這裏給你一個想法)

public class MyWriter extends ItemWriter<MyDto> { 

    private Map<String, JdbcBatchItemWriter<MyDto>> writersMaps = new HashMap<>(); 

    private JdbcBatchItemWriter<MyDto> getDbWriter(String tableName) throws Exception { 
     return writersMaps.putIfAbsent(tableName, createJdbcWriter(tableName)); 

    } 

    private JdbcBatchItemWriter<MyDto> createJdbcWriter(String tableName) { 
      JdbcBatchItemWriter<T> writer = new JdbcBatchItemWriter<>(); 

      // do your configuration 

      writer.afterPropertiesSet(); 
      return writer; 
    } 

    public void write(List<MyDto> items) throws Exception { 
     Map<String, List<MyDto>> groupedItems = 
       --> build a list for every targetTableName, put in a Map 


     for (Map.Entry<String, List<MyDto>> entry : groupedItems) { 
      getDbWriter(entry.getKey()).write(entry.getValue); 
     } 
    } 
} 
+0

感謝您的建議。我最終擴展了ClassifierCompositeItemWriter,這似乎是在按照您所描述的內容進行操作。 – MattSteel

相關問題