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