Дизайн: передовой опыт Spring Integration jdbc

После использования 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] в :headers[d1], тогда он не выдаст никаких исключений и заменит :headers[d1] на null.

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

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

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

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


person Vikas Sharma    schedule 27.06.2014    source источник


Ответы (1)


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

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

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

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

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

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

Последняя идея хороша. Не могли бы вы поделиться своим NullReplyAdvice? На самом деле я добиваюсь того же с <filter> до шлюза 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"/>
person Artem Bilan    schedule 09.07.2014
comment
Для реализации NullReplyAdvice проверьте forum.spring.io/forum/spring-projects/integration/ - person Vikas Sharma; 09.07.2014
comment
В моем проекте слишком много запросов, и теперь он стал слишком многословным. Я должен использовать NullReplyAdvice после каждого запроса для обработки нулевых результатов. Не могли бы вы поделиться кодом полезной нагрузки POJO с геттерами. Я попробую. Спасибо. - person Vikas Sharma; 10.07.2014
comment
Добавлен образец заголовка POJO - person Artem Bilan; 10.07.2014
comment
В приведенном выше примере заголовка POJO показано, как выполнить маршрутизацию на основе значения [foo].foo1 . Например, что-то вроде этого: ‹int:header-value-router input-channel=routingChannel header-name=:headers[foo].foo1› ‹int:mapping value=X channel=xChannel /› ‹int:mapping value= Канал Y=yChannel /› ‹/int:header-value-router› - person Vikas Sharma; 10.07.2014
comment
Нет, ‹header-value-router› просто извлекает header по указанному имени. Для этой вложенной цели вы должны использовать универсальный маршрутизатор с expression="headers[foo].foo1". Примечание. Индикатор : предназначен только для JdbcTemplate. - person Artem Bilan; 10.07.2014