简体   繁体   English

Apache骆驼-SQL到CSV

[英]Apache camel - SQL to CSV

I have tried to convert sql result to csv file this is the route (bluprint.xml): 我试图将sql结果转换为csv文件,这是路由(bluprint.xml):

<route id="extractfromafbl">
  <from uri="timer:foo?period=10000"/>
  <to uri="sql:select * from performances?dataSource=afbl_source"/>
  <to uri="bean:ngtrend.afbl2afc.transformer?method=tocsv(Exchange)"/>
  <log message="${body}"/>
</route>

This is transformer class to create csv format: 这是创建csv格式的转换器类:

    public class transformer {
            public void tocsv(Exchange exchange)
            {
                StringBuilder csv = new StringBuilder();
                List received = exchange.getIn().getBody(List.class);
                for (int i = 0; i < received.size(); i++) 
                 {
                   Map<String,Object> row = (Map<String,Object>) received.get(i);
                   csv.append(row.get("id"));
                   csv.append(",").append(row.get("lastname"));
                   csv.append(",").append(row.get("firstname"));
                   csv.append("\r");
                 }
            }
        }

in this case I should know the name of fields (like id, lastname ...) and I want to use an index instead because the table or fields can change. 在这种情况下,我应该知道字段的名称(例如id,lastname ...),而我想使用索引,因为表或字段可以更改。

How can I use index instead of name fields ? 如何使用索引代替名称字段?

I know you can make the code above work with some tweaks, but I thought I would make a suggestion that could make this whole problem way easier for you. 我知道您可以通过一些调整使上面的代码起作用,但是我想提出一个建议,可以使您更轻松地解决整个问题。 The Camel SQL component lets you automatically map your database response back to an Object. Camel SQL组件使您可以自动将数据库响应映射回对象。 Syntax is like this: 语法如下:

from("sql:select * from performances?dataSource=afbl_source?outputType=SelectList&outputClass=com.myapp.MyDatabaseModel")

Once you have this setup you will get an object in your camel body of a 完成此设置后,您会在骆驼的骆驼体内获得一个对象

List<MyDatabaseModel>

At this point you can leverage a camel component called Bindy. 此时,您可以利用名为Bindy的骆驼组件。 It will let you have an Object represent a CSV file. 它会让您拥有一个代表CSV文件的对象。 The way you would bind this is with a few annotations on your database model so it can also represent your csv output. 绑定方法是在数据库模型上添加一些注释,以便它也可以表示csv输出。

@CsvRecord(isOrdered = true)
public Class MyDatabaseModel{

   @DataField(pos = 1, position = 11)
   private int orderNr;

   @DataField(pos = 2, position = 10)
   private String clientNr;

   ...
}

The call to Bindy would be setup something like this: 对Bindy的调用将设置如下:

// Camel 2.15 or older (configure by package name)
BindyCsvDataFormat bindy = new BindyCsvDataFormat("com.myapp");
// Camel 2.16 onwards (configure by class name)
BindyCsvDataFormat bindy = new BindyCsvDataFormat(com.myapp.MyDatabaseModel.class);

.marshal(bindy)

Bringing it all together you can break your project down into 2 lines of camel and 1 java object for this task. 综上所述,您可以将项目分解为2行骆驼和1个Java对象来完成此任务。 "Full camel below" “下面的完整骆驼”

from("sql:select * from performances?dataSource=afbl_source?outputType=SelectList&outputClass=com.myapp.MyDatabaseModel")
    .marshal(bindy);

I think I should also mention if you don't want to worry too much about configuration of your csv order you can actually skip the whole annotation process and simply do: 我想我也应该提到,如果您不想过多担心csv命令的配置,则可以跳过整个注释过程,而只需执行以下操作:

marshal().csv();

Find a small snippet to show that it will not work as you whish. 找到一个小片段,以表明它在您希望时不起作用。

List<Map<String, Object>> received = new ArrayList<>();
Map<String, Object> rowOne = new HashMap<>();
rowOne.put("id", 42);
rowOne.put("lastname", "Doe");
rowOne.put("firstname", "John");
Map<String, Object> rowTwo = new HashMap<>();
rowTwo.put("id", 23);
rowTwo.put("lastname", "Doe");
rowTwo.put("firstname", "Jane");
received.add(rowOne);
received.add(rowTwo);
StringBuilder csv = new StringBuilder();
for (Map<String, Object> i : received) {
    StringJoiner line = new StringJoiner(",");
    for (Map.Entry<String, Object> j : i.entrySet()) {
        line.add(j.getValue().toString());
    }
    csv.append(line.toString()).append("\n");
}
System.out.println(csv);

output 产量

John,42,Doe
Jane,23,Doe

The order of the values depends on the name of the column and the type of the Map . 值的顺序取决于列的名称和Map的类型。

If you use a TreeMap you might force the names of the columns returned by the SQL statement to be in the order you want to output them (I would not suggest to do so) 如果使用TreeMap ,则可能会强制将SQL语句返回的列的名称按照您要输出的顺序排列(我不建议这样做)

See this small snippet to show the idea 查看此小片段以说明想法

List<Map<String, Object>> received = new ArrayList<>();
Map<String, Object> rowOne = new TreeMap<>();
rowOne.put("1id", 42);
rowOne.put("2lastname", "Doe");
rowOne.put("3firstname", "John");
Map<String, Object> rowTwo = new TreeMap<>();
rowTwo.put("id", 23);
rowTwo.put("lastname", "Doe");
rowTwo.put("firstname", "Jane");
received.add(rowOne);
received.add(rowTwo);
StringBuilder csv = new StringBuilder();
for (Map<String, Object> i : received) {
    StringJoiner line = new StringJoiner(",");
    for (Map.Entry<String, Object> j : i.entrySet()) {
        line.add(j.getValue().toString());
    }
    csv.append(line.toString()).append("\n");
}
System.out.println(csv);

output 产量

42,Doe,John
Jane,23,Doe

I'm just getting started with Camel so perhaps there's another way but I'm able to dump from a table to a CSV file without any knowledge of the field names with: 我刚刚开始使用Camel,所以也许还有另一种方法,但是我可以通过以下方式将表从表转储到CSV文件中:

CsvDataFormat csv = new CsvDataFormat();
csv.setQuoteMode("ALL");

from("sql:select * from MY_TEST_TABLE?dataSource=oracleDataSource&useIterator=false").marshal(csv).to("file:///tmp?fileName=MY_TEST_FILE.csv");

and add the dependency 并添加依赖项

    <dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-csv</artifactId>
<version>version</version>

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

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