簡體   English   中英

為什么我需要連接來創建PreparedStatements?

[英]Why do I need a connection to create PreparedStatements?

出於多種原因 ,我想使用准備好的陳述。 但是,我想創建一個如下所示的方法:

/* This opens a connection, executes the query, and closes the connection */
public static void executeNonQuery(String queryString);

換句話說,我希望我的應用程序邏輯只需要制定查詢和feed參數,但不要處理連接和語句。 但是,PreparedStatements是從連接對象創建的,因此我當前不得不使用String.format()來准備查詢字符串 - 這很丑陋且危險。

有沒有辦法在不使用String.format()的情況下做我想做的事情?

為什么我需要連接來創建PreparedStatements?

因為這些語句是在大多數RDBMS基於每個連接准備的。

准備好的語句實際上是緩存的執行計划,不會考慮您的權限,編碼,整理設置等。

所有這些都是在查詢解析期間完成的。

有沒有辦法在不使用String.format()情況下做我想做的事情

不明白為什么你需要String.format()

您可以將查詢實現為類,創建連接並在類構造函數中准備查詢,然后在方法中執行它。

參數化查詢通常如下所示:

SELECT  *
FROM    table
WHERE   col1 = ?
        AND col2 = ?

,綁定參數將被替換? 在查詢執行期間。

如果你想要一個static方法:

  • 創建static連接句柄。
  • 使用參數化查詢文本作為key創建准備好的查詢的static哈希表,並將准備好的查詢的句柄作為value
  • 每當您想要執行查詢時,找到它的句柄(或者如果找不到它就創建它)並使用來綁定參數並執行查詢。

為什么不讓您的“應用程序”邏輯使用您創建的可以呈現這種接口方法的數據層?

然后,您的數據層可以處理在executeNonQuery方法中創建連接,准備語句等。

我認為如果你試圖將查詢/語句中的參數自己合並到一個String中,那么你就是在自己的腳下拍攝,而實際上並沒有使用PreparedStatements的參數功能。 不知道你為什么要這樣做。

您可能還希望使用諸如Spring之類的API,它具有一系列JdbcTemplate類,可以抽象遠離您的所有連接處理,但仍允許您使用Map參數。

我通過讓我調用QueryRunner的類來抽象出所有JDBC的東西,該類具有一個帶有sql的execute方法,一個表示參數的對象List,以及一個將處理ResultSet的對象。 如果使用JDBC中的setObject方法設置參數,它將根據底層對象確定要使用的相應數據庫類型。 這是我的一部分代碼。 我有另一個方法來包裝這個並獲得連接。

public void executeNoCommit(Connection conn,
                            String sql, 
                            List params, 
                            ResultSetProcessor processor) throws SQLException {
    PreparedStatement stmt = null;
    ResultSet rs = null;
    int updateCount = 0;
    Iterator it;
    int paramIndex = 1;
    boolean query;

    try {
        stmt = conn.prepareStatement(sql);

        if (params != null) {
            it = params.iterator();
            while (it.hasNext()) {
                stmt.setObject(paramIndex, it.next());
                paramIndex++;
            }
        }

        query = stmt.execute();
        if (query) {
            rs = stmt.getResultSet();
        }
        else {
            updateCount = stmt.getUpdateCount();
        }

        processor.process(rs, updateCount);
    }
    finally {
        if (rs != null) {
            try {
                rs.close();
            }
            catch (SQLException e) {
                log.error(e);
            }
        }

        if (stmt != null) {
            try {
                stmt.close();
            }
            catch (SQLException e) {
                log.error(e);
            }
        }
    }
}

你可能想要像Apache Commons庫中的DbUtils包這樣的東西:[ http://commons.apache.org/dbutils/index.html] [1 ]

QueryRunner類允許您執行sql語句,而無需手動創建PreparedStatements,甚至可以打開連接。 從示例頁面:

QueryRunner run = new QueryRunner( dataSource );
try
{
    // Create an object array to hold the values to insert
    Object[] insertParams = {"John Doe", new Double( 1.82 )};
    // Execute the SQL update statement and return the number of
    // inserts that were made
    int inserts = run.update( "INSERT INTO Person (name,height) VALUES (?,?)",
                              insertParams );

    // Now it's time to rise to the occation...
    Object[] updateParams = {new Double( 2.05 ), "John Doe"};
    int updates = run.update( "UPDATE Person SET height=? WHERE name=?",
                              updateParams );
}
catch(SQLException sqle) {
    // Handle it
}

所以它基本上是透明地處理預准備語句的創建,而你真正需要知道的唯一事情是DataSource。 這也適用於非更新/插入語句,即普通選擇查詢,並且創建ResultSetHandlers的功能使您能夠將ResultSet轉換為類似完全准備好的bean或帶有鍵的Map。作為列名,值是實際的行值。 當您無法實現整個ORM解決方案時非常有用。

暫無
暫無

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

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