Camel丰富了SQL语法问题

时间:2017-12-12 22:22:53

标签: apache-camel camel-sql

我的任务是使用Camel版本2.20.0创建Camel路由,从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 ...

2 个答案:

答案 0 :(得分:1)

来自Camel文档:

  

pollEnrich或enrich 访问当前的任何数据   交换意味着在轮询时不能使用任何现有的   您可能在Exchange上设置的标题。

实现目标的推荐方法是使用recipientList,所以我建议你阅读。

修改

正如Ricardo Zanini在他的回答中正确指出的那样,实际上可以通过2.16以后的Camel版本实现这一目标。由于OP使用2.20,我的回答无效。

但是,我会保留我的答案,但是要指出这只有在您使用旧版本而不是2.16时才有效。

答案 1 :(得分:1)

来自docs

  

Camel 2.16 开始 充实 pollEnrich 支持使用Expression计算uri的动态端点,允许使用当前Exchange的数据。换句话说,上面说的所有内容都不再适用,只是有效。

当你使用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}'"

修改

抱歉,我错过了:# suffix。你可以看到unit test working here

请注意列类型。如果它是整数,则不需要引号。

干杯!