简体   繁体   中英

FlatFileItemReader and FlatFileItemWriter Using Batch Job

I want to read, parse and write data from text file. I achieved this but I have a question about the declaration of the identifiers. I show my class below.

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>

I want to ask this, Can I use this class below for FieldSetMapper. If I don't use Camelcase notation when defining identifiers, it doesn't work to write to database. Is there any approach or method about this. Thank you so much.

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;
}
}

I want to ask this, Can use this class for FieldSetMapper

Yes you can use this class. Since you wrote your custom FieldSetMapper , you have control over the mapping logic. Your mapper would be something like:

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;
   }
}

But your issue is not on reading side (and the FieldSetMapper ), it is on the writer side. The JdbcBatchItemWriter uses a ItemSqlParameterSourceProvider to extract data from your Customer object and set them on the sql query. By default, a BeanPropertyItemSqlParameterSourceProvider is used, this implementation extracts data based on JavaBeans naming conventions. However, you can provide a custom implementation, which in your case would be something like:

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

Then you set this CustomerItemSqlParameterSourceProvider on your writer.

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM