2010-07-02 72 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(); 
} 

    }); 
}