Spring Batch:如何从BeanWrapperFieldExtractor中获取子类对象的属性

时间:2018-03-14 11:16:33

标签: java spring spring-batch

我有一个应用程序,它将xml作为输入并写入csv。

这是我的输入xml:

<Main location="ABC" date="2018-02-26" name="Default">
  <Sub firstname="XYZ" lastname="PQR"/>
  <Sub firstname="147" lastname="123"/>
</Main>

我在我的作品编写者的BeanWrapperFieldExtractor中有以下内容:

<beans:property name="fieldExtractor">
    <beans:bean class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
        <beans:property name="names" value="location,date,name"/>
    </beans:bean>
</beans:property>

我获得了正确的输出,但我还要包含名字和姓氏,我在下面添加了:

<beans:property name="names" value="location,date,name,sub.firstname,sub.lastname"/>

但我已经低于错误:

org.springframework.beans.NotReadablePropertyException: Invalid property 'sub.firstname' of bean class [com.xyz.MainClass]: Bean property 'sub.firstname' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
    at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:707)

有没有办法从逐个放入csv文件的xml数据中提取整个Sub元素。

1 个答案:

答案 0 :(得分:0)

遇到相同的问题,我发现了两种检索子属性的解决方案:

我假设您正在将输入映射到其相关类。

1。。使用FieldExtractor在您的类上创建一个自定义属性+ getter以检索子属性:

public class Example {

  @OneToOne
  private ChildExample childExample;

  // add Transient if you use hibernate to avoid validation:
  @Transient
  private String customProperty;

  // custom getter :
  public String getCustomProperty() {
    return childExample.getChildProperty();
  }
}

然后,您可以在编写器上配置BeanWrapperFieldExtractor

  BeanWrapperFieldExtractor<Example> fieldExtractor = new BeanWrapperFieldExtractor<>();
  fieldExtractor.setNames(new String[]{"customProperty"});

  // then you configure the lineAggregator on a FileItemWriter :
  DelimitedLineAggregator<Example> lineAggregator = new DelimitedLineAggregator<>();
  lineAggregator.setFieldExtractor(fieldExtractor);
  FlatFileItemWriter<Example> writer = new FlatFileItemWriter<>();
  writer.setLineAggregator(lineAggregator);
  writer.open(executionContext);
  ...

2。。使用自定义LineAggregator并覆盖toString类方法:

@Component
public class ExampleLineAggregator<Example> implements LineAggregator<Example> {

  @Override
  public String aggregate(Example item) {
    return item.toString();
  }

}

覆盖toString方法:

public class Example {

  @OneToOne
  private ChildExample childExample;

  @Override
  public String toString() {
    return childExample.getChildProperty();
  }
}

然后将自定义LineAggregator设置为作者:

  FlatFileItemWriter<Example> writer = new FlatFileItemWriter<>();
  writer.setLineAggregator(customLineAggregator);