Именованные параметры в JDBC
есть ли именованные параметры в JDBC вместо позиционных, таких как @name
, @city
в ADO.NET запрос ниже?
select * from customers where name=@name and city = @city
6 ответов
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);
чтобы избежать включения большой структуры, я думаю, что простой домашний класс может сделать трюк.
пример класса для обработки именованных параметров:
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 framework, так как у него есть некоторые расширения, которые позволяют использовать именованные параметры в запросах.
в итоге я просто создаю мой собственный meothod фантик.
в котором я сначала санировал значение, связанное (вы можете найти примеры в Google)
затем просто использовал Java
String.replace()
метод для замены заполнителей.
самое большое падение заключается в том, что вы должны убедиться, что переменная действительно безопасна для привязки.
Edit: теперь я просто использую спящий режим весны, много лучше
обычный vanilla JDBC не поддерживает именованные параметры.
Если вы используете DB2, то используйте классы DB2 напрямую: