如何在不将行映射到域对象的情况下使用springbatch

时间:2017-03-01 07:01:33

标签: spring-batch

通常,从csv文件读取然后写入数据库,我们将每一行映射到POJO(域对象)。但是当csv文件发生变化时如何做到这一点?这意味着,有许多不同格式的csv文件,我不想为每个文件编写POJO。

我可以想到两种方法来处理它。首先动态生成POJO类,但是如何?其次,使用PassThroughFieldSetMapperPassThroughItemProcessor,但如何在JdbcBatchItemWriter中为SQL设置参数?

1 个答案:

答案 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);
    }
}