为什么需要连接来创建PreparedStatements?

发布于 2024-07-22 18:06:23 字数 487 浏览 3 评论 0原文

出于许多原因,我想使用准备好的语句。 但是,我想创建一个如下所示的方法:

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

换句话说,我希望我的应用程序逻辑只需制定查询并输入参数,而不处理连接和连接。 声明。 但是,PreparedStatements 是从连接对象创建的,因此我目前被迫使用 String.format() 准备查询字符串 - 但丑陋且危险。

有没有办法在不使用 String.format() 的情况下做我想做的事情?

I would like to use prepared statements, for many reasons.
But, I would like to create a method that looks like this:

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

In other words, I want my application logic to only have to formulate the queries and feed in parameters, but not deal with connections & statements. However, PreparedStatements are created from a connection object, so I am currently forced into preparing the query string using String.format() - butt ugly and dangerous.

Is there a way to do what I want without using String.format()?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

娇纵 2024-07-29 18:06:23

为什么我需要连接来创建PreparedStatements?

因为在大多数 RDBMS 中,语句是根据每个连接准备的。

准备好的语句实际上是缓存的执行计划,不考虑权限、编码、排序规则设置等。

所有这些都是在查询解析期间完成的。

有没有办法在不使用String.format()的情况下做我想做的事情

不明白为什么在这里需要 String.format()

您可以将查询实现为类,创建连接并在类构造函数中准备查询,然后在方法中执行它。

参数化查询通常如下所示:

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

,其中绑定参数将在查询执行期间替换 ?

如果您想要一个静态方法:

  • 创建一个静态连接句柄。
  • 使用参数化查询文本作为,并将准备查询的句柄作为,创建准备查询的静态哈希表。
  • 每当您想要执行查询时,找到其句柄(如果未找到则创建它)并使用 to 绑定参数并执行查询。

Why do I need a connection to create PreparedStatements ?

Because the statements are prepared on per-connection basis in most RDBMS's.

Prepared statements are in fact cached execution plans that don't take you permissions, encodings, collation settings etc. into account.

All this is done during query parsing.

Is there a way to do what I want without using String.format()

Don't see why you need String.format() here.

You can implement your query as a class, create a connection and prepare the query in the class constructor and then execute it in a method.

A parametrized query typically looks like this:

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

, where the bound parameters will be substituted for ?'s during the query execution.

If you want a static method:

  • Create a static connection handle.
  • Create a static hash table of prepared queries using the parametrized query text as a key, and the handle to the prepared query as a value.
  • Whenever you want to execute a query, find its handle (or create it if it wasn't found) and use to to bind the parameters and execute the query.
白色秋天 2024-07-29 18:06:23

为什么不让您的“应用程序”逻辑使用您创建的可以呈现这种接口方法的数据层?

然后,您的数据层可以处理创建连接、准备语句等,所有这些都在该 executeNonQuery 方法中进行。

我认为,如果您尝试将查询/语句中的参数自己合并到字符串中,那么您就是搬起石头砸自己的脚,实际上并没有使用PreparedStatements 的参数功能。 不知道你为什么要这样做。

您可能还想考虑使用 Spring 等 API,它具有一系列 JdbcTemplate 类,可以将所有连接处理从您手中抽象出来,但仍然允许您在地图

Why not have your "application" logic use a data layer which you create which can present that kind of interface method?

Your data layer can then handle creating connections, preparing statements, etc., all within that executeNonQuery method.

I think that if you are attempting to merge the parameters in your query/statement yourself into a String, then you are shooting yourself in the foot and actually not using the parameter functionality of PreparedStatements. Not sure why you would want to do this.

You might also want to look into using an API such as Spring, which has a series of JdbcTemplate classes that can abstract all of the connection handling away from you, but still allow you to work with parameters in a Map.

情独悲 2024-07-29 18:06:23

您可能需要 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
}

因此它基本上透明地处理准备好的语句的创建,您真正需要知道的唯一事情是数据源。 这也适用于非更新/插入语句,即普通选择查询,并且创建 ResultSetHandlers 的能力使您能够将 ResultSet 转换为完全准备好的 bean 或带有键的 Map 之类的东西是列名,值是实际行值。 当您无法实现整个 ORM 解决方案时非常有用。

You probably want something like the DbUtils package in the Apache Commons libraries: [http://commons.apache.org/dbutils/index.html][1]

The QueryRunner class lets you execute sql statements without having to manually create PreparedStatements, or even have an open connection for that matter. From the examples page:

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
}

So it basically handles the creation of prepared statements transparently, and the only thing you really need to know is a DataSource. This also works just as well for non-update/insert statements, i.e. plain-vanilla select queries, and the ability to create ResultSetHandlers gives you the power to convert a ResultSet into something like a fully-prepared bean, or a Map with the keys being the column names, and the values being the actual row values. Very useful for when you can't implement a whole ORM solution.

梦幻的心爱 2024-07-29 18:06:23

我通过一个名为 QueryRunner 的类抽象出所有 JDBC 内容,该类具有一个接受 sql 的执行方法、一个表示参数的对象列表以及一个将处理 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);
            }
        }
    }
}

I abstract out all of the JDBC stuff by having a class I call QueryRunner that has an execute method that takes the sql, a List of objects that represent the parameters, and an object that will process the ResultSet. If you use the setObject method from JDBC to set your parameters it will figure out the appropriate DB types to use based on the underlying object. Here is a portion of my code. I've got another method that wraps this one and get's the connection.

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);
            }
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文