2013-01-17 19 views
0

下面的代碼的問題是,假設如果查詢[]數組中的特定查詢包含錯誤,語句查詢將執行並且將拋出具有錯誤的查詢的異常,如果兩個查詢都是無錯誤的,或者其他都不應該執行,那麼希望兩個查詢都能被執行,那麼我應該如何處理下面的代碼以獲得期望的結果?請幫助。在Java中的addBatch()執行

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {           
     int rw = jTable1.getRowCount(); 
     int col = jTable1.getColumnCount(); 
     System.out.println("RC" + rw); 
     System.out.println("Col" + col); 
     String queries[] = new String[rw]; 
     Object o[][] = new Object[rw][col]; 
     String poid = jComboBox10.getSelectedItem().toString(); 
     java.sql.Date xdate = null; 
     Connection con=null; 
     Statement st=null; 
     String cc = ims.MainWindow.cc; 
     try { 
      for (int i = 0; i < rw; i++) { 
       for (int j = 0; j < col; j++) { 
        o[i][j] = jTable1.getValueAt(i, j); 
        System.out.println("imj" + i + "," + j + "=" + o[i][j]); 
       } 
       if (String.valueOf(o[i][5]) == "") { 
        xdate=null; 
       } 
       else { 
             xdate = new java.sql.Date(df.parse(String.valueOf(o[i][5])).getTime()); 

       } 
       queries[i] = "insert into po_items values('" + poid + "','" + cc + "','" + o[i][1] + "'," + o[i][2] + "," + o[i][4] + ",'" + xdate + "','" + o[i][7] + "'," + o[i][8] + ")"; 
      } 

      for (int k = 0; k < rw; k++) { 
       System.out.println(queries[k]); 
      } 
      String query = "insert into tablex values('xx','yy')"; 
      con=CPool.getConnection(); 
      st=con.createStatement(); 
       con.setAutoCommit(false); 
       for(int l=0;l<rw;l++) 
       { 
        st.addBatch(queries[l]); 
       } 
       st.addBatch(query); 
       st.executeBatch(); 
       con.commit(); 
      System.out.println(query); 
     } catch (Exception x) { 
      System.out.println(x.getMessage()); 
     } 
     finally { 
       CPool.closeConnection(con); 
       CPool.closeStatement(st); 
     } 

    }   
+3

**警告:**您的代碼容易受到[SQL注入攻擊](https://en.wikipedia.org/wiki/SQL_injection)的影響。爲了避免這個漏洞(並獲得一些額外的好處),使用準備好的語句並使用'set *'方法設置參數。 –

回答

1

你不知道查詢是否會出錯,除非你執行/觸發查詢。

但是,您可以做的是將查詢分組到數據庫事務中,如果一切正常,則執行提交,如果任何查詢失敗,則執行提交。您可以使用try catch塊來實現此目的(對異常執行回滾;否則提交)。

+0

我想補充一點,他已經那樣做了,不是嗎?如果execBatch拋出一個SQLException,con.commit將不會被執行。或者我錯過了什麼...... – Fildor

+0

@Fildor我沒有看到他做了回滾,這對於模仿沒有執行查詢的行爲很重要。答案還是要強調,查明查詢是否會失敗而不執行它並不容易。 – Scorpion

+0

啊,當然還有......你是對的。 – Fildor

1

如果發生異常,則在關閉連接之前既不執行rollback也不執行commit,這會導致未指定的行爲。只要try塊未正常完成,您必須rollback

單獨注意,僅當您將它與PreparedStatement組合使用時,使用JDBC批處理API纔會帶來性能,批處理條目僅在相同語句的參數中變化。正如其他地方所建議的,無論您是否希望避免SQL注入攻擊,PreparedStatement都是您的選擇。

+1

附加說明:如果數據庫實際上支持批處理,批處理將僅添加性能(通過'PreparedStatement'),否則驅動程序將僅模擬批處理。但是,在支持批處理的數據庫上,即使使用普通的'Statement',實際上也可能帶來輕微的性能優勢,因爲驅動程序可能一次發送所有查詢:而不是'N x(發送查詢,接收查詢結果) ,它變成'發送(N×查詢),接收(N×查詢結果)'。 –

+1

@MarkRotteveel +1我也認爲,如果你一直使用相同結構的語句,即使語句沒有準備好,你也可能會遇到加速。一如既往,服從特定的驅動程序。但我不想淡化我的主要觀點,所以我沒有在答案中包含這些微妙之處。 –