Вставка нескольких строк с помощью JdbcTemplate

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

  • На сервере выполняется только один оператор SQL
  • он работает для любого количества строк.

Здесь утверждение:

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

Ответы

Ответ 1

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

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

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

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

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

Ответ 2

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

}

Ответ 3

Мне кажется, что метод 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();
}

  });
 }

Ответ 4

вы также можете попробовать с помощью 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);

Ответ 5

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