2016-06-06 4 views
0

Я попытался преобразовать SQL результат в CSV-файл это маршрут (bluprint.xml):Apache верблюд - SQL в CSV

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

Это трансформатор класса для создания формата 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"); 
       } 
      } 
     } 

В этом случае я должен знать имя полей (например, id, lastname ...), и вместо этого я хочу использовать индекс , потому что таблица или поля могут измениться.

Как использовать индекс вместо полей имени?

+0

Что ваш вопрос? –

+0

@Claus Как я могу использовать индекс вместо полей имени? если это невозможно, я могу конвертировать в csv? – zied123456

ответ

0

Найдите небольшой фрагмент, чтобы показать, что он не будет работать, как вы хотите.

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

выход

John,42,Doe 
Jane,23,Doe 

Порядок значений зависит от имени столбца и типа Map.

Если вы используете TreeMap вы можете заставить имена столбцов, возвращаемых в инструкции SQL, чтобы быть в порядке, вы хотите, чтобы выводить их (я не хотел бы предложить, чтобы сделать это)

Смотрите этот небольшой фрагмент кода в показать идею

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

выход

42,Doe,John 
Jane,23,Doe 
2

Я знаю, что вы можете сделать код выше работы с некоторыми ухищрениями, но я думал, что я сделал бы предложить который может облегчить вам всю проблему. Компонент Camel SQL позволяет автоматически сопоставлять ответ вашей базы данных с объектом. Синтаксис выглядит так:

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

После этой установки вы получите объект в вашем теле верблюда из

List<MyDatabaseModel> 

На данный момент вы можете использовать компонент верблюжий под названием Бинди. Это позволит вам создать объект CSV-файла. То, как вы связываете это, - это несколько аннотаций в вашей модели базы данных, чтобы он мог также представлять ваш вывод csv.

@CsvRecord(isOrdered = true) 
public Class MyDatabaseModel{ 

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

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

    ... 
} 

Вызов Бинди будет настроить что-то вроде этого:

// 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) 

Собирает все вместе, вы можете разбить проект на 2 линию верблюда и 1 объект Java для выполнения этой задачи.«Полный верблюд ниже»

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

Я думаю, что я должен также упомянуть, если вы не хотите слишком беспокоиться о конфигурации вашего заказа Csv вы можете пропустить весь процесс аннотаций и просто сделать:

marshal().csv(); 
+0

Спасибо за ваш ответ! Проблема в том, что я не знаю названия полей. Мне нужно преобразовать список в формат csv независимо от результата sql. – zied123456

+1

Возможно, вы сможете использовать функции самой базы данных. Большинство баз данных позволяют экспортировать таблицу в формате CSV. Вы можете упростить это, используя эту функцию в качестве хранимой процедуры и планируя ее, чтобы у вас не было большого количества кода для обслуживания. Это еще один вариант –

0

Я просто начать работу с 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"); 

в й добавить зависимость

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