Y a-t-il des paramètres nommés dans JDBC au lieu des paramètres positionnels, comme @name
, @city
dans la requête ADO.NET ci-dessous?Paramètres nommés dans JDBC
select * from customers where [email protected] and city = @city
Y a-t-il des paramètres nommés dans JDBC au lieu des paramètres positionnels, comme @name
, @city
dans la requête ADO.NET ci-dessous?Paramètres nommés dans JDBC
select * from customers where [email protected] and city = @city
JDBC ne prend pas en charge les paramètres nommés. Sauf si vous êtes obligé d'utiliser JDBC simple (ce qui provoque la douleur, laissez-moi vous dire que) Je suggère d'utiliser Springs Excellent JDBCTemplate qui peut être utilisé sans le conteneur IoC entier.
NamedParameterJDBCTemplate supports nommés paramètres, 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);
Merci - mais je ne peux pas utiliser de ressorts, parce que je ne peux pas faire autant de changement à la base de code existante :( – Fakrudeen
le point que @Malax est en train de faire est que vous pouvez utiliser le NamedParameterJdbcTemplate de spring standalone. –
Mais vous devez inclure de nombreux JARs de Spring dans votre projet, juste pour utiliser quelques classes liées au NamedParameterJdbcTemplate. ty le org.springframework.jdbc.jar ne peut pas être utilisé seul. – xmedeko
Vous ne pouvez pas utiliser les paramètres nommés dans JDBC lui-même. Vous pouvez essayer d'utiliser le framework Spring, car il possède des extensions qui permettent l'utilisation de paramètres nommés dans les requêtes.
Vanilla JDBC ne prend en charge que les paramètres nommés dans un CallableStatement
(par exemple setString("name", name)
), et même alors, je soupçonne que la mise en œuvre de la procédure stockée sous-jacente doit le supporter.
Un exemple de comment utiliser 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));
}
Oui c'est vrai, mais tous les db ne supportent pas cette fonctionnalité . J'ai testé sur postgresql ça ne marche pas. –
Oui, évidemment, la base de données doit d'abord prendre en charge les paramètres nommés ... et il semble que postgres ne le fasse pas. La question implique que leur base de données supporte cela, et veut comprendre comment utiliser la fonctionnalité dans JDBC. – Hotel
Plain vanilla JDBC ne prend pas en charge les paramètres nommés.
Si vous utilisez DB2 puis en utilisant des classes DB2 directement:
J'ai fini juste créer ma propre meothod wrapper.
où j'ai désinfecté la valeur étant liée (vous trouverez des exemples sur Google)
Puis juste utilisé la méthode de Java String.replace()
pour faire remplacer les espaces réservés.
La plus grosse chute est que vous devez vous assurer que la variable est sûre pour la reliure.
Edit: Je maintenant juste utiliser Hibernate Spring, beaucoup mieux
Pour éviter d'inclure un grand cadre, je pense une simple classe 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'appeler 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();
S'il vous plaît noter que l'exemple ci-dessus ne gère simplement pas deux fois en utilisant le paramètre nommé. Il ne gère pas non plus l'utilisation du signe: entre guillemets.
J'ai utilisé le vôtre avec quelques petites modifications. ' Motif findParametersPattern = Motif.compile (" (? WillieT
pense que je vais faire quelque chose de similaire. Je pense qu'il serait plus agréable de surcharger l'indexeur pour cela. –
@WillieT Pattern '(?! \\ B '[^'] *) (: \\ w +) (?! [^ '] *' \\ B) 'fonctionne mieux pour moi. – Furgas
duplication possible de [Utilisation d'une variable au lieu d'un index de paramètre avec une instruction préparée JDBC] (http://stackoverflow.com/questions/1097855/using-a-variable-instead-of-a-parameter-index- with-a-jdbc-prepared-statement) – bluish
Cet article propose une implémentation rapide d'une telle classe: http://www.javaworld.com/article/2077706/core-java/named-parameters-for-preparedstatement.html –