簡體   English   中英

在JDBC中一次執行多個語句

[英]Execute more than one statement at once in JDBC

我正在使用MySQL數據庫。 下一段創建一條記錄,並從創建的記錄中獲取ID:


    insertStmt = connection
                    .prepareStatement("INSERT INTO bugs (summary, status, report_date) VALUES (?, ?, ? )");
            //...
    insertStmt.executeUpdate();
    idQuery = connection.prepareStatement("SELECT LAST_INSERT_ID()");
    rs = idQuery.executeQuery();
    if (rs != null) {
                rs.next();
                return new Long(rs.getLong(1)).toString();
    }

現在,如果有兩個線程執行此操作並交錯執行,例如,第一個線程插入記錄,然后由第二個線程插入,之后第一個線程調用last_insert_id(),此線程對於第二個線程而言是錯誤的已經插入了一條記錄。
但是,使用同步可以解決此問題。 有沒有辦法可以在一個數據庫調用中執行兩個語句?

LAST_INSERT_ID每個連接有效,並且如您的問題所述,如果兩個線程中的兩個語句使用相同的連接,則可以具有競爭條件。

您有兩種解決方法:

1:每個線程使用單獨的連接(這並不容易,但這實際上是擴展和感知的最佳選擇;使用連接池)

2:使用executeUpdate的形式在同一API調用中記錄自動生成的密鑰 ,使您以后可以使用getGeneratedKeys讀取它,這樣就不必在第二個查詢中使用LAST_INSERT_ID ,從而避免了競爭情況。 您可以在准備好的語句中使用類似的prepareStatement形式。

選擇2可能是短期內您想要的。 選項2中的鏈接直接指向該API。 此鏈接是MySQL文章,概述了如何使用它。

根據https://dev.mysql.com/doc/refman/5.7/zh-CN/connector-j-reference-configuration-properties.html ,您應該能夠在JDBC連接字符串中添加?allowMultiQueries=true 這樣,您就可以在Statement#execute(String sql)調用中傳遞多個由分號分隔的Statement#execute(String sql)

編輯:或使用執行所需操作的存儲過程。 或者,正如您所說, synchronize Java代碼。

您可以嘗試使用Multiquery,將Insert和Select Last_INSERT_ID()組合在同一字符串中。

1)准備使用多重查詢的連接:“ jdbc:mysql://” + host +“ /” + database +“?allowMultiQueries = true”

2)將插入查詢與選擇結合起來:

multiQuerySqlString =“將錯誤(摘要,狀態,報告日期)插入VALUES(1、2、3); SELECT LAST_INSERT_ID()”

3)進行查詢並期望有多個結果集:

boolean isResultSet = statement.execute();

ResultSet res = statement.getResultSet();

if isResultSet = statement.getMoreResults();

// Second ReulstSet object
res = cs.getResultSet();

我希望它能起作用

如果必須在單個連接上完成所有操作,則可以要求驅動程序返回生成的ID:

insertStmt = connection.prepareStatement("...",PreparedStatement.RETURN_GENERATED_KEYS );
insertStmt.executeUpdate();
ResultSet rs = insertStatement.getGeneratedKeys();
Long id = null;
if (rs != null) 
{
  rs.next();
  id = rs.getLong(1);
}
connection.commit();
return id;

根據驅動程序,您可能需要一個不同的prepareStatement()調用,該調用將列名作為第二個參數:

insertStmt = connection.prepareStatement("INSERT ", new String[] {"ID"});

但是即使使用上面的代碼,您也應該在不同的物理連接上進行並發插入,以便能夠正確地控制您的事務。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM