2012-05-18 74 views
2

我有以下方法。註釋方法saveOrUpdateToDatabase執行得很好,但我想使用executeBatch。我錯過了什麼?收到executeBatch()結果的int [] r始終爲空......SQL PreparedStatement.executeBatch()在SQLite不工作

public boolean saveOrUpdate(MonitoredData mData) { 
     try { 
      PreparedStatement prep; 
      String timeID = this.getTimeLastRowID(); 

      for (CpuData o : mData.getCpu()) { 
       prep = this.conn.prepareStatement(String.format(
         INSERT_CPU_USAGE, this.nodeID, timeID, o.toString())); 
       prep.addBatch(); 
       // saveOrUpdateToDatabase(String.format(INSERT_CPU_USAGE, 
       // this.nodeID, timeID, o.toString())); 
      } 
      for (DiskData o : mData.getDisk()) { 
       prep = this.conn.prepareStatement(String.format(
         INSERT_DISK_USAGE, this.nodeID, timeID, o.toString())); 
       prep.addBatch(); 
       // saveOrUpdateToDatabase(String.format(INSERT_DISK_USAGE, 
       // this.nodeID, timeID, o.toString())); 

      } 
      for (NetworkData o : mData.getNet()) { 
       prep = this.conn.prepareStatement(String 
         .format(INSERT_NETWORK_USAGE, this.nodeID, timeID, o 
           .toString())); 
       prep.addBatch(); 
       // saveOrUpdateToDatabase(String.format(INSERT_NETWORK_USAGE, 
       // this.nodeID, timeID, o.toString())); 

      } 

      prep = this.conn.prepareStatement(String.format(
        INSERT_MEMORY_USAGE, this.nodeID, timeID, mData.getMem() 
          .toString())); 
      // saveOrUpdateToDatabase(String.format(INSERT_MEMORY_USAGE, 
      // this.nodeID, timeID, mData.getMem().toString())); 

      conn.setAutoCommit(false); 
      int[] r = prep.executeBatch(); 
      conn.setAutoCommit(true); 

      return true; 

     } catch (SQLException ex) { 
      Logger.getLogger(HistoricalDatabase.class.getName()).log(
        Level.SEVERE, null, ex); 
     } 
     return false; 
    } 
+1

我對批次不熟悉,但看起來您正在爲預備聲明添加一個批次,但隨後用新的語句替換該預備聲明。最後,你指定準備一個新的預備語句,但不要調用addBatch(),然後調用executeBatch(),所以看起來你總是在執行最後一個準備語句的批處理,這是你永遠不會調用addBatch ()之前。 – Luciano

+0

它也看起來像您正在使用preparedStatement作爲常規語句,因爲您正在設置SQL字符串中的參數,而不是使用PreparedStatement類提供的設置器。 – Luciano

回答

5

您正在錯誤地使用addBatch()方法。在你的代碼正在做的:

for (CpuData o : mData.getCpu()) { 
    // this is wrong, you can not prepare a new query each time 
    prep = this.conn.prepareStatement(INSERT_CPU_USAGE); 
    prep.setObject(1, this.nodeID); 
    prep.addBatch(); 
} 

取代每次準備好的查詢。你只應該每批打一次電話prepareStatement(...)。你應該做下面的事情。你將不得不改變你的INSERT語句有?參數:正在使用的只有一個prepareStatement()呼叫

PreparedStatement prep = conn.prepareStatement(INSERT_CPU_USAGE); 
for (CpuData o : mData.getCpu()) { 
    prep.setObject(1, this.nodeID); 
    prep.setObject(2, timeID); 
    prep.setObject(3, o); 
    prep.addBatch(); 
} 
prep.executeBatch(); 

通知。其中有? SQL參數實體,然後在prep.setString(1, ...)的循環中分配這些實體。當批次準備好執行時,您可以撥打prep.executeBatch(),但這是而不是曾替代您正在執行的prep準備好的陳述。

