0

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;
}
}
S.Balaban
  • 174
  • 2
  • 19

1 Answers1

1

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.

Mahmoud Ben Hassine
  • 28,519
  • 3
  • 32
  • 50
  • I want to ask another question. How can i avoid to insert the all lines if one lines was damaged and thrown an exception. Now, just damaged lines don't insert to table? If you help me, I will so happy. – S.Balaban Jan 31 '19 at 11:31
  • You can use a [SkipListener](https://docs.spring.io/spring-batch/4.1.x/reference/html/step.html#skipListener). I see you have already a `listener.CustomerSkipListener`, so you can use this component to save skipped lines in a table. – Mahmoud Ben Hassine Jan 31 '19 at 11:37
  • I understand but I want to avoid to insert into table for all lines if one line have exception. Is there such a method? – S.Balaban Jan 31 '19 at 11:45
  • I don't understand. In the skip listener, you will have the lines that were skipped. It is up to you to decide which ones should go in the table and which ones should be filtered. – Mahmoud Ben Hassine Jan 31 '19 at 12:28