【问题标题】:FlatFileItemReader and FlatFileItemWriter Using Batch Job使用批处理作业的 FlatFileItemReader 和 FlatFileItemWriter
【发布时间】:2019-01-24 07:19:59
【问题描述】:

我想从文本文件中读取、解析和写入数据。我实现了这一点,但我对标识符的声明有疑问。我在下面展示我的班级。

CustomerDataMapper.java

public class CustomerDataMapper implements FieldSetMapper<Customer> {
     private static Log log = LogFactory.getLog(CustomerDataMapper.class);

     @Override
     public RawData mapFieldSet(FieldSet fieldSet) throws BindException {
          Customer customer = new Customer();

          try {
              customer.setCustNum(fieldSet.readInt("id"));
              customer.setNameSurname(fieldSet.readString("name"));
          }catch (Exception e){
              log.error("Mapping error, " + e);
          }
          return customer;
     }
}

Customer.java

@Component
@Scope("prototype")
public class Customer implements Serializable{
    private Integer custNum;
    private String nameSurname;

    public String getCustNum) {
        return custNum;
    }

    public void setCustNum(String custNum) {
        this.custNum = custNum;
    }

    public String getNameSurname() {
        return nameSurname;
    }

    public void setNameSurname(String nameSurname) {
        this.nameSurname = nameSurname;
    }
}

fileManager.xml

<bean id="customerFileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
    <property name= "encoding" value ="Cp1254"/>                           
    <property name="resource" value="#{jobParameters['processPath']}"/>
    <property name="lineMapper">
    <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
        <property name="lineTokenizer">
            <bean class="org.springframework.batch.item.file.transform.FixedLengthTokenizer">
                <property name="names" value="id, name"/>
                <property name="columns" ref="1-9, 10-30"/>
            </bean>
        </property>
        <property name="fieldSetMapper">
            <bean class="mapper.CustomerDataMapper ">
                <property name="fileName" value="#{jobParameters['fileNameAndTime']}"/>
            </bean>
        </property>
    </bean>
</property>

<bean id="customerFileItemWriter" class="org.springframework.batch.item.database.JdbcBatchItemWriter">
    <property name="dataSource" ref="dataSource"/>
    <property name="sql">
        <value>
            <![CDATA[
                insert into CUSTOMER(CUST_NUM, NAME_SURNAME)
                values (:custNum, :nameSurname)
            ]]>
        </value>
    </property>
    <property name="itemSqlParameterSourceProvider">
    <bean class="org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider"/>
</property>

 <bean id = "customerSkipListener" class="listener.CustomerSkipListener"/>

<batch:job id="customerImportJob">
    <batch:step id="smsPasswordDataImportStep">
        <batch:tasklet>
            <batch:chunk reader="customerFileItemReader" writer="customerFileItemWriter" commit-interval="1" skip-limit="1000">
            <batch:skippable-exception-classes>
                <batch:include class="java.lang.Exception"/>
                <batch:exclude class="java.io.FileNotFoundException"/>
            </batch:skippable-exception-classes> <batch:listeners>
            <batch:listener ref="customerSkipListener" />
        </batch:listeners>
        </batch:chunk>
    </batch:tasklet>

</batch:step>

我想问一下,FieldSetMapper下面这个类可以用吗?如果我在定义标识符时不使用 Camelcase 表示法,则无法写入数据库。有没有关于这个的任何方法或方法。非常感谢。

Customer.java

@Component
@Scope("prototype")
public class Customer implements Serializable{

private Integer Cust_Num;
private String Name_Surname;

public String getCust_Num() {
    return Cust_Num;
}

public void setCust_Num(String Cust_Num) {
    this.Cust_Num = Cust_Num;
}

public String getName_Surname() {
    return Name_Surname;
}

public void setName_Surname(String Name_Surname) {
    this.Name_Surname = Name_Surname;
}
}

【问题讨论】:

    标签: java xml spring-mvc spring-batch flatfilereader


    【解决方案1】:

    我想问这个,FieldSetMapper可以用这个类

    是的,你可以使用这个类。由于您编写了自定义FieldSetMapper,因此您可以控制映射逻辑。您的映射器将类似于:

    public class CustomerDataMapper implements FieldSetMapper<Customer> {
       private static Log log = LogFactory.getLog(CustomerDataMapper.class);
    
       @Override
       public RawData mapFieldSet(FieldSet fieldSet) throws BindException {
          Customer customer = new Customer();
    
          try {
              customer.setCust_Num(fieldSet.readInt("id"));
              customer.setName_Surname(fieldSet.readString("name"));
          }catch (Exception e){
              log.error("Mapping error, " + e);
          }
          return customer;
       }
    }
    

    但您的问题不在于阅读方面(以及FieldSetMapper),而在于作者方面。 JdbcBatchItemWriter 使用 ItemSqlParameterSourceProvider 从您的 Customer 对象中提取数据并将它们设置在 sql 查询中。默认情况下,使用BeanPropertyItemSqlParameterSourceProvider,此实现基于 JavaBeans 命名约定提取数据。但是,您可以提供自定义实现,在您的情况下类似于:

    class CustomerItemSqlParameterSourceProvider implements ItemSqlParameterSourceProvider<Customer> {
    
        @Override
        public SqlParameterSource createSqlParameterSource(Customer customer) {
            Map<String, Object> params = new HashMap<>();
            params.put("custNum", customer.getCust_Num());
            params.put("nameSurname", customer.getName_Surname());
            return new MapSqlParameterSource(params);
        }
    }
    

    然后你在你的作家上设置这个CustomerItemSqlParameterSourceProvider

    希望这会有所帮助。

    【讨论】:

    • 我想问另一个问题。如果一行损坏并引发异常,我如何避免插入所有行。现在,只是损坏的行不插入到表中?如果你帮助我,我会很高兴。
    • 您可以使用SkipListener。我看到您已经有一个listener.CustomerSkipListener,因此您可以使用此组件将跳过的行保存在表格中。
    • 我明白,但如果一行有异常,我想避免插入所有行的表格。有这样的方法吗?
    • 我不明白。在跳过侦听器中,您将拥有被跳过的行。由您决定哪些应该放在表中,哪些应该被过滤。
    猜你喜欢
    • 2018-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多