我正在使用一个应用程序,我需要将各种CSV文件转换为SQL数据库。不同的CSV文件可能包含可变数量的列,但前三个文件在文件之间始终保持一致。
正在读取文件,并且在拾取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()));
基本上,'tableName'需要为每个处理的行进行更新。
似乎ItemSqlParameterSourceProvider和ItemPreparedStatementSetter是为在SQL查询字符串中填充值而设计的,但是我没有找到任何可以将表名作为参数的内容。因为我无法访问编写器定义级别的每个项目,所以在准备好的语句放在一起之前,我无法替换该值。
我考虑在项目到达之前对其进行过滤,但对于可能需要从CSV输入的未知数量的表格来说,它太杂乱了。有什么想法吗?
答案 0 :(得分: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);
}
}
}