Дизайн: лучшая практика Spring Integration jdbc

#spring-integration

#spring-интеграция

Вопрос:

После использования Spring Integration в проекте я считаю, что следует использовать адаптер или шлюз jdbc только в начале или в конце потока. Если мы будем использовать их в середине потока, то он станет слишком подробным и сложным.

Например:

 <jdbc:outbound-gateway 
    query="select * from foo where
        c1=:headers[c1] AND
        c2=:headers[c2] AND
        c3=:headers[c3] AND
        c4=:headers[c4]"
    row-mapper="fooMapper" data-source="myDataSource" max-rows-per-poll="100000" />

<int:service-activator ref="serviceActivator" method="processFoo" />
 

В приведенном выше <jdbc:outbound-gateway> примере нам нужно передать все заполнители (c1, c2, c3, c4) в заголовке сообщения. Нам нужно просматривать java-код и XML-файл для любых изменений в where условие или когда слишком много предложений where.

Это также подвержено ошибкам. Например, если мы неправильно :headers[c1] написали to :headers[d1] , то он не выдаст никакого исключения и заменит :headers[d1] на null .

Если запрос не возвращает ни одной строки, то по умолчанию он будет генерировать исключение. Итак, мы должны использовать requires-reply="false" его, чтобы изменить поведение по умолчанию.

Если мы хотим продолжить, когда запрос не возвращает никакого значения, тогда мы должны добавить рекомендации в gateway, как показано ниже:

 <jdbc:outbound-gateway ... >
    <jdbc:request-handler-advice-chain>
        <bean class="com.service.NullReplyAdvice" />
    </jdbc:request-handler-advice-chain>
</jdbc:outbound-gateway>
 

Пожалуйста, поправьте меня, если есть недостатки в понимании концепции.

Ответ №1:

Нам нужно просматривать java-код и XML-файл на предмет любых изменений в условии where или когда предложений where слишком много.

Это верно даже для необработанного Java-кода вокруг JDBC: если вы измените модель, вы, конечно, должны изменить SELECT , потому что это просто строка. И именно поэтому требуется много работы, чтобы сделать его типобезопасным — ORM, QueryDSL, Spring-Data и т.д.

если мы неправильно написали :headers[c1] в :headers[d1], то это не вызовет никаких исключений и заменит :headers[d1] на null .

Это потому headers , что это просто a Map , и это правда, которую вы получаете null , если на карте такого a нет key . Чтобы устранить эту проблему с опечаткой, вы можете использовать POJO payload с геттерами или какой-нибудь пользовательский заголовок, и снова — POJO с геттерами. В этом случае вы получаете исключение из-за отсутствия такого свойства для object. Хотя вы увидите эту проблему только во время выполнения, а не при компиляции. И снова то же самое с Hashtable — только во время выполнения.

Итак, мы должны использовать requires-reply=»false», чтобы изменить поведение по умолчанию.

Вы должны понимать это во время разработки: разрешить или не возвращать ничего для компонента.

Последняя идея хороша. Не могли бы вы поделиться своим NullReplyAdvice ? На самом деле я добиваюсь того же с <filter> помощью шлюза before the JDBC: чтобы определить, есть ли что-то, что можно получить с помощью count(*) запроса. Оттуда я могу привести свой поток к другой логике, а не к прямому потоку, когда SELECT возвращает строки.

Обновить

Если вы хотите использовать объект модели для сохранения значений, специфичных для бизнеса, в сообщении, достаточно просто поместить этот объект в заголовок:

 public class Foo {

   private String foo1;

   private String foo2;

   public String getFoo1() {
      return foo1;
   }

   public String getFoo2() {
      return foo2;
   }

}

...

MessageBuilder.withPayload(payload).setHeader("foo", foo).build();

...

<jdbc:outbound-gateway 
    query="select * from foo where
        c1=:headers[foo].foo1 AND
        c1=:headers[foo].foo2"/>
 

Комментарии:

1. Для реализации NullReplyAdvice, пожалуйста, проверьте forum.spring.io/forum/spring-projects/integration /…

2. В моем проекте слишком много запросов, и теперь он стал слишком подробным. Я должен использовать NullReplyAdvice после каждого запроса для обработки нулевых результатов. Не могли бы вы поделиться кодом полезной нагрузки POJO с получателями. Я попробую. Спасибо.

3. Добавлен образец заголовка POJO

4. В приведенном выше примере заголовка POJO показано, как выполнить маршрутизацию на основе значения [foo].foo1 . Например, что-то вроде этого: <int:header-value-router input-channel=»routingChannel» header-name=»:headers[foo].foo1″> <int:значение сопоставления =»X» channel=»xChannel» /> <int: значение сопоставления =»Y» channel=»yChannel» /> </int:заголовок-значение-маршрутизатор>

5. Нет, <заголовок-значение-маршрутизатор> просто извлекается header по указанному имени. Для этой вложенной цели вы должны использовать универсальный маршрутизатор с. expression="headers[foo].foo1" : Индикатор примечания предназначен только для JdbcTemplate