2010-07-02 70 views
14

如何使用运行在mySQL上的JdbcTemplate以可伸缩的方式执行以下SQL。在这种情况下,可扩展的方式:使用JdbcTemplate插入多行

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

这里的语句:

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

假设我有POJO的与foobar字段列表。我意识到我可以迭代列表并执行:

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

但这并不能达到第一个标准。

,我相信我也可以执行:

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

但我可以告诉,这将只是编译SQL一次执行它多次,再次失败的第一个标准。

最后的可能性,似乎通过这两个标准,将简单地构建SQL自己与StringBuffer,但我想避免这种情况。

+0

我们能不能只使用JDBC一样吗? ? – 2010-07-02 12:54:15

+0

这与JdbcTemplate甚至JDBC无关。你不能在SQL,period(或标准SQL,无论如何)中这样做,所以你当然不能在JdbcTemplate中做到这一点。 – skaffman 2010-07-02 12:55:55

+0

@skaffman:我更新了我的问题,说我正在使用mySQL。也许它只是一个mySQL特性,但在http://dev.mysql.com/doc/refman/5.1/en/insert.html大约四分之一的地方描述了它:“使用VALUES语法的INSERT语句可以插入为了做到这一点,需要包含多个列值列表,每个列表值都包含在括号内,并用逗号分隔。例如:“ – 2010-07-02 13:01:05

回答

4

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

有些数据库不支持这种语法,但很多都可以。根据我的经验,Derby/Cloudscape,DB2,Postgresql和更新的Hypersonic 2.0 *发行版都支持这一点。

您对将此作为PreparedStatement使用的担忧是可以理解的,但我也见过类似的情况,Spring JDBC会自动处理某些查询的集合(例如(?)中的位置),但我无法保证对于这种情况。

我确实发现了一些可能有用的信息(不能添加第二个链接到这篇文章) 这可能有一些帮助。

我可以告诉你,它可能不适合你的第二个要求(适用于任意数量的参数)在最严格的意义上得到满足:我使用的每个数据库都会施加查询长度限制, 。

+0

SO以上不允许我发布的URL是:http://fusesource.com/docs/router/2.2/transactions/DataAccess-JDBC.html – Will 2010-10-15 18:42:48

-4

你不能在JDBC,期间这样做。在MySQL中它只是语法糖,但是语句的作用与发出几个INSERT语句相同。所以你可以使用batchUpdate,它会有相同的效果。

+1

不正确。 MySQL的“扩展插入”(如问题中提供的)比批量插入(您提前准备,但一次插入一行)的速度更快。它不是MySQL中的语法糖。 – 2013-07-04 06:39:52

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 2016-10-21 09:35:11

-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 2018-01-26 22:30:34

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

    }); 
}