2014-11-14 26 views
1

我創建了一個自定義函數來在我的MySQL數據庫中插入數據。這些函數首先根據給定的輸入創建一個查詢。該查詢將看起來像INSERT INTO tableName (columnName1, ..., columnNamei) VALUES (?, ..., ?), ..., (?, ...,?)。之後,需要製作PreparedStatement,其中包含真實值。這些需要添加到批處理中,因爲我想一次添加多行(如此處所示:Java: Insert multiple rows into MySQL with PreparedStatement)。下面是代碼:Java:用Prepared Statements在MySQL數據庫中插入批處理數據

insertData()函數

public static void insertData(String table, List<HashMap<String, Object>> list) throws SQLException { 

    //Create query: make sure all of the rows in the table get the same amount of values passed 
    //Prepare colnames string 
    String colNamesParsed = ""; 
    int counter = 1; 

    //Iterate over only the first hashmap of the list (THATS WHY ALL THE ROWS NEED TO HAVE THE SAME AMOUNT OF VALUES PASSED) 
    for (String colName : list.get(0).keySet()) { 

     //Check if it is the last col name 
     if (counter != list.get(0).keySet().size()) { 
      colNamesParsed = colNamesParsed + colName+", "; 
     } 
     else { 
      colNamesParsed = colNamesParsed + colName; 
     } 

     counter++; 
    } 

    //Now create the place holder for the query variables 
    String queryVariablesPlaceholder = ""; 
    int rowSize = 0; 
    for (HashMap<String, Object> row : list) { 

     //This part is to check if all row sizes are equal 
     if (rowSize == 0) { 
      rowSize = row.values().size(); 
     } 
     else { 
      //Check if the rowsize is equal for all rows 
      if (row.values().size() != rowSize) { 
       System.out.println("The rows of the arrays are from a different size"); 
       return; 
      } 
     } 

     String queryVariablesRow = "(?, "; 
     for (int j = 1; j < (row.values().size()-1); j++) { 
      queryVariablesRow = queryVariablesRow+"?, "; 
     } 
     queryVariablesRow = queryVariablesRow+"?)"; 

     //Make sure the query does not start with a comma 
     if (queryVariablesPlaceholder.equals("")) { 
      queryVariablesPlaceholder = queryVariablesRow; 
     } 
     else { 
      queryVariablesPlaceholder = queryVariablesPlaceholder+", "+queryVariablesRow; 
     } 
    } 

    //The MySQL query needs to be built now 
    String query = "INSERT INTO "+table+" ("+colNamesParsed+") VALUES "+queryVariablesPlaceholder+";"; 
    System.out.println(query); 

    //Init prepared statement 
    PreparedStatement statement = con.prepareStatement(query); 

    for (HashMap<String, Object> map : list) { 

     int varCounter = 1; 
     //Iterate over all values that need to be inserted 
     for (Object object : map.values()) { 

      if (object instanceof Integer) { 
       statement.setInt(varCounter, Integer.parseInt(object.toString())); 
      } 
      else if (object instanceof String) { 
       statement.setString(varCounter, object.toString()); 
      } 
      else if (object instanceof Timestamp) { 
       statement.setTimestamp(varCounter, parseStringToTimestamp(object.toString())); 
      } 
      else if (object instanceof Double) { 
       statement.setDouble(varCounter, Double.parseDouble(object.toString())); 
      } 
      System.out.println(varCounter); 
      varCounter++; 
     } 

     //Add row to the batch 
     try { 
      statement.addBatch(); 
     } 
     catch (SQLException e) { 
      e.printStackTrace(); 
     } 

    } 
    //Execute the query, which is in fact the batch 
    statement.executeBatch(); 
} 

當我想在數據庫中插入一些數據,我執行下面的代碼:

功能部分

List<HashMap<String, Object>> list = new ArrayList<>(); 
    for (Object object : listOfObjects) { 
     HashMap<String, Object> map = new HashMap<>(); 
     map.put("columnName1", object.getSomeValue()); 
     /....../ 
     map.put("columnName2", object.getSomeOtherValue()); 

     list.add(map); 
    } 

    Functions.insertData("tableName", list); 

創建動態查詢似乎完美。但是,我無法使statement.addBatch()正常工作。它不斷給我下面的錯誤:

java.sql.SQLException: No value specified for parameter 9 

我不明白這一點,因爲我只有8個參數在批處理的各單位通過。我的目標表有9列,所以我試圖爲該列添加一個值,但它說:No value specified for parameter 10,所以它好像不關閉「批處理單元」或其他東西。

我在這裏錯過了什麼?

任何幫助,非常感謝!

+0

您可能想閱讀批處理語句(請參閱[此問題](例如)(http://stackoverflow.com/questions/3784197/efficient-way-to-do-do-batch-inserts-with-jdbc)) – 2014-11-14 12:26:21

+0

感謝您的評論@RC。如果我添加'statement.clearParameters()',我得到這個錯誤:'java.sql.SQLException:沒有爲參數1指定值。所以不會改變這種情況。此外,我認爲我的代碼與您的示例中提到的代碼相同。 – bashoogzaad 2014-11-14 12:42:21

回答

1

INSERT INTO tableName (columnName1, ..., columnNamei) VALUES (?, ..., ?), ..., (?, ...,?) 

是不是標準的SQL語法。 如果你使用這個JDBC,將爲每個「?」指定一個參數在你的查詢中。

用途:

INSERT INTO表名(columnName1,...,columnNamei)VALUES

和每個語句添加到批處理(,...?)。

+0

感謝您的回答!在這個例子中(http://stackoverflow.com/questions/4355046/java-insert-multiple-rows-into-mysql-with-preparedstatement)有說我正在使用標準的SQL語法。 – bashoogzaad 2014-11-14 13:04:38

+0

我想到了這一點:我已經基於這個例子的代碼:http://www.electrictoolbox.com/mysql-insert-multiple-records/,從中我得出結論,我需要多個(?,? ?....?)。對於批處理功能,只有一個就足夠了。誰能告訴我爲什麼會出現這種情況? – bashoogzaad 2014-11-14 15:41:03

+0

當您使用批量更新+ PreparedStatement時,會發生什麼情況是: 1. SQL只編譯一個,而不是每次執行。這是一次節省; 2.所有插入數據都發送到數據庫並批量執行,這意味着它不使用循環發送語句+執行它+將結果/錯誤返回給客戶端。這是另一個節省時間。 它基本上等效於插入多個(?,..?),即使在表演中。 – 2014-11-14 17:24:06