JDBC 中的命名参数

发布于 2024-08-23 04:50:36 字数 168 浏览 10 评论 0原文

JDBC 中是否有命名参数而不是位置参数,例如下面 ADO.NET 查询中的 @name@city

select * from customers where name=@name and city = @city

Are there named parameters in JDBC instead of positional ones, like the @name, @city in the ADO.NET query below?

select * from customers where name=@name and city = @city

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

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

发布评论

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

评论(5

少女七分熟 2024-08-30 04:50:36

JDBC 不支持命名参数。除非你一定要使用普通的 JDBC(这会带来痛苦,让我告诉你),我建议使用 Springs Excellent JDBCTemplate,它可以在没有整个 IoC 容器的情况下使用。

NamedParameterJDBCTemplate支持命名参数,你可以这样使用它们:

 NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);

 MapSqlParameterSource paramSource = new MapSqlParameterSource();
 paramSource.addValue("name", name);
 paramSource.addValue("city", city);
 jdbcTemplate.queryForRowSet("SELECT * FROM customers WHERE name = :name AND city = :city", paramSource);

JDBC does not support named parameters. Unless you are bound to using plain JDBC (which causes pain, let me tell you that) I would suggest to use Springs Excellent JDBCTemplate which can be used without the whole IoC Container.

NamedParameterJDBCTemplate supports named parameters, you can use them like that:

 NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);

 MapSqlParameterSource paramSource = new MapSqlParameterSource();
 paramSource.addValue("name", name);
 paramSource.addValue("city", city);
 jdbcTemplate.queryForRowSet("SELECT * FROM customers WHERE name = :name AND city = :city", paramSource);
单身情人 2024-08-30 04:50:36

为了避免包含大型框架,我认为一个简单的自制类就可以解决问题。

处理命名参数的类示例:

public class NamedParamStatement implements AutoClosable {

    private final PreparedStatement prepStmt;
    private final List<String> fields = new ArrayList<>();

    public NamedParamStatement(final Connection conn, String sql) throws SQLException {
        int pos;
        while((pos = sql.indexOf(":")) != -1) {
            int end = sql.indexOf(" ", pos);
            if (end == -1) {
                end = sql.length();
            }
            fields.add(sql.substring(pos + 1,end));
            sql = sql.substring(0, pos) + "?" + sql.substring(end);
        }       
        prepStmt = conn.prepareStatement(sql);
    }

    public void close() throws SQLException {
        prepStmt.close();
    }
    public PreparedStatement getPreparedStatement() {
        return prepStmt;
    }
    public ResultSet executeQuery() throws SQLException {
        return prepStmt.executeQuery();
    }

    public void setInt(final String name, final int value) throws SQLException {        
        prepStmt.setInt(getIndex(name), value);
    }

    private int getIndex(final String name) {
        return fields.indexOf(name) + 1;
    }
}

调用该类的示例:

String sql = "SELECT id, Name, Age, TS FROM TestTable WHERE Age < :age OR id = :id";
try (NamedParamStatement stmt = new NamedParamStatement(conn, sql))
{
    stmt.setInt("age", 35);
    stmt.setInt("id", 2);
    ResultSet rs = stmt.executeQuery();
}

请注意,上面的简单示例不处理两次使用命名参数。它也不处理在引号内使用 : 符号。

To avoid including a large framework, I think a simple homemade class can do the trick.

Example of class to handle named parameters:

public class NamedParamStatement implements AutoClosable {

    private final PreparedStatement prepStmt;
    private final List<String> fields = new ArrayList<>();

    public NamedParamStatement(final Connection conn, String sql) throws SQLException {
        int pos;
        while((pos = sql.indexOf(":")) != -1) {
            int end = sql.indexOf(" ", pos);
            if (end == -1) {
                end = sql.length();
            }
            fields.add(sql.substring(pos + 1,end));
            sql = sql.substring(0, pos) + "?" + sql.substring(end);
        }       
        prepStmt = conn.prepareStatement(sql);
    }

    public void close() throws SQLException {
        prepStmt.close();
    }
    public PreparedStatement getPreparedStatement() {
        return prepStmt;
    }
    public ResultSet executeQuery() throws SQLException {
        return prepStmt.executeQuery();
    }

    public void setInt(final String name, final int value) throws SQLException {        
        prepStmt.setInt(getIndex(name), value);
    }

    private int getIndex(final String name) {
        return fields.indexOf(name) + 1;
    }
}

Example of calling the class:

String sql = "SELECT id, Name, Age, TS FROM TestTable WHERE Age < :age OR id = :id";
try (NamedParamStatement stmt = new NamedParamStatement(conn, sql))
{
    stmt.setInt("age", 35);
    stmt.setInt("id", 2);
    ResultSet rs = stmt.executeQuery();
}

Please note that the above simple example does not handle using named parameter twice. Nor does it handle using the : sign inside quotes.

不打扰别人 2024-08-30 04:50:36

Vanilla JDBC 仅支持 CallableStatement 中的命名参数(例如 setString("name", name)),即使如此,我怀疑底层存储过程实现也必须支持它。

如何使用命名参数的示例:

//uss Sybase ASE sysobjects table...adjust for your RDBMS
stmt = conn.prepareCall("create procedure p1 (@id int = null, @name varchar(255) = null) as begin "
        + "if @id is not null "
        + "select * from sysobjects where id = @id "
        + "else if @name is not null "
        + "select * from sysobjects where name = @name "
        + " end");
stmt.execute();

//call the proc using one of the 2 optional params
stmt = conn.prepareCall("{call p1 ?}");
stmt.setInt("@id", 10);
ResultSet rs = stmt.executeQuery();
while (rs.next())
{
    System.out.println(rs.getString(1));
}


//use the other optional param
stmt = conn.prepareCall("{call p1 ?}");
stmt.setString("@name", "sysprocedures");
rs = stmt.executeQuery();
while (rs.next())
{
    System.out.println(rs.getString(1));
}

Vanilla JDBC only supports named parameters in a CallableStatement (e.g. setString("name", name)), and even then, I suspect the underlying stored procedure implementation has to support it.

An example of how to use named parameters:

//uss Sybase ASE sysobjects table...adjust for your RDBMS
stmt = conn.prepareCall("create procedure p1 (@id int = null, @name varchar(255) = null) as begin "
        + "if @id is not null "
        + "select * from sysobjects where id = @id "
        + "else if @name is not null "
        + "select * from sysobjects where name = @name "
        + " end");
stmt.execute();

//call the proc using one of the 2 optional params
stmt = conn.prepareCall("{call p1 ?}");
stmt.setInt("@id", 10);
ResultSet rs = stmt.executeQuery();
while (rs.next())
{
    System.out.println(rs.getString(1));
}


//use the other optional param
stmt = conn.prepareCall("{call p1 ?}");
stmt.setString("@name", "sysprocedures");
rs = stmt.executeQuery();
while (rs.next())
{
    System.out.println(rs.getString(1));
}
ゞ记忆︶ㄣ 2024-08-30 04:50:36

您不能在 JDBC 本身中使用命名参数。您可以尝试使用 Spring 框架,因为它有一些扩展允许在查询中使用命名参数。

You can't use named parameters in JDBC itself. You could try using Spring framework, as it has some extensions that allow the use of named parameters in queries.

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