Camel расширяет синтаксис SQL

Мне поручено создать маршрут Camel с использованием Camel версии 2.20.0, который берет строку из CSV-файла, использует значение из этой строки в предложении SQL where, объединяет результаты и выводит их снова. Если я жестко запрограммирую идентификатор в операторе SQL, он будет работать нормально, если я попытаюсь использовать динамический URI, я получу ошибку.

Маршрут:

from("file:///tmp?fileName=test.csv")
.split()
.tokenize("\n")
.streaming()
.parallelProcessing(true)
.setHeader("userID", constant("1001"))
//.enrich("sql:select emplid,name from employees where emplid = '1001'",
.enrich("sql:select name from employees where emplid = :#userID",
     new AggregationStrategy() {
        public Exchange aggregate(Exchange oldExchange,
                                     Exchange newExchange)    {...

Как я уже сказал, если я раскомментирую строку с жестко закодированным 1001, она запрашивает базу данных и работает, как и ожидалось. Однако, используя синтаксис ':#userID', я получаю ошибку Oracle:

java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist


    Message History
    ---------------------------------------------------------------------------------------------------------------------------------------
    RouteId              ProcessorId          Processor                                                                        Elapsed (ms)
    [route3            ] [route3            ] [file:///tmp?fileName=test.csv                                                 ] [        43]
    [route3            ] [log5              ] [log                                                                           ] [         2]
    [route3            ] [setHeader2        ] [setHeader[userID]                                                             ] [         0]
    [route3            ] [enrich2           ] [enrich[constant{sql:select name from employees where emplid = :#userID] [        40]

Таблица явно существует, потому что она работает, когда значение жестко закодировано, поэтому она как-то связана с передачей динамического значения. Я пробовал множество вариантов того, как передать эту переменную внутри одинарных кавычек, используя значения из тела вместо заголовков и т. д., и еще не нашел рабочей комбинации, хотя я видел много похожих, казалось бы, рабочих примеров. .

Я включил трассировку, похоже, заголовок также установлен правильно:

o.a.camel.processor.interceptor.Tracer   :  >>> (route3) setHeader[userID, 1001] --> enrich[constant{sql:select name from employees where emplid = :#userID}] <<< Pattern:InOnly, Headers:{CamelFileAbsolute=true, CamelFileAbsolutePath=/tmp/test.csv, CamelFileLastModified=1513116018000, CamelFileLength=26, CamelFileName=test.csv, CamelFileNameConsumed=test.csv, CamelFileNameOnly=test.csv, CamelFileParent=/tmp, CamelFilePath=/tmp/test.csv, CamelFileRelativePath=test.csv, userID=1001}, BodyType:String, Body:1001,SomeValue,MoreValues

Что нужно изменить, чтобы это заработало?

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

.enrich().simple("sql:select * from employees where emplid = :#${in.header.userID}").aggregate ...

person user2501326    schedule 12.12.2017    source источник


Ответы (2)


Из документов:

Начиная с Camel 2.16 и далее как enrich, так и pollEnrich поддерживают динамические конечные точки, которые используют выражение для вычисления uri, что позволяет использовать данные из текущей биржи. Другими словами, все, что сказано выше, больше не применимо, а просто работает.

Поскольку вы используете 2.20, я думаю, вы можете попробовать этот пример:

from("file:///tmp?fileName=test.csv")
.split()
.tokenize("\n")
.streaming()
.parallelProcessing(true)
.setHeader("userID", constant("1001"))
//.enrich("sql:select emplid,name from employees where emplid = '1001'",
.enrich("sql:select name from employees where emplid = ':#${in.header.userID}'",
    new AggregationStrategy() {
        public Exchange aggregate(Exchange oldExchange,
                                    Exchange newExchange)    {...

Дополнительные примеры см. в разделе документации Expression.

Подводя итог, выражение может быть:

"sql:select name from employees where emplid = ':#${in.header.userID}'"

ИЗМЕНИТЬ:

Извините, я пропустил суффикс :# . Вы можете увидеть здесь работает модульный тест.

Просто будьте осторожны с типами столбцов. Если это целое число, вам не нужны кавычки.

Ваше здоровье!

person Ricardo Zanini    schedule 13.12.2017
comment
К сожалению, когда я пытаюсь это сделать, я получаю другое исключение: org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL []; SQL state [99999]; error code [17034]; Non supported SQL92 token at position: 45; nested exception is java.sql.SQLException: Non supported SQL92 token at position: 45, которое является '{'. Замен почти не бывает. - person user2501326; 13.12.2017
comment
Я пробовал как с двоеточием, так и без него, и получаю ту же ошибку, без двоеточия выдает ошибку в позиции 44. - person user2501326; 13.12.2017
comment
Вот ошибка без токена: org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL []; SQL state [99999]; error code [17034]; Non supported SQL92 token at position: 44; nested exception is java.sql.SQLException: Non supported SQL92 token at position: 44 история сообщений заканчивается на [route3 ] [enrich2 ] [enrich[constant{sql:select name from employees where emplid = ${in.header.use] [ 56] - person user2501326; 13.12.2017
comment
Я пропустил цитаты. Попробуйте это: "sql:select name from employees where emplid = '${in.header.userID}'". Но это странно.. кажется, что динамические выражения не работают, и это было реализовано в версии 2.16.. :( - person Ricardo Zanini; 13.12.2017
comment
Кроме того, попробуйте добавить вашу константу как целое число: .setHeader("userID", constant(1001)). Ваш столбец является целым числом или varchar? - person Ricardo Zanini; 13.12.2017
comment
Только что отредактировал свой вопрос, я забыл суффикс :#. - person Ricardo Zanini; 13.12.2017
comment
Фантастика @Рикардо! Используя ваш модульный тест, я смог сузить проблему. Ваш модульный тест работает, конечно. Когда я меняю Derby на Oracle, он также работает. Однако он завершается с той же ошибкой, о которой я сообщал, если я предваряю имя таблицы схемой (верблюд.проекты против проектов в операторе sql) и использую Oracle. Он отлично работает в Derby со схемой, предшествующей имени таблицы. Я не уверен, в чем проблема с именем схемы и Oracle, но я могу обойти это. Спасибо! - person user2501326; 13.12.2017

Из документов Camel:

pollEnrich или обогащение не получает доступ к каким-либо данным из текущего Exchange, что означает, что при опросе он не может использовать ни один из существующих заголовков, которые вы, возможно, установили на Exchange.

Рекомендуемый способ добиться того, чего вы хотите, — вместо этого использовать recipientList, поэтому я предлагаю вам прочитать об этом.

Изменить:

Как справедливо отметил Рикардо Занини в своем ответе, на самом деле это возможно сделать с версиями Camel начиная с версии 2.16. Поскольку ОП использует 2.20, мой ответ недействителен.

Однако я оставлю свой ответ, но хочу отметить, что это действительно только в том случае, если вы используете более старую версию, чем 2.16.

person Erik Karlstrand    schedule 13.12.2017