簡體   English   中英

使用單個 JDBC Statement 對象執行多個查詢

[英]Execute multiple queries using a single JDBC Statement object

在 JDBC 中,我可以使用單個Statement對象多次調用executeQuery("")嗎? 安全嗎? 或者我應該在每次查詢后關閉語句對象,並創建新對象來執行另一個查詢。

例如:

Connection con;
Statement s;
ResultSet rs;
ResultSet rs2;
try
{
    con = getConnection();
    s = con.prepareStatement();

    try
    {
        rs = s.executeQuery(".......................");

        // process the result set rs
    }
    finally
    {
        close(rs);
    }

    // I know what to do to rs here
    // But I am asking, should I close the Statement s here? Or can I use it again for the next query?

    try
    {
        rs2 = s.executeQuery(".......................");

        // process the result set rs2
    }
    finally
    {
        close(rs2);
    }
}
finally
{
    close(s);
    close(con);
}

是的,您可以重復使用Statement (特別是PreparedStatement ),並且通常應該使用 JDBC 這樣做。 如果您不重用您的語句並立即創建另一個相同的Statement對象,那將是低效和糟糕的風格。 至於關閉它,最好在 finally 塊中關閉它,就像您在此代碼段中一樣。

有關您要問的內容的示例,請查看此鏈接: jOOq Docs

我不確定你為什么要問。 API 設計和文檔表明,將Statement對象重用於多個executeexecuteUpdateexecuteQuery調用是非常好的(甚至有意)。 如果不允許,則會在 Java 文檔中明確記錄(並且 API 可能會有所不同)。

此外, Statement的 apidoc 說:

如果存在打開的對象,則Statement接口中的所有執行方法都會隱式關閉語句的 [原文如此] 當前ResultSet對象。

這表明您可以多次使用它。

TL;DR:是的,您可以多次對單個Statement對象調用execute ,只要您意識到任何先前打開的ResultSet將被關閉。

您的示例錯誤地使用PreparedStatement ,並且您不能(或:不應該)能夠調用任何接受PreparedStatement上的Stringexecute...方法

SQLException - 如果 [...] 在PreparedStatementCallableStatement該方法

但要答案PreparedStatement還有:一個的整個目的PreparedStatement是預編譯與參數占位符的聲明,並重新使用它與不同的參數值多次執行。

我在API 文檔中找不到任何可以說明您不應在給定PreparedStatement實例上多次調用executeQuery()內容。

但是你的代碼不會關閉PreparedStatement -到呼叫executeQuery()將拋出SQLException在這種情況下-但ResultSet是由返回executeQuery() 當您重新執行PreparedStatement時,ResultSet 會自動關閉 根據您的情況,您應該在不再需要它時關閉它。 我會關閉它,因為我認為不這樣做是不好的風格。

更新Upps,我錯過了您在兩個 try 塊之間的評論。 如果此時關閉 PreparedStatement,則不應該在沒有得到 SQLException 的情況下再次調用 executeQuery()。

Prepared Statement告訴數據庫記住您的查詢並准備好接受參數化變量以在該查詢中執行。 它很像一個存儲過程。

Prepared Statement主要完成兩件事:

  1. 它會自動轉義您的查詢變量以幫助防止 SQL 注入。

  2. 它告訴數據庫記住查詢並准備好接受變量。

數字 2 很重要,因為它意味着數據庫只需要解釋一次您的查詢,然后它就可以准備執行該過程。 所以它提高了性能。

您不應在執行調用之間關閉准備好的語句和/或數據庫連接。 這樣做效率低得令人難以置信,而且會比使用普通的舊Statement導致更多的開銷,因為您每次都指示數據庫創建一個過程並記住它。 即使數據庫被配置為“熱點”並且即使關閉PreparedStatement仍然記住您的查詢,您仍然會產生網絡開銷以及小的處理時間。

簡而言之,保持ConnectionPreparedStatement打開,直到您完成它們。

編輯:要評論不從執行中返回ResultSet ,這很好。 executeQuery將為剛剛執行的任何查詢返回ResultSet

首先我對你的代碼感到困惑

s = con.prepareStatement();

效果好嗎

s = con.createStatement();

我只是用一個 Statement 實例運行了兩次訪問 DB2 的代碼,而沒有在兩次操作之間關閉它。它運行良好。我想你也可以自己嘗試一下。

    String sql = "";
    String sql2 = "";
    String driver = "com.ibm.db2.jcc.DB2Driver";
    String url = "jdbc:db2://ip:port/DBNAME";
    String user = "user";
    String password = "password";
    Class.forName(driver).newInstance();
    Connection conn = DriverManager.getConnection(url, user, password);
    Statement statement = conn.createStatement();
    ResultSet resultSet = statement.executeQuery(sql);
    int count = 0;
    while (resultSet.next()) {
        count++;
    }
    System.out.println("Result row count of query number one is: " + count);
    count = 0;
    resultSet = statement.executeQuery(sql2);
    while (resultSet.next()) {
        count++;
    }
    System.out.println("Result row count of query number two is: " + count);

暫無
暫無

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

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