Statement vs PreparedStatement
Quando frequentavo l’università mi chiedevo quale fosse effettivamente la differenza tra uno Statement e un PreparedStatement Java. Fondamentalmente mi permettevano di raggiungere lo stesso risultato in maniera lievemente diversa.
In realtà i due costrutti sono molto più diversi di quanto non si creda. Ogni comando SQL ricevuto dal DBMS viene elaborato seguendo 3 fasi:
- Compilazione (parsing del comando SQL);
- Esecuzione;
- Fetching (restituzione del risultato al client).
Supponendo che vengano eseguite molte operazioni, la classe PreparedStatement permette di eseguire il passo di compilazione una sola volta, la prima, e poi di aggiornarne i valori in seguito:
"SELECT * FROM TABELLA WHERE CAMPO = ?");
Iterator ricerca = lista.iterator();
while(ricerca.hasNext()){
pstmt.setString(1, (String)ricerca.next());
ResultSet rs = pstmt.executeQuery();
while(rs.next()){
//Get results
}
//...
}
Questo si concretizza in un miglioramento delle performance, generalmente. Ciò non è sempre vero, ci sono altri fattori che entrano in gioco che possono rendere uno Statement più veloce di un PreparedStatement. A mio avviso anche se fosse, una leggera diminuzione di performance (che dipende moltissimo dal database utilizzato) per il PreparedStatement è sicuramente ben accetta data la sua grande flessibilità. Non solo, dalle FAQ Oracle ho appreso anche che ci sono dei benefici in termini di sicurezza nell’utilizzo di PreparedStatement: il binding dei dati, infatti, eviterebbe un considerevole numero di attacchi di tipo SQL Injection. La FAQ infatti riporta:
“Statements may be slightly faster if you are only going to execute the SQL once. PreparedStatements are much faster when the SQL will be executed more than once. If you are using the statement cache, which you should, getting a statement from the cache is the same as executing the same statement.
In general we strongly recommend that you use PreparedStatements. This is especially true if you are sending user provided data in the SQL. By binding the data to a PreparedStatement parameter you can prevent most SQL injection attacks. Any performance advantage of using Statements is negligible.”
Insomma, per i miei gusti, non c’è motivo di usare Statement e PreparedStatement è la classe vincente.





Il PreparedStatement è un po’ scomodo solo in fase di debug visto che non si ha la possibilità di sapere la query effettiva che viene mandata al DB dopo aver settato i vari parametri.
@ZeL
In fase di debug è possibile conoscere quanto inviato al server.
Esempio:
Logger log = Logger.getLogger(Esempio.class.getName());
String sql=”select * from TABELLA where 1=?”;
PreparedStatement statement = connection.prepareStatement(sql);
statement.setInt(1, 1);
log.debug(“statement”);
Esito:
statement
@teacher
log.debug(“statement[" + statement.toString() + "]“);
Esito:
statement[select * from TABELLA where 1=1]
Si, ora non so se dipenda dal particolare driver che uso di solito (hsqldb), ma l’output che genera è un po’ più verboso, del tipo:
org.hsqldb.jdbc.jdbcPreparedStatement@37bd2664[sql=[select * from TABELLA where 1=?], parameters=[[1]]]
Però certamente è il modo corretto di farne il debug e non è nulla di particolarmente preoccupante :-)