JDBC 中的命名参数

2022-08-31 12:15:07

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

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

答案 1

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);

答案 2

为了避免包含大型框架,我认为一个简单的自制类可以做到这一点。

处理命名参数的类示例:

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

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

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

    private int getIndex(String name) {
        return fields.indexOf(name)+1;
    }
    private PreparedStatement prepStmt;
    private List<String> fields = new ArrayList<String>();
}

调用类的示例:

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

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


推荐