在JDBC中命名参数

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

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

JDBC不支持命名参数。 除非你肯定使用普通的JDBC(这会导致痛苦,让我告诉你),我会build议使用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); 

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

处理命名参数的类的示例:

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

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

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

我最终创造了自己的包装方法。

  1. 我首先清理了被绑定的价值(您可以在Google上find示例)

  2. 然后使用Java的String.replace()方法来replaceplaceHolders。

最大的不利之处是你必须确保这个variables对绑定来说确实是安全的。

编辑:我现在只是使用Spring的Hibernate,好多了

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

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

  1. 使用带有PreparedStatement对象的命名参数标记
  2. 使用具有CallableStatement对象的命名参数标记