2013-11-03 54 views
0

我有一個應用程序將大量數據記錄到MySQL數據庫。生產版本已經批量運行插入語句以提高性能。我們正在改變數據庫模式,以便將一些無關數據發送到我們可以加入查詢的不同表中。批量MySQL插入,一個主要記錄,一個具有外部密鑰的詳細記錄

但是,我試圖正確設計查詢以使用我們的批處理系統。我想使用mysql LAST_QUERY_ID,所以我不必擔心獲取生成的密鑰並將它們匹配起來(看起來像一個非常困難的任務)。

但是,我似乎無法找到一種方法來添加不同的插入語句到一個批處理,所以如何解決這個問題?我假設我需要構建第二批並添加所有詳細查詢,但這意味着LAST_QUERY_ID失去意義。

s = conn.prepareStatement("INSERT INTO mytable (stuff) VALUES (?)"); 
while (!queue.isEmpty()){ 
    s.setLong(1, System.currentTimeMillis()/1000L); 
    // ... set other data 
    s.addBatch(); 

    // Add insert query for extra data if needed 
    if(a.getData() != null && !a.getData().isEmpty()){ 
     s = conn.prepareStatement("INSERT INTO mytable_details (stuff_id,morestuff) 
            VALUES (LAST_INSERT_ID(),?)"); 
     s.setString(1, a.getData()); 
     s.addBatch(); 
    } 
} 
+0

你能再詳細一點嗎? 「你似乎無法找到方法」是什麼意思?上面的代碼是否會拋出異常呢? – hqcasanova

+0

上面的代碼將不起作用,因爲語句被覆蓋。如果有第二個查詢的數據,第一個查詢就不會運行。我不能讓它的工作沒有第二個語句變量/批處理,但然後查詢將運行不順序和last_insert_id是無用的 – helion3

+0

謝謝。我在下面添加了我的答案,但我不確定它是否會對您有所幫助。 – hqcasanova

回答

0

這不是如何配料的作品。批處理只能在一個StatementPreparedStatement內工作,這意味着您只能爲一個相同的語句添加批量參數。你的代碼也忽略了執行這些語句。

對於你想要做的,你應該使用setAutoCommit(false),執行兩條語句,然後執行commit()(或者如果發生錯誤,則回滾)。

另外我建議你看一下JDBC標準的檢索生成的密鑰的方法,因爲這會使你的代碼更少的MySQL特定。另請參閱Retrieving AUTO_INCREMENT Column Values through JDBC

0

我已經修復了現在,但我希望有更好的方法。我構建了一個額外數據值的數組列表,我可以將這些數據值與從批量插入返回的generatedKeys關聯起來。在第一個查詢批處理執行後,我使用正確的ID /數據構建第二批。