Apache camel 获取 Oracle 数据库生成的 ID

Apache camel getting Oracle database generated ID

我正在使用 camel jdbc 组件将记录插入 Oracle table。插入使用序列填充主键 ID 列。

INSERT INTO my_table (id, data) VALUES (my_seq.nextval, 'some data')

路线的相关部分如下所示:

 from("some end point here")
     .process(preInsertProcessor)
     .to("jdbc:myDataSource")
     .process(new Processor() {
         public void process(Exchange exchange) throws Exception {
             LOGGER.info("Extracting database generated id");
             // This list is null
             List<Integer> ids = exchange.getIn().getHeader(
                   JdbcConstants.JDBC_GENERATED_KEYS_DATA, List.class);
       });

preInsertProcessir 中,我将消息 body 设置为我的插入语句,还设置了一些两个 header 值来指示 camel 我想要返回生成的 ID:

    message.setBody("INSERT INTO my_table (id, data) VALUES (my_seq.nextval, ?:data)");
    message.setHeader("data", "some data");
    message.setHeader(JDBC_RETRIEVE_GENERATED_KEYS, true);
    message.setHeader(JDBC_GENERATED_COLUMNS, new String[]{"ID"});

结束如果我查看日志我可以看到:

[DEBUG] org.apache.camel.component.bean.MethodInfo - Setting bean invocation result on the OUT message: [Message: INSERT INTO my_table(id, data)VALUES (my_seq.nextval, :?data]
[DEBUG] org.apache.camel.spring.spi.TransactionErrorHandler - Transaction begin (0x1de4bee0) redelivered(false) for (MessageId: ID-MELW1TYGC2S-62650-1438583607644-0-8 on ExchangeId: ID-MELW1TYGC2S-62650-1438583607644-0-9))
[INFO ] au.com.nab.cls.router.non.repudiation.GeneratedIdExtractor - Extracting database generated id
[DEBUG] org.apache.camel.processor.MulticastProcessor - Done sequential processing 1 exchanges
[DEBUG] org.apache.camel.spring.spi.TransactionErrorHandler - Transaction commit (0x1de4bee0) redelivered(false) for (MessageId: ID:414d5120445041594855423120202020027844552045b302 on ExchangeId: ID-MELW1TYGC2S-62650-1438583607644-0-7))

如果我从日志中看得很好,插入将被执行,我的最终处理器应该能够获得生成的 ID。实际上,消息的 header 中没有插入记录,也没有 ID 存在。没有最终处理器一切正常。

显然我在这里做错了什么,但我不知道是什么。我知道我可以使用消息 en-richer 在插入之前获取 ID,但我希望避免额外的数据库访问。

提前感谢您的意见。

更新 我在 org.apache.camel.component.jdbc.JdbcProducer 中放置了一个断点,并找出了没有执行 INSERT 并因此没有取回 ID 的原因。

// JdbcProducer code; creating a prepared statement part
if (shouldRetrieveGeneratedKeys) {
...
    } else if (expectedGeneratedColumns instanceof String[]) {
        // Execution gets herestatement
        ps = conn.prepareStatement(preparedQuery, (String[]) expectedGeneratedColumns);
...
}
// Expected count returned here is 2
int expectedCount = ps.getParameterMetaData().getParameterCount();
if (expectedCount > 0) {
    ...
    // And here I get the crash:
    // java.sql.SQLException: Number of parameters mismatch. Expected: 2, was:1
    getEndpoint().getPrepareStatementStrategy().populateStatement(ps, it, expectedCount);
 }

这是我的研究停止的地方,因为在各种 3 方代码中挖掘太多并不是一件容易的事。我怀疑以下两个选项之一是原因:

  1. 我做的还是不对
  2. 当 header 包含命名参数和 检索生成的密钥 设置时,无法按预期工作的骆驼错误

请告知任何修复或解决方法。

再次感谢

我也运行加入这个。我的解决方法:

使用骆驼-sql 而不是骆驼-jdbc。添加 parametersCount 选项到端点 URL(除了 setHeader(SqlConstants.SQL_RETRIEVE_GENERATED_KEYS, constant(true))setHeader(SqlConstants.SQL_GENERATED_COLUMNS, constant(new String[] {"ID_COLUMN_NAME"}))。

更新:适用于 11.2.0.4 jdbc 驱动程序(不适用于 12.2.0.1 jdbc 驱动程序)。