[英]Spring Batch : Write a List to a database table using a custom batch size
背景
我有一個Spring 批處理作業,其中:
FlatFileItemReader
- 從文件中一次讀取一行ItemProcesor
- 將文件中的行轉換為List<MyObject>
並返回List
。 也就是說,文件中的每一行都分解為一個List<MyObject>
(文件中的 1 行轉換為許多 output 行)。ItemWriter
- 將List<MyObject>
寫入數據庫表。 (我使用此實現將收到的來自處理器和委托的列表解包到JdbcBatchItemWriter
)問題
MyObject
實例的List
。JdbcBatchItemWriter
最終會將包含 100000 個對象的整個List
寫入數據庫。 我的問題是: JdbcBatchItemWriter
不允許自定義批量大小。 出於所有實際目的,該步驟的批大小 = 提交間隔。 考慮到這一點, Spring Batch中是否有另一個ItemWriter
實現,它允許寫入數據庫並允許可配置的批量大小? 如果沒有,go 如何自己編寫自定義作家來實現這一目標?
我看不到在JdbcBatchItemWriter
上設置批處理大小的明顯方法。 但是,您可以擴展編寫器並使用自定義BatchPreparedStatementSetter
來指定批處理大小。 這是一個簡單的例子:
public class MyCustomWriter<T> extends JdbcBatchItemWriter<T> {
@Override
public void write(List<? extends T> items) throws Exception {
namedParameterJdbcTemplate.getJdbcOperations().batchUpdate("your sql", new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
// set values on your sql
}
@Override
public int getBatchSize() {
return items.size(); // or any other value you want
}
});
}
}
示例中的StagingItemWriter也是如何使用自定義BatchPreparedStatementSetter
的示例。
Mahmoud Ben Hassine的答案和評論幾乎涵蓋了解決方案的所有方面,並且是公認的答案。
如果有人感興趣,這是我使用的實現:
public class JdbcCustomBatchSizeItemWriter<W> extends JdbcDaoSupport implements ItemWriter<W> {
private int batchSize;
private ParameterizedPreparedStatementSetter<W> preparedStatementSetter;
private String sqlFileLocation;
private String sql;
public void initReader() {
this.setSql(FileUtilties.getFileContent(sqlFileLocation));
}
public void write(List<? extends W> arg0) throws Exception {
getJdbcTemplate().batchUpdate(sql, Collections.unmodifiableList(arg0), batchSize, preparedStatementSetter);
}
public void setBatchSize(int batchSize) {
this.batchSize = batchSize;
}
public void setPreparedStatementSetter(ParameterizedPreparedStatementSetter<W> preparedStatementSetter) {
this.preparedStatementSetter = preparedStatementSetter;
}
public void setSqlFileLocation(String sqlFileLocation) {
this.sqlFileLocation = sqlFileLocation;
}
public void setSql(String sql) {
this.sql = sql;
}
}
筆記:
Collections.unmodifiableList
可以避免任何顯式轉換的需要。sqlFileLocation
來指定一個包含 sql 的外部文件,而FileUtilities.getfileContents
只返回這個 sql 文件的內容。 這可以跳過,也可以在創建 bean 時直接將sql
傳遞給 class。我不會這樣做的。 它提出了可重啟性的問題。 相反,修改您的閱讀器以生成單個項目,而不是讓您的處理器接收 object 並返回一個列表。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.