JDBC 中的命名参数

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

select * from customers where name=@name and city = @city
135919 次浏览

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

NamedParameter terJDBCTemplate 支持命名参数,您可以这样使用它们:

 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 本身中使用命名参数。您可以尝试使用 Spring 框架,因为它有一些扩展,允许在查询中使用命名参数。

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

普通的 JDBC 不支持命名参数。

如果您使用的是 DB2,那么直接使用 DB2类:

  1. 对 PreparedStatement 对象使用命名参数标记
  2. 对 CallableStatement 对象使用命名参数标记

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

处理命名参数的类示例:

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

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