Y at-il des paramètres nommés dans JDBC au lieu de paramètres positionnels, comme le @name
, @city
dans la requête ADO.NET ci-dessous?
select * from customers where name=@name and city = @city
JDBC ne prend pas en charge les paramètres nommés. À moins que vous ne soyez obligé d'utiliser JDBC (ce qui cause une douleur, laissez-moi vous le dire), je suggérerais d'utiliser Springs Excellent JDBCTemplate, qui peut être utilisé sans le conteneur IoC complet.
NamedParameterJDBCTemplate supporte les paramètres nommés, vous pouvez les utiliser comme ça:
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);
Pour éviter d’inclure un grand cadre, je pense qu’un simple cours à la maison peut faire l'affaire.
Exemple de classe pour gérer les paramètres nommés:
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>();
}
Exemple d'appel de la classe:
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();
Veuillez noter que l'exemple simple ci-dessus ne gère pas l'utilisation du paramètre nommé deux fois. Il ne gère pas non plus l’utilisation du signe suivant entre guillemets.
Vanilla JDBC ne prend en charge que les paramètres nommés dans un CallableStatement
(par exemple, setString("name", name)
), et même dans ce cas, je suppose que l'implémentation de la procédure stockée sous-jacente doit le prendre en charge.
Un exemple d'utilisation des paramètres nommés:
//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));
}
Vous ne pouvez pas utiliser de paramètres nommés dans JDBC même. Vous pouvez essayer d'utiliser la structure Spring, car elle possède des extensions permettant d'utiliser des paramètres nommés dans les requêtes.