Вставка нескольких строк с использованием JdbcTemplate - PullRequest
18 голосов
/ 02 июля 2010

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

  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, но я бы хотел этого избежать.

Ответы [ 5 ]

33 голосов
/ 16 января 2012

Вы можете использовать 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();
        }
    });

}
4 голосов
/ 15 октября 2010

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

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

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

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

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

0 голосов
/ 27 июля 2015

Мне кажется, что метод batchUpdate () JdbcTemplate может быть полезен в этом случае (скопировано здесь http://www.mkyong.com/spring/spring-jdbctemplate-batchupdate-example/):

//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();
}

  });
 }
0 голосов
/ 07 февраля 2014

вы также можете попробовать с 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 голосов
/ 14 октября 2010

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

...