25

如何使用在 mySQL 上运行的JdbcTemplate以可扩展的方式执行以下 SQL。在这种情况下,可扩展意味着:

  1. 服务器上只执行一条 SQL 语句
  2. 它适用于任意数量的行。

这是声明:

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

假设我有一个带有foobar字段的 POJO 列表。我意识到我可以遍历列表并执行:

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

但这并没有达到第一个标准。

我相信我也可以执行:

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

但据我所知,这只会编译一次 SQL 并多次执行,再次失败第一个标准。

最后一种可能性,似乎同时通过了这两个标准,就是自己简单地用 a 构建 SQL StringBuffer,但我想避免这种情况。

4

5 回答 5

43

您可以使用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();
        }
    });

}
于 2012-01-15T21:32:37.620 回答
5

多行插入(使用“行值构造函数”)实际上是 SQL-92 标准的一部分。请参阅 http://en.wikipedia.org/wiki/Insert_(SQL)#Multirow_inserts

一些数据库不支持这种语法,但很多支持。根据我的经验,Derby/Cloudscape、DB2、Postgresql 和较新的 Hypersonic 2.*+ 版本确实支持这一点。

您对让它作为 PreparedStatement 工作的担忧是可以理解的,但我看到类似的情况,Spring JDBC 确实为某些查询自动处理项目集合(比如 where in (?)),但我不能保证这种情况。

我确实在 (can't add second link to this post) 找到了一些可能有用的信息,这可能会有所帮助。

我可以告诉您,从最严格的意义上说,您的第二个要求(适用于任意数量的参数)可能无法满足:我使用的每个数据库确实都会施加查询长度限制。

于 2010-10-15T18:41:06.390 回答
4

在我看来, JdbcTemplate 的 batchUpdate() 方法在这种情况下可能会有所帮助(从这里复制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();
}

  });
 }
于 2015-07-27T11:20:18.273 回答
-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);
于 2014-02-07T09:40:22.690 回答
-4

您不能在 JDBC 中执行此操作,期间。在 MySQL 中它只是语法糖,但语句的效果将与发出多个 INSERT 语句相同。所以你可以使用batchUpdate,它会产生同样的效果。

于 2010-10-14T18:09:50.033 回答