通常,从csv文件读取然后写入数据库,我们将每一行映射到POJO(域对象)。但是当csv文件发生变化时如何做到这一点?这意味着,有许多不同格式的csv文件,我不想为每个文件编写POJO。
我可以想到两种方法来处理它。首先动态生成POJO类,但是如何?其次,使用PassThroughFieldSetMapper
和PassThroughItemProcessor
,但如何在JdbcBatchItemWriter
中为SQL设置参数?
答案 0 :(得分:1)
您可以使其相对可配置,但在一天结束时,您最终需要将文件中的字段映射到数据库的列某处。
你可以从这样的事情开始,然后弄清楚如何动态定义你的fieldMap
bean ...你还可以更进一步,包括数据库中每列的数据类型。
<bean id="csvReader" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="#{jobParameters['FILENAME']}" />
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="names" value="#{fieldMap.keySet()}" />
</bean>
</property>
<property name="fieldSetMapper">
<bean class="org.springframework.batch.item.file.mapping.PassThroughFieldSetMapper" />
</property>
</bean>
</property>
</bean>
<bean id="jdbcWriter" class="org.springframework.batch.item.database.JdbcBatchItemWriter">
<property name="dataSource" ref="dataSource" />
<property name="sql" ref="sqlString" />
<property name="itemSqlParameterSourceProvider">
<bean class="org.sample.sql.FieldSetItemSqlParameterSourceProvider" />
</property>
</bean>
<bean id="sqlString" class="org.sample.factory.SqlFactoryBean">
<property name="table" value="MY_TABLE" />
<property name="schema" value="${my.schema}" />
<property name="fieldMap" ref="fieldMap" />
</bean>
<util:map id="fieldMap">
<entry key="firstName" value="FIRST_NAME" />
<entry key="lastName" value="LAST_NAME" />
<entry key="email" value="EMAIL" />
<entry key="birthDate" value="BIRTH_DATE" />
</util:map>
<强>的FactoryBean 强>
public class SqlFactoryBean implements FactoryBean<String> {
private String table;
private String schema;
private Map<String, String> fieldMap;
@Override
public String getObject() throws Exception {
Assert.isTrue((fieldMap != null) && (fieldMap.size() > 0));
final StringBuilder sb = new StringBuilder("INSERT INTO " + schema + "." + table + " ");
final Iterator<Entry<String, String>> iterator = fieldMap.entrySet().iterator();
Entry<String, String> entry = iterator.next();
final StringBuilder columnBuilder = new StringBuilder("(" + entry.getValue());
final StringBuilder paramBuilder = new StringBuilder("(" + entry.getKey());
while (iterator.hasNext()) {
entry = iterator.next();
columnBuilder.append("," + entry.getValue());
paramBuilder.append("," + entry.getKey());
}
columnBuilder.append(")");
paramBuilder.append(")");
sb.append(columnBuilder.toString());
sb.append(" values ");
sb.append(paramBuilder.toString());
return sb.toString();
}
}
<强> ItemSqlParameterSourceProvider 强>
public class FieldSetItemSqlParameterSourceProvider
implements ItemSqlParameterSourceProvider<FieldSet> {
@Override
public SqlParameterSource createSqlParameterSource(FieldSet item) {
Map<String, Object> map = new HashMap<>();
for (Entry<Object, Object> entry : item.getProperties().entrySet()) {
map.put((String) entry.getKey(), entry.getValue());
}
return new MapSqlParameterSource(map);
}
}