2016-10-15 2 views
3

У меня есть требование вставить список POJO для вставки в базу данных. У меня есть хранимая процедура, которая выполняет одну вставку за раз. В текущей реализации у меня есть сплиттер, который разбивается на POJO и передает эту полезную нагрузку на сохраненный исходящий шлюз proc для вызова моей хранимой процедуры.Spring Integration JDBC Batch Insert

В реальном времени размер моего списка может составлять 500K. Так есть ли способ для лучшей реализации? Есть ли способ выполнить пакетную вставку в поток SI?

Благодаря

+0

Я не знаю, каков ваш критерий измерения, но вот несколько советов: (1) НЕ ВСТАВЛЯЙТЕ один за раз; пакетные запросы для сокращения сетевого трафика, (2) Разделите список на более мелкие фрагменты, которые вы фиксируете как единицу работы, чтобы вы не создали огромный сегмент отката, (3) Посмотрите, ускоряет ли параллельные потоки Java 8 , – duffymo

+1

Какой вкус SQL вы используете? Вероятно, вам придется получить довольно низкий уровень, если вы вставляете 500K в режиме реального времени. Например, MySQL имеет вызов LOAD INTO, который принимает входной поток, который намного быстрее, чем стандартная вставка пакета. –

+0

Прямо сейчас, Spring Integration не поддерживает эту функцию. Для этого есть запрос функции - https://jira.spring.io/browse/INT-3364. Итак, для этой цели я использую самозаписывающийся адаптер исходящего канала. – Eugene

ответ

0

я писал упомянутый пользовательский исходящий адаптер канала, который использует пружинный JDBC пакетное способность:

public class ArrayListSqlBatchOBCA { 

    private final static Logger   log = LoggerFactory.getLogger(ArrayListSqlBatchOBCA.class); 
    private NamedParameterJdbcTemplate template; 
    private String      sql; 

    public void process(Message<? extends ArrayList<?>> message) throws Exception { 

    try { 
      ArrayList<?> list = (ArrayList<?>) message.getPayload(); 

      SqlParameterSource[] batchArgs = new SqlParameterSource[list.size()]; 
      for (int i = 0; i < list.size(); i++) { 
       batchArgs[i] = new BeanPropertySqlParameterSource(list.get(i)); 
      } 

      template.batchUpdate(sql, batchArgs); 
     } 
     catch (Exception e) { 
      log.error("Exception while processing message", e); 
      throw e; 
     } 
    } 
} 

Это, как я использую его (XML конфигурации):

<channel id="cc"/> 
    <outbound-channel-adapter channel="cc" method="process"> 
     <beans:bean class="mypackage.ArrayListSqlBatchOBCA"> 
      <beans:property name="template" ref="jdbcTemplate"/> 
      <beans:property name="sql" 
      value="INSERT INTO test (field1,field2,field3) 
        VALUES (:f1,:f2,:f3)"/> 
    </beans:bean> 
    </outbound-channel-adapter> 

Кроме того, я добавил ?reWriteBatchedInserts=true в URL-адрес jdbc моего источника данных (я использую драйвер JDBC postgres).

Documentation about the option:

reWriteBatchedInserts - Включить оптимизацию переписать и разрушаться совместимые заявления INSERT, которые дозируют. Если включено, pgjdbc перезаписывает пакет insert into ... values(?, ?) в insert into ... values(?, ?), (?, ?), ...

Таким образом, используя небольшой пользовательский код, я вставляю сразу несколько строк из коллекции ввода.