如果你想在同一批次中的行執行一系列不同 INSERT語句,那麼你應該考慮關閉自動提交,做你的語句,調用commit,然後打開自動提交回上。例如:

conn.setAutoCommit(false); 
// statements prepared and executed here 
// maybe no need for batch operations 
... 
conn.commit(); 
conn.setAutoCommit(true); 
+0

我想我有另一個問題。我的INSERT_CPU_USAGE是「INSERT INTO CpuUsage(NODE_ID,TIME_ID,CORE_ID,USER,NICE,SYSMODE,IDLE,IOWAIT,IRQ,SOFTIRQ,STEAL,GUEST)VALUES(?,?,?);」正如你之前看到的,我通過節點ID,時間和第三個「?」是來自getCPu和所有其他值的字符串。但是這導致我「12列3個值」的例外。它解析插入和比較?的數量? =/ –

+0

不知道我理解,但是你的'INSERT'語句中的列數應該匹配'VALUES'的數量。 'INSERT INTO CpuUsage(NODE_ID,TIME_ID,USER)VALUES(?,?,?)'。如果'getCPu'返回「所有其他值」,那麼你需要將它們分解出來並逐個設置它們,並有12個「?」字段。 – Gray

-1

除了我寫的評論,我會冒險給出答案。如果您嘗試如下所示:

public boolean saveOrUpdate(MonitoredData mData) { 
    try { 
     PreparedStatement prep; 
     String timeID = this.getTimeLastRowID(); 
     conn.setAutoCommit(false); 
     for (CpuData o : mData.getCpu()) { 
      prep = this.conn.prepareStatement(INSERT_CPU_USAGE); 
      prep.setObject(1, this.nodeID); 
      prep.setObject(2, timeID); 
      prep.setObject(3, o); 
      prep.addBatch(); 
      // saveOrUpdateToDatabase(String.format(INSERT_CPU_USAGE, 
      // this.nodeID, timeID, o.toString())); 
     } 
     prep.executeBatch(); 
     for (DiskData o : mData.getDisk()) { 
      prep = this.conn.prepareStatement(INSERT_DISK_USAGE); 
      prep.setObject(1, this.nodeID); 
      prep.setObject(2, timeID); 
      prep.setObject(3, o); 
      prep.addBatch(); 
      // saveOrUpdateToDatabase(String.format(INSERT_DISK_USAGE, 
      // this.nodeID, timeID, o.toString())); 
     } 
     prep.executeBatch(); 
     for (NetworkData o : mData.getNet()) { 
      prep = this.conn.prepareStatement(INSERT_NETWORK_USAGE); 
      prep.setObject(1, this.nodeID); 
      prep.setObject(2, timeID); 
      prep.setObject(3, o); 
      prep.addBatch(); 
      // saveOrUpdateToDatabase(String.format(INSERT_NETWORK_USAGE, 
      // this.nodeID, timeID, o.toString())); 

     } 
     prep.executeBatch(); 
     prep = this.conn.prepareStatement(INSERT_MEMORY_USAGE); 
     prep.setObject(1, this.nodeID); 
     prep.setObject(2, timeID); 
     prep.setObject(3, o); 
     prep.executeUpdate(); 
     // saveOrUpdateToDatabase(String.format(INSERT_MEMORY_USAGE, 
     // this.nodeID, timeID, mData.getMem().toString())); 

     conn.setAutoCommit(true); 
     return true; 

    } catch (SQLException ex) { 
     Logger.getLogger(HistoricalDatabase.class.getName()).log(
       Level.SEVERE, null, ex); 
    } 
    return false; 
} 

您可能需要修改常量中定義的那些SQL查詢。

+0

這與OP有相同的錯誤。他無法以這種方式準備多個陳述。看我的帖子。 – Gray

+0

你是對的,我的意圖是在for之前設置任務,但是我忘了在複製粘貼他的代碼時移動它。對不起 – Luciano