2010-07-02 4 views
14

Как я могу выполнить следующий SQL с масштабируемым способом, используя JdbcTemplate, работающий на mySQL. В этом случае, масштабируемые средства:Вставка нескольких строк с использованием JdbcTemplate

  1. заявление только один SQL выполняется на сервере
  2. это работает для любого количества строк.

Вот заявление:

INSERT INTO myTable (foo, bar) VALUES ("asdf", "asdf"), ("qwer", "qwer") 

Предположим, что у меня есть список POJO с foo и bar полей. Я понимаю, что я мог бы просто перебрать список и выполнить:

jdbcTemplate.update("INSERT INTO myTable(foo, bar) VALUES (?, ?)", paramMap) 

, но это не не выполняет первый критерий.

Я считаю, что я мог бы также выполнить:

jdbcTemplate.batchUpdate("INSERT INTO myTable(foo, bar) VALUES (?, ?)", paramMapArray) 

, но от того, что я могу сказать, что будет просто скомпилировать SQL один раз и выполнить его несколько раз, снова провалив первый критерий.

Последняя возможность, которая, как представляется, проходит оба критерия, состоит в том, чтобы просто построить SQL сам с StringBuffer, но я бы хотел этого избежать.

+0

Можем ли мы сделать то же самое, используя только JDBC? ? –

+0

Это не имеет ничего общего с JdbcTemplate или даже JDBC. Вы не можете сделать это в SQL, периоде (или стандартном SQL, так или иначе), так что вы, конечно же, не сможете это сделать в JdbcTemplate. – skaffman

+0

@skaffman: Я обновил свой вопрос, чтобы сказать, что я использую mySQL. Возможно, это функция mySQL, но она описана в http://dev.mysql.com/doc/refman/5.1/en/insert.html примерно на четверть пути вниз: «Операторы INSERT, которые используют синтаксис VALUES, могут вставлять несколько строк.Чтобы сделать это, включите несколько списков значений столбцов, каждый из которых заключен в круглые скобки и разделен запятыми. Пример: « –

ответ

4

Многострочные вставки (с использованием конструкторов значений строк) на самом деле являются частью стандарта SQL-92. См. http://en.wikipedia.org/wiki/Insert_(SQL)#Multirow_inserts.

Некоторые базы данных не поддерживают этот синтаксис, но многие это делают. По моему опыту, Derby/Cloudscape, DB2, Postgresql и более новые версии Hypersonic 2. * + Поддерживают это.

Ваша забота о том, чтобы это работать как подготовленное состояние, понятно, но я видел похожие случаи, когда Spring JDBC автоматически обрабатывает коллекцию элементов для определенных запросов (например, где в (?)), Но я не могу ручаться для этого случая.

Я нашел некоторую, возможно, полезную информацию на (не могу добавить вторую ссылку на это сообщение) , который может быть полезен.

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

+0

, что этот URL-адрес, который не разрешил мне опубликовать выше, был: http://fusesource.com/docs/router/2.2/transactions/DataAccess-JDBC.html – Will

-4

Вы не можете сделать это в JDBC, период. В MySQL это просто синтаксический сахар, но эффект от оператора будет таким же, как выдача нескольких инструкций INSERT. Таким образом, вы можете использовать batchUpdate, и он будет иметь тот же эффект.

+1

Неверный. «Расширенная вставка» MySQL (как указано в Вопросе) быстрее, чем пакетная вставка (где вы готовите заранее, но вставляете по одной строке за раз). Это НЕ синтаксический сахар в MySQL. –

28

Вы можете использовать BatchPreparedStatementSetter, как показано ниже.

public void insertListOfPojos(final List<MyPojo> myPojoList) { 

    String sql = "INSERT INTO " 
     + "MY_TABLE " 
     + "(FIELD_1,FIELD_2,FIELD_3) " 
     + "VALUES " + "(?,?,?)"; 

    getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() { 

     @Override 
     public void setValues(PreparedStatement ps, int i) 
      throws SQLException { 

      MyPojo myPojo = myPojoList.get(i); 
      ps.setString(1, myPojo.getField1()); 
      ps.setString(2, myPojo.getField2()); 
      ps.setString(3, myPojo.getField3()); 

     } 

     @Override 
     public int getBatchSize() { 
      return myPojoList.size(); 
     } 
    }); 

} 
+0

У меня есть «Индекс параметров вне диапазона (1> номер параметров, которое равно 0) "при использовании: NamedParameters вместо?. Некоторое обновление для использования с NamedParameterJdbcTemplate? – luso

-1

вы также можете попробовать использовать jdbcInsert.executeBatch (sqlParamSourceArray)

// define parameters 
jdbcInsert = new SimpleJdbcInsert(jdbcTemplate); 
jdbcInsert.withTableName("TABlE_NAME"); 
SqlParameterSource[] sqlParamSourceArray = new SqlParameterSource[apiConsumer 
     .getApiRoleIds().size()]; 
for (int i = 0; i < myCollection.size(); i++) 
    { 
    sqlParamSourceArray[i] = new MapSqlParameterSource().addValue("COL1"); 
     ...................... 
} 
// execute insert 
int[] keys = jdbcInsert.executeBatch(sqlParamSourceArray); 
+0

Этот ответ неверен! 'jdbcInsert.executeBatch()' НЕ возвращает ключи. Он возвращает 'массив числа строк, затронутых как возвращаемый драйвером JDBC'. См. Javadocs. https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/core/simple/SimpleJdbcInsert.html#executeBatch-org.springframework.jdbc.core.namedparam.SqlParameterSource – Stewart

0

Мне кажется, что метод batchUpdate() из JdbcTemplate может быть полезным в этом случае (скопировано отсюда):

//insert batch example 
public void insertBatch(final List<Customer> customers){ 

    String sql = "INSERT INTO CUSTOMER " + 
    "(CUST_ID, NAME, AGE) VALUES (?, ?, ?)"; 

    getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() { 

@Override 
public void setValues(PreparedStatement ps, int i) throws SQLException { 
    Customer customer = customers.get(i); 
    ps.setLong(1, customer.getCustId()); 
    ps.setString(2, customer.getName()); 
    ps.setInt(3, customer.getAge()); 
} 

@Override 
public int getBatchSize() { 
    return customers.size(); 
} 

    }); 
} 
Смежные вопросы