繁体   English   中英

带标题的Apache Camel CSV

[英]Apache Camel CSV with Header

我编写了一个简单的测试应用程序,该程序从数据库读取记录,并将结果放入csv文件中。 到目前为止,它可以正常工作,但列名称(即标头)未放入csv文件中。 根据文档,它应该放在那儿。 我也尝试过不带/带流媒体和拆分的情况,但是情况是一样的。

在第182行的骆驼单元测试中,标题明确放置在此处: https : //github.com/apache/camel/blob/master/components/camel-csv/src/test/java/org/apache/camel/ dataformat / csv / CsvDataFormatTest.java

无需迭代头就如何解决这个非常简单的问题? 我还尝试了不同的设置,但都一样。 例如,定界符被认为是我设置的,但标头没有。 也提前感谢您的回复。

我这样使用Camel 2.16.1:

final CsvDataFormat csvDataFormat = new CsvDataFormat();
csvDataFormat.setHeaderDisabled(false);
[...]
from("direct:TEST").routeId("TEST")
        .setBody(constant("SELECT * FROM MYTABLE"))
        .to("jdbc:myDataSource?readSize=100") // max 100 records
//      .split(simple("${body}"))             // split the list
//      .streaming()                          // not to keep all messages in memory
        .marshal(csvDataFormat)
        .to("file:extract?fileName=TEST.csv");
[...]

编辑1

我也尝试过从exchange.in添加标题。 它们在HashSet中以名称“ CamelJdbcColumnNames”可用。 我将其添加到csvDataFormat中,如下所示:

    final CsvDataFormat csvDataFormat = new CsvDataFormat();
    csvDataFormat.setHeaderDisabled(false);
    [...]
    from("direct:TEST").routeId("TEST")
            .setBody(constant("SELECT * FROM MYTABLE"))
            .to("jdbc:myDataSource?readSize=100") // max 100 records
            .process(new Processor() {
                public void process(Exchange exchange) throws Exception {
                    headerNames =                       (HashSet)exchange.getIn().getHeader("CamelJdbcColumnNames");
                    System.out.println("#### Process headernames = " + new ArrayList<String>(headerNames).toString());
                     csvDataFormat.setHeader(new ArrayList<String>(headerNames));
                         }
                })
                .marshal(csvDataFormat)//.tracing()
                .to("file:extract?fileName=TEST.csv");

println()打印列名,但生成的cvs文件不打印。

EDIT2我按照注释1中的建议将标头名称添加到正文中,如下所示:

.process(new Processor() {
    public void process(Exchange exchange) throws Exception {

        Set<String> headerNames = (HashSet)exchange.getIn().getHeader("CamelJdbcColumnNames");
        Map<String, String> nameMap = new LinkedHashMap<String, String>();
        for (String name: headerNames){
            nameMap.put(name, name);
        }
        List<Map> listWithHeaders = new ArrayList<Map>();
        listWithHeaders.add(nameMap);

        List<Map> records = exchange.getIn().getBody(List.class);
        listWithHeaders.addAll(records);
        exchange.getIn().setBody(listWithHeaders, List.class);


        System.out.println("#### Process headernames = " + new ArrayList<String>(headerNames).toString());
        csvDataFormat.setHeader(new ArrayList<String>(headerNames));
     }
})

该提案解决了该问题,并对此表示感谢,但这意味着CsvDataFormat并不是真正可用的。 JDBC查询后的交换主体包含HashMaps中的ArrayList,其中包含表的一条记录。 HashMap的键是列的名称,值是值。 因此,为CsvDataFormat中的标头输出设置config值应该足以获取标头。 您知道更简单的解决方案还是我错过了配置中的某些功能?

您是使用JDBC从数据库中获取数据的,因此您需要自己首先将标头添加到消息正文中,从而将其添加到第一行。 jdbc的结果集只是数据,不包括标题。

我通过重写BindyCsvDataFormat和BindyCsvFactory做到了

public class BindySplittedCsvDataFormat extends BindyCsvDataFormat {

    private boolean marshallingfirslLot = false;

    public BindySplittedCsvDataFormat() {
        super();
    }

    public BindySplittedCsvDataFormat(Class<?> type) {
        super(type);
    }

    @Override
    public void marshal(Exchange exchange, Object body, OutputStream outputStream) throws Exception {
        marshallingfirslLot = new Integer(0).equals(exchange.getProperty("CamelSplitIndex"));
        super.marshal(exchange, body, outputStream);
    }

    @Override
    protected BindyAbstractFactory createModelFactory(FormatFactory formatFactory) throws Exception {
        BindySplittedCsvFactory bindyCsvFactory = new BindySplittedCsvFactory(getClassType(), this);
        bindyCsvFactory.setFormatFactory(formatFactory);
        return bindyCsvFactory;
    }

    protected boolean isMarshallingFirslLot() {
        return marshallingfirslLot;
    }
}


public class BindySplittedCsvFactory extends BindyCsvFactory {

    private BindySplittedCsvDataFormat bindySplittedCsvDataFormat;

    public BindySplittedCsvFactory(Class<?> type, BindySplittedCsvDataFormat bindySplittedCsvDataFormat) throws Exception {
        super(type);
        this.bindySplittedCsvDataFormat = bindySplittedCsvDataFormat;
    }

    @Override
    public boolean getGenerateHeaderColumnNames() {
        return super.getGenerateHeaderColumnNames() && bindySplittedCsvDataFormat.isMarshallingFirslLot();
    }

}

我使用spring xml的解决方案(但我想在顶部也提取标题:

使用Spring XML

<multicast stopOnException="true">
    <pipeline>
      <log message="saving table ${headers.tablename} header to ${headers.CamelFileName}..."/>
      <setBody>     
<groovy>request.headers.get('CamelJdbcColumnNames').join(";") + "\n"</groovy>
      </setBody>
      <to uri="file:output"/>
    </pipeline>

    <pipeline>
      <log message="saving table ${headers.tablename} rows to ${headers.CamelFileName}..."/>
      <marshal>
        <csv delimiter=";" headerDisabled="false" useMaps="true"/>
      </marshal>
      <to uri="file:output?fileExist=Append"/>
    </pipeline>
  </multicast>

http://www.redaelli.org/matteo-blog/2019/05/24/exporting-database-tables-to-csv-files-with-apache-camel/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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