Как обновить только используемые строки SQL с помощью Apache Camel SQL Component?

Я новичок в Camel, и я пытаюсь обрабатывать данные SQL. Если выполнение SQL (выбор) завершено, я пытаюсь обновить использованные строки, но я просто получаю исключение "плохая грамматика SQL".

Я использую SQL-компонент Apache Camel, где начальной конечной точкой является оператор выбора SQL. Чтобы пометить их как использованные, я использую onConsume параметр SQL-компонента. В выборе v_table это вид исходной таблицы t_table, который используется впоследствии в обновлении. Итак id ряда в v_table а также t_table та же. Чтобы обновить не все строки в t_tableя использую условие where с where id = :#id,

String sqlSelect = "select * from v_table where camel_is_read = 0";
String sqlUpdate = "update t_table set camel_is_read = 1, date_checked = sysdate where id = :#id";
from("sql:"+sqlSelect+"?dataSource=myDataSource&onConsume="+sqlUpdate)
.process(new Processor() {
    public void process(Exchange exchange) throws Exception {
        System.out.println(exchange.getIn().getBody().toString());
    }
})                    
.errorHandler(deadLetterChannel("direct:moveFailedOut").useOriginalMessage())
.bean("orderToJms")
.to(jmsURI)
.bean("validate")
.to(ftpOut);

Если я выполню это, я получу следующее исключение:

WARN  Error executing onConsume/onConsumeFailed query update t_table set camel_is_read = 1, date_checked = sysdate where id = :?id. Caused by: [org.springframework.jdbc.BadSqlGrammarException - PreparedStatementCallback; bad SQL grammar [update t_table set camel_is_read = 1, date_checked = sysdate where id = ?]; nested exception is java.sql.SQLSyntaxErrorException: ORA-00904: "YSDATEHERE": ungültiger Bezeichner
]
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [update t_table set camel_is_read = 1, date_checked = sysdate where id = ? exception is java.sql.SQLSyntaxErrorException: ORA-00904: "YSDATEHERE": ungültiger Bezeichner

    at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:237)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:605)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617)
    at org.apache.camel.component.sql.DefaultSqlProcessingStrategy.commit(DefaultSqlProcessingStrategy.java:46)
    at org.apache.camel.component.sql.SqlConsumer.processBatch(SqlConsumer.java:195)
    at org.apache.camel.component.sql.SqlConsumer$1.doInPreparedStatement(SqlConsumer.java:118)
    at org.apache.camel.component.sql.SqlConsumer$1.doInPreparedStatement(SqlConsumer.java:91)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:589)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617)
    at org.apache.camel.component.sql.SqlConsumer.poll(SqlConsumer.java:91)
    at org.apache.camel.impl.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:174)
    at org.apache.camel.impl.ScheduledPollConsumer.run(ScheduledPollConsumer.java:101)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:351)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:178)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:724)
Caused by: java.sql.SQLSyntaxErrorException: ORA-00904: "YSDATEHERE": ungültiger Bezeichner

Я попытался выполнить обновление вручную в базе данных с идентификатором теста (например, "3"), который работает, поэтому общая грамматика SQL должна быть в порядке. Так что мне кажется, что верблюд не может заменить :#id параметр.

Я добавил процессор, чтобы проверить результат выбора:

{ID=3, [...] CAMEL_IS_READ=0}

Здесь я вижу, что выбранные успешно поймали необходимое id, Я не понимаю, почему Camel не может заменить :#id параметр с id значение 3. Кто-нибудь знает, как решить эту проблему? Я использовал это и это как грубый пример / шаблон. Или этот подход вообще неверен?

1 ответ

Решение

Наконец это работает для меня, окружив sysdate заявление с to_date() функция:

String sqlSelect = "select * from v_table where camel_is_read = 0";
String sqlUpdate = "update t_table set camel_is_read = 1, date_checked = to_date(sysdate) where id = :#id";
from("sql:"+sqlSelect+"?dataSource=myDataSource&onConsume="+sqlUpdate)
.process(new Processor() {
    public void process(Exchange exchange) throws Exception {
        System.out.println(exchange.getIn().getBody().toString());
    }
})                    
.errorHandler(deadLetterChannel("direct:moveFailedOut").useOriginalMessage())
.bean("orderToJms")
.to(jmsURI)
.bean("validate")
.to(ftpOut);

Несколько замечаний, что не работает / не является хорошей идеей (на мой взгляд) и может сэкономить вам время:
В некоторых ситуациях onConsumeBatchComplete может быть решением. Если вы знаете условие, вы можете подразумевать, что, если все строки с этим условием проходят через верблюда, эти строки могут быть обновлены. Это работает вместе с sysdate и не нуждается в id заполнитель. Недостатком этого решения является то, что оно неявно, и если в то же время добавляются новые строки, которые верблюд не прошел, они также будут обновлены после завершения партии. Поэтому я не могу рекомендовать это.

Также не работает установка времени в Java, например так:

String sqlUpdate = "update t_table date_checked = " + today + " where id = :#id";

Если вы не перезапускаете свой маршрут каждый день, верблюжий маршрут активен в течение нескольких дней, недель или лет. В этом случае верблюжий маршрут будет сгенерирован при запуске, и после этого всегда будет зафиксирована "сегодняшняя" дата с этой датой. Таким образом, он всегда будет использовать одну и ту же дату для обновления базы данных.

Другие вопросы по тегам